Opencv(C++)学习系列---特征点检测和匹配

简介: Opencv(C++)学习系列---特征点检测和匹配

关于特征检测和匹配的具体原理会在后续的文章中具体讲解,本文主要介绍Opencv实现的简单过程:

第一步:定义特征检测器(SIFT,SURF,ORB等)。

第二步:对图像中特征点进行检测,并将特征点存储在Keypoints中。

第三步:提取特征点的描述信息。

第四步:定义特征匹配器(特征匹配的方法主要有两种分别为暴力匹配BFmatch和FlannBased)。

第五步:过滤掉较差的匹配点位(一般根据临近两点的距离进行过滤)

主要是根据DMatch中的distance进行过滤,对于distance可以抽象理解为匹配的分值,distance越小说明检测点的相似度越高,效果越好。

第六步:对匹配的特征点显示。

代码1(未滤波,只限制筛选点数为20)

#include <iostream>
#include <opencv2/opencv.hpp>  
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>
#include <opencv2/xfeatures2d.hpp>
using namespace cv;  //包含cv命名空间
using namespace std;
using namespace xfeatures2d;
int main() {
  system("color 2E");
  //载入图片
  Mat src1 = imread("E:\\乔大花进度\\11-18\\sift特征检测和匹配\\3.jpg",1);
  Mat src2 = imread("E:\\乔大花进度\\11-18\\sift特征检测和匹配\\4.jpg", 1);
  //显示原图
  imshow("原图1",src1);
  imshow("原图2", src2);
  //定义变量
  vector<KeyPoint> keypoints1, keypoints2;//定义检测的特征点存储容器
  Mat descriptors1,descriptors2;//定义特征点描述信息为Mat类型
  Mat result_img;//匹配结果图片
  //创建sift特征检测器实例
  //将SIFT可以换位SURF、ORB
  Ptr<SIFT>detector = SIFT::create();
  //提取特征点
  detector->detect(src1,keypoints1,noArray());
  detector->detect(src2, keypoints2, Mat());
  //获取特征点的描述信息=>特征向量
  detector->compute(src1,keypoints1,descriptors1);
  detector->compute(src2, keypoints2, descriptors2);
  //定义匹配器的实例化=>方法为暴力匹配法
  Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create(DescriptorMatcher::BRUTEFORCE);//create中的参数可以填string FlannBased等匹配方法
  //第二种实例化方法
  //BFMatcher matcher;
  //进行暴力匹配
  vector<DMatch> matches;
  //第一个参数为queryDescription为目标,第二个参数为trainDescription模板
  matcher->match(descriptors1,descriptors2,matches);
  //限制特征点匹配数量=》只匹配前20个较好的特征点
  int num = 20;
  nth_element(matches.begin(), matches.begin()+num,matches.end());
  //vector去除20以后的元素
  matches.erase(matches.begin()+num,matches.end());
  
  //输出关键点和匹配结果
  //其中右侧图为trainDescription模板,左侧图为queryDescription目标
  //左图中的点与右图中进行匹配对应
  drawMatches(src1,keypoints1,src2,keypoints2, matches,result_img);
  drawKeypoints(src1,keypoints1,src1);
  drawKeypoints(src2,keypoints2,src2);
  
  imshow("匹配结果",result_img);
  imshow("特征点1",src1);
  imshow("特征点2",src2);
  waitKey(0);
  system("pause");
  return 0;
}

运行结果为:

代码2(通过距离进行滤波)

