尺度不变特征核心是不同尺度拍摄的两幅图像的同一个物体,对应的两个theta比率等于拍摄两幅图像的尺度的比率。

而OpenCV提供的SIFT和Surf正是利用尺度不变性就行特征点检测的代表。它们的原理可以参考本文的参考文献,写的很详细,本来想在这里介绍下它们的原理的,但是看到参考的blog中写的太好了,我不能写的这么清楚,就省去了。

使用起来也很方便,比如利用Sift找到匹配物体代码如下:

int main(int argc, char** argv){Mat img_scene = imread("./box_in_scene.png", CV_LOAD_IMAGE_GRAYSCALE);Mat img_object = imread("./box.png", CV_LOAD_IMAGE_GRAYSCALE);if (!img_object.data || !img_scene.data){std::cout << " --(!) Error reading images " << std::endl; return -1;}std::vector<KeyPoint> keypoints_object, keypoints_scene;//-- Step 1: Detect the keypoints using SIFT DetectorPtr<FeatureDetector> detector = SiftFeatureDetector::create(400);detector->detect(img_object, keypoints_object);detector->detect(img_scene, keypoints_scene); //-- Step 2: Calculate descriptors (feature vectors)Ptr<DescriptorExtractor>  extractor = SiftDescriptorExtractor::create();Mat descriptors_object, descriptors_scene;extractor->compute(img_object, keypoints_object, descriptors_object);extractor->compute(img_scene, keypoints_scene, descriptors_scene);//-- Step 3: Matching descriptor vectors using FLANN matcherFlannBasedMatcher matcher;std::vector< DMatch > matches;matcher.match(descriptors_object, descriptors_scene, matches);double max_dist = 0; double min_dist = 100;//-- Quick calculation of max and min distances between keypointsfor (int i = 0; i < descriptors_object.rows; i++){double dist = matches[i].distance;if (dist < min_dist) min_dist = dist;if (dist > max_dist) max_dist = dist;}//-- Draw only "good" matches (i.e. whose distance is less than 3*min_dist )std::vector< DMatch > good_matches;for (int i = 0; i < descriptors_object.rows; i++){if (matches[i].distance < 3 * min_dist){good_matches.push_back(matches[i]);}}Mat img_matches;drawMatches(img_object, keypoints_object, img_scene, keypoints_scene,good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);//-- Localize the objectstd::vector<Point2f> obj;std::vector<Point2f> scene;for (int i = 0; i < good_matches.size(); i++){//-- Get the keypoints from the good matchesobj.push_back(keypoints_object[good_matches[i].queryIdx].pt);scene.push_back(keypoints_scene[good_matches[i].trainIdx].pt);}Mat H = findHomography(obj, scene, RANSAC);   //-- Get the corners from the image_1 ( the object to be "detected" )std::vector<Point2f> obj_corners(4);obj_corners[0] = Point(0, 0);obj_corners[1] = Point(img_object.cols, 0);obj_corners[2] = Point(img_object.cols, img_object.rows);obj_corners[3] = Point(0, img_object.rows);std::vector<Point2f> scene_corners(4);perspectiveTransform(obj_corners, scene_corners, H);//-- Draw lines between the corners (the mapped object in the scene - image_2  )line(img_matches, scene_corners[0] + Point2f(img_object.cols, 0),  scene_corners[1] + Point2f(img_object.cols, 0), Scalar(0, 255, 0), 4);line(img_matches, scene_corners[1] + Point2f(img_object.cols, 0),  scene_corners[2] + Point2f(img_object.cols, 0), Scalar(0, 255, 0), 4);line(img_matches, scene_corners[2] + Point2f(img_object.cols, 0),  scene_corners[3] + Point2f(img_object.cols, 0), Scalar(0, 255, 0), 4);line(img_matches, scene_corners[3] + Point2f(img_object.cols, 0),  scene_corners[0] + Point2f(img_object.cols, 0), Scalar(0, 255, 0), 4);//-- Show detected matchesimshow("Good Matches & Object detection", img_matches);waitKey(0);return 0;
}

结果如下:

如果用Surf只用把代码中的Sift换成Surf即可。研究Sift和Surf原理会发现,他们都会用到Hessian矩阵,而且Hessian矩阵的特征值大小和它两个方向的边缘强度有关,特征向量是它梯度方向即垂直于边缘方向。

