SURF原理详解:https://wenku.baidu.com/view/2f1e4d8ef705cc1754270945.html

SURF算法工作原理

  1. 选择图像中的POI(Points of interest) Hessian Matrix

  2. 在不同的尺度空间发现关键点,非最大信号压制

  3. 发现特征点方法、旋转不变性要求

  4. 生成特征向量

SURF构造函数介绍

C++:  SURF::SURF(

double hessianThreshold, --阈值检测器使用Hessian的关键点,默认值在

300-500之间

int nOctaves=4,                 -- 4表示在四个尺度空间

int nOctaveLayers=2,        -- 表示每个尺度的层数

bool extended=false,

bool upright=false              --表示计算旋转不变性,不计算的速度更快

)

特征点绘制

特征点绘制是为了把检测出来的Surf特征点在原图上绘制出来,这一步是为了把特征点直观的显示出来给我们看,跟整个Surf算子的特征提取和匹配流程没关系。

绘制使用drawKeypoints方法:

void drawKeypoints( const Mat& image,const vector<KeyPoint>& keypoints,CV_OUT Mat& outImage,const Scalar& color=Scalar::all(-1),int flags=DrawMatchesFlags::DEFAULT
);

第一个参数image:原始图像,可以使三通道或单通道图像;

第二个参数keypoints:特征点向量,向量内每一个元素是一个KeyPoint对象,包含了特征点的各种属性信息;

第三个参数outImage:特征点绘制的画布图像,可以是原图像;

第四个参数color:绘制的特征点的颜色信息,默认绘制的是随机彩色;

第五个参数flags:特征点的绘制模式,其实就是设置特征点的那些信息需要绘制,那些不需要绘制,有以下几种模式可选:

  DEFAULT:只绘制特征点的坐标点,显示在图像上就是一个个小圆点,每个小圆点的圆心坐标都是特征点的坐标。
  DRAW_OVER_OUTIMG:函数不创建输出的图像,而是直接在输出图像变量空间绘制,要求本身输出图像变量就是一个初始化好了的,size与type都是已经初始化好的变量
  NOT_DRAW_SINGLE_POINTS:单点的特征点不被绘制
  DRAW_RICH_KEYPOINTS:绘制特征点的时候绘制的是一个个带有方向的圆,这种方法同时显示图像的坐标,size,和方向,是最能显示特征信息的一种绘制方式。

 1 #include <opencv2/opencv.hpp>
 2 #include <opencv2/xfeatures2d.hpp>
 3 #include <iostream>
 4
 5 using namespace cv;
 6 using namespace cv::xfeatures2d;
 7 using namespace std;
 8
 9 int main(int argc, char** argv) {
10     Mat src = imread("test.jpg", IMREAD_GRAYSCALE);
11     if (src.empty()) {
12         printf("could not load image...\n");
13         return -1;
14     }
15     namedWindow("input image", CV_WINDOW_AUTOSIZE);
16     imshow("input image", src);
17
18     // SURF特征点检测
19     int minHessian = 100;
20     Ptr<SURF> detector = SURF::create(minHessian);//创建一个surf类对象并初始化
21     vector<KeyPoint> keypoints;
22     detector->detect(src, keypoints, Mat());//找出关键点
23
24     // 绘制关键点
25     Mat keypoint_img;
26     drawKeypoints(src, keypoints, keypoint_img, Scalar::all(-1), DrawMatchesFlags::DEFAULT);
27     imshow("KeyPoints Image", keypoint_img);
28
29     waitKey(0);
30     return 0;
31 }

绘制匹配点

drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1,const Mat& img2, const vector<KeyPoint>& keypoints2,const vector<DMatch>& matches1to2, Mat& outImg,const Scalar& matchColor=Scalar::all(-1), const Scalar& singlePointColor=Scalar::all(-1),const vector<char>& matchesMask=vector<char>(), int flags=DrawMatchesFlags::DEFAULT );

其中参数如下:

* img1 – 源图像1

* keypoints1 –源图像1的特征点.

* img2 – 源图像2.

* keypoints2 – 源图像2的特征点

* matches1to2 – 源图像1的特征点匹配源图像2的特征点[matches[i]] .

* outImg – 输出图像具体由flags决定.

* matchColor – 匹配的颜色(特征点和连线),若matchColor==Scalar::all(-1),颜色随机.

* singlePointColor – 单个点的颜色,即未配对的特征点,若matchColor==Scalar::all(-1),颜色随机.

*matchesMask – Mask决定哪些点将被画出,若为空,则画出所有匹配点.

*flags—它跟drawKeypoints方法中flags的含义是一样的。