#include <iostream>
#include <opencv2/opencv.hpp>  
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>
#include <opencv2/xfeatures2d.hpp>
using namespace cv;  //包含cv命名空间
using namespace std;
using namespace xfeatures2d;
int main() {
  system("color 2E");
  //载入图片
  Mat src1 = imread("E:\\乔大花进度\\11-18\\sift特征检测和匹配\\3.jpg",1);
  Mat src2 = imread("E:\\乔大花进度\\11-18\\sift特征检测和匹配\\4.jpg", 1);
  //显示原图
  imshow("原图1",src1);
  imshow("原图2", src2);
  //定义变量
  vector<KeyPoint> keypoints1, keypoints2;//定义检测的特征点存储容器
  Mat descriptors1,descriptors2;//定义特征点描述信息为Mat类型
  Mat result_img;//匹配结果图片
  //创建sift特征检测器实例
  //将SIFT可以换位SURF、ORB
  Ptr<SIFT>detector = SIFT::create();
  //提取特征点
  detector->detect(src1,keypoints1,noArray());
  detector->detect(src2, keypoints2, Mat());
  //获取特征点的描述信息=>特征向量
  detector->compute(src1,keypoints1,descriptors1);
  detector->compute(src2, keypoints2, descriptors2);
  //定义匹配器的实例化=>方法为暴力匹配法
  Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create(DescriptorMatcher::BRUTEFORCE);//create中的参数可以填string FlannBased等匹配方法
  //第二种实例化方法
  //BFMatcher matcher;
  //进行暴力匹配
  vector<DMatch> matches;
  //第一个参数为queryDescription为目标,第二个参数为trainDescription模板
  matcher->match(descriptors1,descriptors2,matches);
  //限制特征点匹配数量=》只匹配前20个较好的特征点
  int num = 20;
  nth_element(matches.begin(), matches.begin()+num,matches.end());
  //vector去除20以后的元素
  matches.erase(matches.begin()+num,matches.end());
  
  double Max_distance = matches[1].distance;
  double Min_distance = matches[1].distance;
  vector<DMatch> goodfeatrues;
  
  //根据特征点的距离去筛选
  for (int i = 0; i < matches.size(); i++)
  {
    double dist = matches[i].distance;
    if (dist>Max_distance)
    {
      Max_distance = dist;
    }
    if (dist<Min_distance)
    {
      Min_distance = dist;
    }
    
  }
  cout << "匹配点的最大距离:" << Max_distance << endl;
  cout << "匹配点的最小距离:" << Min_distance << endl;
  //M为距离阈值,M越大点数越多
  double M = 1.3;
  for (int  i = 0; i < matches.size(); i++)
  {
    double dist = matches[i].distance;
    if (dist<M*Min_distance)    {
      goodfeatrues.push_back(matches[i]);
    }
  }
  cout << "最终选取特征点的数量为:" << matches.size() << endl;
  //输出关键点和匹配结果
  //其中右侧图为trainDescription模板,左侧图为queryDescription目标
  //左图中的点与右图中进行匹配对应
  drawMatches(src1,keypoints1,src2,keypoints2, goodfeatrues,result_img);
  drawKeypoints(src1,keypoints1,src1);
  drawKeypoints(src2,keypoints2,src2);
  
  imshow("匹配结果",result_img);
  imshow("特征点1",src1);
  imshow("特征点2",src2);
  waitKey(0);
  system("pause");
  return 0;
}

运行结果为:

代码3(通过knnMatch匹配,可以通过对distance设置阈值进行滤波,效果最好)

#include <iostream>
#include <opencv2/opencv.hpp>  
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>
#include <opencv2/xfeatures2d.hpp>
using namespace cv;  //包含cv命名空间
using namespace std;
using namespace xfeatures2d;
int main() {
  system("color 2E");
  //载入图片
  Mat src1 = imread("E:\\乔大花进度\\11-18\\sift特征检测和匹配\\3.jpg",1);
  Mat src2 = imread("E:\\乔大花进度\\11-18\\sift特征检测和匹配\\4.jpg", 1);
  //显示原图
  imshow("原图1",src1);
  imshow("原图2", src2);
  //定义变量
  vector<KeyPoint> keypoints1, keypoints2;//定义检测的特征点存储容器
  Mat descriptors1,descriptors2;//定义特征点描述信息为Mat类型
  Mat result_img;//匹配结果图片
  //创建sift特征检测器实例
  //将SIFT可以换位SURF、ORB
  Ptr<SIFT>detector = SIFT::create();
  //提取特征点
  detector->detect(src1,keypoints1,noArray());
  detector->detect(src2, keypoints2, Mat());
  //获取特征点的描述信息=>特征向量
  detector->compute(src1,keypoints1,descriptors1);
  detector->compute(src2, keypoints2, descriptors2);
  //定义匹配器的实例化=>方法为暴力匹配法
  Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create(DescriptorMatcher::BRUTEFORCE);//create中的参数可以填string FlannBased等匹配方法
  //第二种实例化方法
  //BFMatcher matcher;
  //进行暴力匹配
  vector<DMatch> matches;
  vector<Mat>train_desc(1, descriptors2);
  matcher->add(train_desc);
  matcher->train();
  vector<vector<DMatch>> matchpoints;
  matcher->knnMatch(descriptors1,matchpoints,2);
  vector<DMatch> goodfeatur;
  for (int i = 0; i < matchpoints.size(); i++)
  {
    if (matchpoints[i][0].distance<0.15*matchpoints[i][1].distance)
    {
      goodfeatur.push_back(matchpoints[i][0]);
    }
  }
  cout << "筛选后的特征点数量为: " << goodfeatur.size() << endl;
  //输出关键点和匹配结果
  //其中右侧图为trainDescription模板,左侧图为queryDescription目标
  //左图中的点与右图中进行匹配对应
  drawMatches(src1,keypoints1,src2,keypoints2, goodfeatur,result_img);
  drawKeypoints(src1,keypoints1,src1);
  drawKeypoints(src2,keypoints2,src2);
  
  namedWindow("匹配结果",WINDOW_NORMAL);
  resizeWindow("匹配结果",500,500);
  imshow("匹配结果",result_img);
  waitKey(0);
  system("pause");
  return 0;
}