注意DescriptorExtractor和FeatureDetector是一回事,可以直接给DescriptorExtractor赋值为FeatureDetector。

/** Feature detectors in OpenCV have wrappers with a common interface that enables you to easily switch
between different algorithms solving the same problem. All objects that implement keypoint detectors
inherit the FeatureDetector interface. */
typedef Feature2D FeatureDetector;
/** Extractors of keypoint descriptors in OpenCV have wrappers with a common interface that enables you
to easily switch between different algorithms solving the same problem. This section is devoted to
computing descriptors represented as vectors in a multidimensional space. All objects that implement
the vector descriptor extractors inherit the DescriptorExtractor interface.*/
typedef Feature2D DescriptorExtractor;

通过这一点我们可以得到启发,其实利用它的这一思想,可以进行边缘检测。

比如对下图进行边缘检测,因为整体对比度不高,我们先试试用Canny边缘检测。

Mat gray;
int low_threshold = 100;
const int max_threshold = 128;void canny_edge_detector(int, void*)
{Mat edge;Canny(gray, edge, low_threshold, 2 * low_threshold);imshow("canny detect", edge);
}int main(int argc, char** argv)
{Mat src = imread("./demo.png", CV_LOAD_IMAGE_COLOR);imshow("source image", src);cvtColor(src, gray, CV_BGR2GRAY);namedWindow("canny detect");createTrackbar("canny threshold", "canny detect", &low_threshold,  max_threshold, canny_edge_detector);canny_edge_detector(0, 0);waitKey(0);return 0;
}

结果如下:

在低阈值为100,高阈值为200时候,可以准确检测到白线的边缘,但是左侧边缘因为对比度低,丢失了,如果调整阈值,比较小的时候可以依稀看到左侧边缘,但是此时干扰太多,而且我们很难能够得到准确的阈值时多少,如果借助Hessian矩阵特征值,最大特征值是最小特征值的10倍以上,认为是边缘点(这个条件比较宽松,后续可以再改进)

int main(int argc, char** argv)
{Mat src = imread("./demo.png", CV_LOAD_IMAGE_COLOR);imshow("source image", src);Mat gray;cvtColor(src, gray, CV_BGR2GRAY);// 高斯滤波Mat filter;cv::GaussianBlur(gray, filter, cv::Size(3, 3), 1.1, 1.1);cv::GaussianBlur(filter, filter, cv::Size(3, 3), 1.1, 1.1);// 利用cornerEigenValsAndVecs计算Hessian矩阵特征值和特征向量Mat dst; Mat result = Mat::zeros(src.size(), CV_8UC1);cornerEigenValsAndVecs(filter, dst, 3, 3); // dst每一个元素是Vec6ffor (int r = 0; r < dst.rows; r++){for (int c = 0; c < dst.cols; c++){float lamda1 = dst.at<Vec6f>(r, c)[0];float lamda2 = dst.at<Vec6f>(r, c)[1];if (lamda1 == 0 || lamda2 == 0) continue;                 if (lamda1 > 10 * lamda2 || lamda2 > 10 * lamda1){result.at<uchar>(r, c) = 255;}}}// 数学形态学 腐蚀Mat  k1 = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));Mat  k2 = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));morphologyEx(result, result, MORPH_ERODE, k2, Point(-1, -1), 1);morphologyEx(result, result, MORPH_DILATE, k1, Point(-1, -1), 1);imshow("my edge detector", result);waitKey(0);return 0;
}

可以保留所有的边缘,后面再根据一些过滤条件,应该可以获取边缘信息。

参考:

《OpenCV计算机视觉编程攻略(第2版)》  [加] Robert 著   相银初 译

https://blog.csdn.net/zddblog/article/details/7521424

https://www.jianshu.com/p/db4bbe760d2e

http://www.doc88.com/p-6458994174161.html