当仅使用筛选出的最优匹配点进行匹配的时候,意味着会有很多非最优的特征点不会被匹配,这时候可以设置flags=DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS

BF(暴力)匹配(src目标图,temp需要查找的背景图)

 1 #include <opencv2/opencv.hpp>
 2 #include <opencv2/xfeatures2d.hpp>
 3 #include <iostream>
 4
 5 using namespace cv;
 6 using namespace cv::xfeatures2d;
 7 using namespace std;
 8
 9 int main(int argc, char** argv) {
10     Mat src = imread("数字.jpg");
11     Mat temp = imread("2.png");
12     if (src.empty() || temp.empty()) {
13         printf("could not load image...\n");
14         return -1;
15     }
16     namedWindow("input image", CV_WINDOW_AUTOSIZE);
17     imshow("input image", src);
18
19     // SURF特征点检测
20     int minHessian = 400;
21     Ptr<SURF> detector = SURF::create(minHessian, 4, 3, true, true);//创建一个surf类检测器对象并初始化
22     vector<KeyPoint> keypoints1, keypoints2;
23     Mat src_vector, temp_vector;//用来存放特征点的描述向量
24
25     //detector->detect(src, keypoints1, Mat());//找出关键点
26     //detector->detect(temp, keypoints2, Mat());//找出关键点
27
28     //找到特征点并计算特征描述子(向量)
29     detector->detectAndCompute(src, Mat(), keypoints1, src_vector);//输入图像,输入掩码,输入特征点,输出Mat,存放所有特征点的描述向量
30     detector->detectAndCompute(temp, Mat(), keypoints2, temp_vector);//这个Mat行数为特征点的个数,列数为每个特征向量的尺寸,SURF是64(维)
31
32
33     //匹配
34     BFMatcher matcher(NORM_L2);         //实例化一个暴力匹配器(括号里可以选择匹配方法)
35
36     vector<DMatch> matches;    //DMatch是用来描述匹配好的一对特征点的类,包含这两个点之间的匹配信息
37                                //比如左图有个特征m,它和右图的特征点n最匹配,这个DMatch就记录它俩最匹配,并且还记录m和n的
38                                //特征向量的距离和其他信息,这个距离在后面用来做筛选
39
40     matcher.match(src_vector, temp_vector, matches);             //匹配,数据来源是特征向量,结果存放在DMatch类型里面
41
42     //匹配点筛选
43     //sort函数对数据进行升序排列
44     //筛选匹配点,根据match里面特征对的距离从小到大排序
45     //筛选出最优的30个匹配点(可以不使用,会画出所有特征点)
46
47     sort(matches.begin(), matches.end());
48     vector< DMatch > good_matches;
49     int ptsPairs = std::min(30, (int)(matches.size() * 0.15));//匹配点数量不大于50
50     cout << ptsPairs << endl;
51     for (int i = 0; i < ptsPairs; i++)
52     {
53         good_matches.push_back(matches[i]);//距离最小的50个压入新的DMatch
54     }
55
56
57     Mat MatchesImage;                                //drawMatches这个函数直接画出摆在一起的图
58     drawMatches(src, keypoints1, temp, keypoints2, good_matches, MatchesImage, Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);  //绘制匹配点
59     imshow("BFMatcher Image", MatchesImage);
60
61     waitKey(0);
62     return 0;
63 }

FLANN匹配

 1 #include <opencv2/opencv.hpp>
 2 #include <opencv2/xfeatures2d.hpp>
 3 #include <iostream>
 4 #include <math.h>
 5
 6 using namespace cv;
 7 using namespace cv::xfeatures2d;
 8 using namespace std;
 9