运行结果为:

相关文章
|
3月前
|
计算机视觉
Opencv学习笔记(八):如何通过cv2读取视频和摄像头来进行人脸检测(jetson nano)
如何使用OpenCV库通过cv2模块读取视频和摄像头进行人脸检测,并提供了相应的代码示例。
150 1
|
3月前
|
机器学习/深度学习 计算机视觉
目标检测笔记(六):如何结合特定区域进行目标检测(基于OpenCV的人脸检测实例)
本文介绍了如何使用OpenCV进行特定区域的目标检测,包括人脸检测实例,展示了两种实现方法和相应的代码。
102 1
目标检测笔记(六):如何结合特定区域进行目标检测(基于OpenCV的人脸检测实例)
|
7月前
|
算法 开发工具 计算机视觉
【零代码研发】OpenCV实验大师工作流引擎C++ SDK演示
【零代码研发】OpenCV实验大师工作流引擎C++ SDK演示
103 1
|
3月前
|
Ubuntu Linux 编译器
Linux/Ubuntu下使用VS Code配置C/C++项目环境调用OpenCV
通过以上步骤,您已经成功在Ubuntu系统下的VS Code中配置了C/C++项目环境,并能够调用OpenCV库进行开发。请确保每一步都按照您的系统实际情况进行适当调整。
790 3
|
4月前
|
存储 计算机视觉 C++
在C++中实现Armadillo库与OpenCV库之间的数据格式转换
在C++中实现Armadillo库与OpenCV库之间的数据格式转换是一项常见且实用的技能。上述步骤提供了一种标准的方法来进行这种转换,可以帮助开发者在两个库之间高效地转移和处理数据。虽然转换过程相对直接,但开发者应留意数据类型匹配和性能优化等关键细节。
73 11
|
3月前
|
算法 计算机视觉 Python
圆形检测算法-基于颜色和形状(opencv)
该代码实现了一个圆检测算法,用于识别视频中的红色、白色和蓝色圆形。通过将图像从RGB转换为HSV颜色空间,并设置对应颜色的阈值范围,提取出目标颜色的区域。接着对这些区域进行轮廓提取和面积筛选,使用霍夫圆变换检测圆形,并在原图上绘制检测结果。
108 0
|
4月前
|
存储 计算机视觉 C++
在C++中实现Armadillo库与OpenCV库之间的数据格式转换
在C++中实现Armadillo库与OpenCV库之间的数据格式转换是一项常见且实用的技能。上述步骤提供了一种标准的方法来进行这种转换,可以帮助开发者在两个库之间高效地转移和处理数据。虽然转换过程相对直接,但开发者应留意数据类型匹配和性能优化等关键细节。
40 3
|
6月前
|
机器学习/深度学习 传感器 算法
OpenCV4工业缺陷检测的六种方法
OpenCV4工业缺陷检测的六种方法
|
7月前
|
机器学习/深度学习 人工智能 自然语言处理
OpenCV与AI深度学习之常用AI名词解释学习
AGI:Artificial General Intelligence (通用人工智能):是指具备与人类同等或超越人类的智能,能够表现出正常人类所具有的所有智能行为。又被称为强人工智能。
143 2
|
7月前
|
存储 编解码 算法
【Qt&OpenCV 检测图像中的线/圆/轮廓 HoughLinesP/HoughCircles/findContours&drawContours】
【Qt&OpenCV 检测图像中的线/圆/轮廓 HoughLinesP/HoughCircles/findContours&drawContours】
124 0