OpenCV特征检测(三)SIFT,Surf及其引申的思考相关推荐

  1. opencv中的SIFT,SURF,ORB,FAST 特征描叙算子比较

    opencv中的SIFT,SURF,ORB,FAST 特征描叙算子比较 参考: http://wenku.baidu.com/link?url=1aDYAJBCrrK-uk2w3sSNai7h52x_ ...

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

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

  3. 图像特征检测描述:SIFT、SURF、ORB、HOG、LBP特征的原理概述

    版权声明:本文为博主原创文章,转载请标明原始博文地址: https://blog.csdn.net/yuanlulu/article/details/82148429 </div>< ...

  4. 三种强大的物体识别算法——SIFT/SURF、haar特征、广义hough变换的特性对比分析

    识别算法概述: SIFT/SURF基于灰度图, 一.首先建立图像金字塔,形成三维的图像空间,通过Hessian矩阵获取每一层的局部极大值,然后进行在极值点周围26个点进行NMS,从而得到粗略的特征点, ...

  5. linux/ubuntu下简单好用的python opencv安装教程 ( 解决 imshow, SIFT, SURF, CSRT使用问题)

    linux/ubuntu下简单好用的python opencv安装教程 ( 解决 imshow, SIFT, SURF, CSRT使用问题) 参考文章: (1)linux/ubuntu下简单好用的py ...

  6. OpenCV系列之SIFT尺度不变特征变换 | 三十九

    目标 在这一章当中, 我们将学习SIFT算法的概念 我们将学习找到SIFT关键点和描述算符. 理论 在前两章中,我们看到了一些像Harris这样的拐角检测器.它们是旋转不变的,这意味着即使图像旋转了, ...

  7. 【Python+OpenCV】主流特征点检测器和描述子总结与实现附拼接结果(SIFT,SURF,ORB,AKAZE,FAST,BRIEF,CenSurE,BEBLID,SuperPoint)

    文章目录 准备工作 SIFT SURF ORB AKAZE FAST与BRIEF CenSurE BEBLID 匹配点后的图像拼接 SuperPoint 总结 准备工作 先准备两张待处理的图像,要求有 ...

  8. 物体识别算法——SIFT/SURF、haar特征、广义hough变换的对比分析

    著作权归作者所有. 商业转载请联系作者获得授权,非商业转载请注明出处. 作者:cvvision 链接:http://www.cvvision.cn/7780.html 来源:CV视觉网 识别算法概述: ...

  9. SIFT,SURF,ORB,FAST 特征提取算法比较

    SIFT,SURF,ORB,FAST 特征提取算法比较 主要的特征检测方法有以下几种,在一般的图像处理库中(如OpenCV, VLFeat, Boofcv等)都会实现. FAST ,Machine L ...

最新文章

  1. 激动~这是我看到的最好的目标检测RCNN了!
  2. Spring Boot 整合 Freemarker
  3. PPT讲解机器人产业发展现状与未来展望,重磅资料
  4. LINUX CentOS7安装字体库
  5. 6月统计|.NET薪资一旦高起来,岂是其他语言能比的!
  6. python 代理服务器_Python实现HTTP代理服务器
  7. 关于UNIX功能测试宏
  8. 你那不是拖延症,只是习惯性逃避
  9. C++ Struct和Union区别
  10. sqlserver备份还原丢失dbo_sqlserver数据库的备份与恢复sql实现
  11. 水经注地图发布服务中间件的适用范围
  12. IDEA添加快捷输入
  13. aabResGuard使用
  14. 软件推荐:强力卸载软件HIBIT
  15. Facebook 企业广告账户开户流程、资料准备、开户时间、开户须知及OE链接
  16. WPF在mxs里引用图片资源并释放的方法
  17. 《nodejs+gulp+webpack基础实战篇》课程笔记(六)--附加课
  18. 大咖说·图书分享|了不起的JavaScript工程师:从前端到全端高级进阶
  19. Zigbee(E18-MS1-PCB)使用记录
  20. springboot 快速启动(十二)——发送短信

热门文章

  1. rhel系统启动过程_技术|Linux 开机引导和启动过程详解
  2. 教师在家长群内表扬配合家长的话术
  3. windows服务器直播推流
  4. 毕业设计-校园招聘系统
  5. conda安装python虚拟环境+配置channels
  6. 正则表达式(regex,RE)
  7. 【微信小程序】-- 全局配置 -- window - 下拉刷新 上拉触底(十六)
  8. Zabbix 5.0 监控教程(一)
  9. http报错405问题解决方法
  10. 谷歌今年在中国新招200人 应届毕业生占50%