10 int main(int argc, char** argv) {
11     Mat src = imread("数字.jpg",0);
12     Mat temp = imread("2.png",0);
13     if (src.empty() || temp.empty()) {
14         printf("could not load image...\n");
15         return -1;
16     }
17     namedWindow("input image", CV_WINDOW_AUTOSIZE);
18     imshow("input image", src);
19
20     // SURF特征点检测
21     int minHessian = 400;
22     Ptr<SURF> detector = SURF::create(minHessian, 4, 3, true, true);//创建一个surf类检测器对象并初始化
23     vector<KeyPoint> keypoints1, keypoints2;
24     Mat src_vector, temp_vector;//用来存放特征点的描述向量
25
26     //detector->detect(src, keypoints1, Mat());//找出关键点
27     //detector->detect(temp, keypoints2, Mat());//找出关键点
28
29     //找到特征点并计算特征描述子(向量)
30     detector->detectAndCompute(src, Mat(), keypoints1, src_vector);//输入图像,输入掩码,输入特征点,输出Mat,存放所有特征点的描述向量
31     detector->detectAndCompute(temp, Mat(), keypoints2, temp_vector);//这个Mat行数为特征点的个数,列数为每个特征向量的尺寸,SURF是64(维)
32
33
34     //匹配
35     FlannBasedMatcher matcher;         //实例化一个FLANN匹配器(括号里可以选择匹配方法)
36
37     vector<DMatch> matches;    //DMatch是用来描述匹配好的一对特征点的类,包含这两个点之间的匹配信息
38                                //比如左图有个特征m,它和右图的特征点n最匹配,这个DMatch就记录它俩最匹配,并且还记录m和n的
39                                //特征向量的距离和其他信息,这个距离在后面用来做筛选
40
41     matcher.match(src_vector, temp_vector, matches);             //匹配,数据来源是特征向量,结果存放在DMatch类型里面
42
43     //求最小最大距离
44     double minDistance = 1000;//反向逼近
45     double maxDistance = 0;
46     for (int i=0; i< src_vector.rows; i++) {
47         double distance = matches[i].distance;
48         if (distance > maxDistance)        {
49             maxDistance = distance;
50         }
51         if (distance < minDistance)        {
52             minDistance = distance;
53         }
54     }
55     printf("max distance : %f\n", maxDistance);
56     printf("min distance : %f\n", minDistance);
57
58     //筛选较好的匹配点
59     vector< DMatch > good_matches;
60     for (int i = 0; i < src_vector.rows; i++) {
61         double distance = matches[i].distance;
62         if (distance < max(minDistance * 2, 0.02)) {
63             good_matches.push_back(matches[i]);//距离小于范围的压入新的DMatch
64         }
65     }
66
67     /*//sort函数对数据进行升序排列
68     //筛选匹配点,根据match里面特征对的距离从小到大排序
69     //筛选出最优的50个匹配点(可以不使用,会画出所有特征点)
70
71     sort(matches.begin(), matches.end());
72     vector< DMatch > good_matches;
73     int ptsPairs = std::min(50, (int)(matches.size() * 0.15));//匹配点数量不大于50
74     cout << ptsPairs << endl;
75     for (int i = 0; i < ptsPairs; i++)
76     {
77         good_matches.push_back(matches[i]);//距离最小的50个压入新的DMatch
78     }
79     */
80
81     Mat MatchesImage;                                //drawMatches这个函数直接画出摆在一起的图
82     drawMatches(src, keypoints1, temp, keypoints2, good_matches, MatchesImage, Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);  //绘制匹配点
83     imshow("FLANN Image", MatchesImage);
84
85     waitKey(0);
86     return 0;
87 }

对象查找

  1 #include <opencv2/opencv.hpp>
  2 #include <opencv2/xfeatures2d.hpp>
  3 #include <iostream>
  4 #include <math.h>
  5
  6 using namespace cv;
  7 using namespace cv::xfeatures2d;
  8 using namespace std;
  9
 10 int main(int argc, char** argv) {
 11     Mat src = imread("fire_5.jpg");
 12     Mat temp = imread("数字.jpg");
 13     if (src.empty() || temp.empty()) {
 14         printf("could not load image...\n");
 15         return -1;
 16     }
 17     namedWindow("input image", CV_WINDOW_AUTOSIZE);
 18     imshow("input image", src);
 19
 20     // SURF特征点检测
 21     int minHessian = 400;
 22     Ptr<SURF> detector = SURF::create(minHessian, 4, 3, true, true);//创建一个surf类检测器对象并初始化
 23     vector<KeyPoint> keypoints1, keypoints2;
 24     Mat src_vector, temp_vector;//用来存放特征点的描述向量
 25
 26     //detector->detect(src, keypoints1, Mat());//找出关键点
 27     //detector->detect(temp, keypoints2, Mat());//找出关键点
 28
 29     //找到特征点并计算特征描述子(向量)
 30     detector->detectAndCompute(src, Mat(), keypoints1, src_vector);//输入图像,输入掩码,输入特征点,输出Mat,存放所有特征点的描述向量
 31     detector->detectAndCompute(temp, Mat(), keypoints2, temp_vector);//这个Mat行数为特征点的个数,列数为每个特征向量的尺寸,SURF是64(维)
 32
 33
 34     //匹配
 35     FlannBasedMatcher matcher;         //实例化一个FLANN匹配器(括号里可以选择匹配方法)
 36
 37     vector<DMatch> matches;    //DMatch是用来描述匹配好的一对特征点的类,包含这两个点之间的匹配信息
 38                                //比如左图有个特征m,它和右图的特征点n最匹配,这个DMatch就记录它俩最匹配,并且还记录m和n的
 39                                //特征向量的距离和其他信息,这个距离在后面用来做筛选
 40
 41     matcher.match(src_vector, temp_vector, matches);             //匹配,数据来源是特征向量,结果存放在DMatch类型里面
 42
 43     //求最小最大距离
 44     double minDistance = 1000;//反向逼近
 45     double maxDistance = 0;
 46     for (int i = 0; i < src_vector.rows; i++) {
 47         double distance = matches[i].distance;
 48         if (distance > maxDistance) {
 49             maxDistance = distance;
 50         }
 51         if (distance < minDistance) {
 52             minDistance = distance;
 53         }
 54     }
 55     printf("max distance : %f\n", maxDistance);
 56     printf("min distance : %f\n", minDistance);
 57
 58     //筛选较好的匹配点
 59     vector< DMatch > good_matches;
 60     for (int i = 0; i < src_vector.rows; i++) {
 61         double distance = matches[i].distance;
 62         if (distance < max(minDistance * 3, 0.02)) {
 63             good_matches.push_back(matches[i]);//距离小于范围的压入新的DMatch
 64         }
 65     }
 66
 67
 68     Mat MatchesImage;                                //drawMatches这个函数直接画出摆在一起的图
 69     drawMatches(src, keypoints1, temp, keypoints2, good_matches, MatchesImage, Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);  //绘制匹配点
 70
 71
 72     vector<Point2f> obj;
 73     vector<Point2f> objInScene;
 74     for (size_t t = 0; t < good_matches.size(); t++) {
 75         obj.push_back(keypoints1[good_matches[t].queryIdx].pt);//返回对象在模板图特征点坐标
 76         objInScene.push_back(keypoints2[good_matches[t].trainIdx].pt);//返回对象在背景查找图的坐标
 77     }
 78
 79     Mat H = findHomography(obj,objInScene,RANSAC);//计算透视变换矩阵
 80
 81     vector<Point2f> obj_corner(4);
 82     vector<Point2f> scene_corner(4);
 83     obj_corner[0] = Point(0, 0);
 84     obj_corner[1] = Point(src.cols, 0);
 85     obj_corner[2] = Point(src.cols,src.rows);
 86     obj_corner[3] = Point(0, src.rows);
 87
 88     perspectiveTransform(obj_corner, scene_corner,H);//透视变换
 89
 90     //画出边框线
 91     line(MatchesImage, scene_corner[0] + Point2f(src.cols, 0), scene_corner[1] + Point2f(src.cols, 0), Scalar(0, 0, 255), 2, 8, 0);
 92     line(MatchesImage, scene_corner[1] + Point2f(src.cols, 0), scene_corner[2] + Point2f(src.cols, 0), Scalar(0, 0, 255), 2, 8, 0);
 93     line(MatchesImage, scene_corner[2] + Point2f(src.cols, 0), scene_corner[3] + Point2f(src.cols, 0), Scalar(0, 0, 255), 2, 8, 0);
 94     line(MatchesImage, scene_corner[3] + Point2f(src.cols, 0), scene_corner[0] + Point2f(src.cols, 0), Scalar(0, 0, 255), 2, 8, 0);
 95     imshow("FLANN Image", MatchesImage);
 96
 97     line(temp, scene_corner[0], scene_corner[1], Scalar(0, 0, 255), 2, 8, 0);
 98     line(temp, scene_corner[1], scene_corner[2], Scalar(0, 0, 255), 2, 8, 0);
 99     line(temp, scene_corner[2], scene_corner[3], Scalar(0, 0, 255), 2, 8, 0);
100     line(temp, scene_corner[3], scene_corner[0], Scalar(0, 0, 255), 2, 8, 0);
101     imshow("temp Image", temp);
102
103     waitKey(0);
104     return 0;
105 }

转载于:https://www.cnblogs.com/long5683/p/9692987.html

OpenCV——SURF特征检测、匹配与对象查找相关推荐

  1. OpenCV SURF FLANN匹配单应性的实例(附完整代码)

    OpenCV SURF FLANN匹配单应性的实例 OpenCV SURF FLANN匹配单应性的实例 OpenCV SURF FLANN匹配单应性的实例 #include <iostream& ...

  2. OpenCV SURF FLANN匹配的实例(附完整代码)

    OpenCV SURF FLANN匹配的实例 OpenCV SURF FLANN匹配的实例 OpenCV SURF FLANN匹配的实例 #include <iostream> #incl ...

  3. OpenCV中的SURF特征检测、匹配与对象查找

    SURF算法工作原理 选择图像中的POI(Points of interest) Hessian Matrix 在不同的尺度空间发现关键点,非最大信号压制 发现特征点方法.旋转不变性要求 生成特征向量 ...

  4. OpenCV特征检测,角检测,特征点检测,特征匹配,对象查找

    特征检测 图像的特征是指图像中具有独特性和易于识别性的区域,角.边缘等都属于有意义的特征. 8.1角检测 角是两条边的交点,也可称为角点或拐角,它是图像中各个方向上强度变化最大的区域. OpenCV的 ...

  5. OpenCV——KAZE、AKAZE特征检测、匹配与对象查找

      AKAZE是KAZE的加速版 特征点查找和绘制:把surf中的surf改成KAZE或AKAZE即可 1 #include <opencv2/opencv.hpp> 2 #include ...

  6. OpenCV + CPP 系列(卅五)图像特征提取(SURF特征检测、SIFT特征检测)

    文章目录 一.SIFT特征检测 二.SURF特征检测 演示SURF.SIFT特征检测 OpenCV-python 角点特征检测之二(SIFT.SURF.ORB) 一.SIFT特征检测 SIFT(Sca ...

  7. 【OpenCV-Python】——哈里斯/Shi-Tomas角检测FAST/SIFT/ORB特征点检测暴力/FLANN匹配器对象查找

    目录 前言: 1.角检测 1.1 哈里斯角检测 1.2 优化哈里斯角 1.3 Shi-Tomasi角检测 2.特征点检测 2.1 FAST特征点检测 2.2 SIFT特征检测 2.3 ORB特征检测 ...

  8. 利用SURF特征检测和FLANN最近邻算法实现图像的目标提取

    图像处理开发需求.图像处理接私活挣零花钱,请加微信/QQ 2487872782 图像处理开发资料.图像处理技术交流请加QQ群,群号 271891601 标题中提到的方法的具体应用场景如下: ⑴以图搜图 ...

  9. 使用Python,OpenCV检测摄像机到标记对象的距离

    使用Python,OpenCV检测摄像机到标记对象的距离 1. 效果图 2. 三角形相似性是什么? 3. 三角形相似性检测距离原理 4. 使用Python,OpenCV检测标记对象 5. 源码 参考 ...

  10. opencv3/C++ SURF特征检测

    SURF即Speeded Up Robust Features加速鲁棒特征: SURF可以用于对象定位和识别.人脸识别.3D重建.对象跟踪和提取兴趣点等. 工作原理: 1.选择图像中POI(Point ...

最新文章

  1. 初识java反射机制
  2. Windows Phone 开发起步之旅之二 C#中的值类型和引用类型
  3. NET Core 3.0 AutoFac替换内置DI的新姿势
  4. 请移步到我的新浪博客
  5. 华为mstp多生成树配置_MSTP多区域生成树协议配置举例
  6. 别说我不告诉你,如此养车包你把自己也养穷了……
  7. 《人月神话》——一部被名字误导的软件开发的书——第一次阅读
  8. 求求你,别再叫我 X 工了!!!
  9. webrtc学习———记录三:mediaStreamTrack
  10. 例2.2 成绩排序 - 九度教程第2题(排序)
  11. 人之间的尊重是相互的_人和人之间,尊重永远是相互的,是礼貌,是美德,更是善良的表现...
  12. 飞秋常见文件解决方案
  13. DS1302时钟基础使用(含代码)
  14. word文档怎么压缩,word文档压缩方法
  15. 2017版张宇1000题【题目收集】
  16. R可视化绘图二-ggplot2
  17. Rational rose安装步骤
  18. PS小知识(二)——画固定大小的形状
  19. 计算机桌面变蓝屏,电脑进入桌面蓝屏解决方法
  20. DPU芯片头部企业云豹智能加入龙蜥社区,共同推动新一代数据中心基础设施蓬勃发展

热门文章

  1. go语言应用知识:-1-输入项目信息,获取相应内容打印
  2. 帆软报表嵌套在iframe中,HTML的fieldset 定义的为自定义导出按钮
  3. FR决策表单JS实现自动滚屏/滚动效果
  4. coco 数据集_PyTorch版YOLOv4更新了,适用于自定义数据集
  5. python字符串的删除操作_学习快人一步|python中常见的27个字符串操作
  6. antdesign 所兼容的浏览器_React爬坑之路——Antd兼容IE
  7. CS224N笔记——RNN和语言模型
  8. [CF592D]Super M
  9. 最长不下降子序列//序列dp
  10. vagrant 错误记录