点击上方“3D视觉工坊”,选择“星标”

干货第一时间送达

学习3D视觉核心技术,扫描查看介绍,3天内无条件退款

圈里有高质量教程资料、可答疑解惑、助你高效解决问题

本文由知乎作者yikang授权转载,不得擅自二次转载。原文链接:https://zhuanlan.zhihu.com/p/115339325

「本文演示了使用OpenCV对两帧图像进行ORB特征提取和特征匹配,对程序中出现的知识点作了整理总结,一如往常在程序中作了非常详尽的注释」

对两幅图像进行特征提取,可选的特征点种类有很多,不同的特征点计算方式和提取方式也各不相同。

本案例中采用的是ORB特征点,其关键点是改进的FAST角点,改进之处在于计算了特征点的主方向进而增加了旋转不变特性;描述子采用的是改进的BRIEF描述子,改进之处在于使用了之前计算的关键点方向信息。

我在公开数据集(here)中选取了两张图像:

对以上两张图像分步进行角点检测、描述子计算、特征点匹配、匹配点筛选、绘制匹配结果,得到了筛选匹配关键点后的图像:

在实现过程中主要学习了以下的知识点(部分列出):

  1. cv::assert()计算括号内的表达式,如果表达式为FALSE (或0), 程序将报告错误,并终止执行。如果表达式不为0,则继续执行后面的语句。

  2. opencv中keypoint类的默认构造函数为:CV_WRAP KeyPoint() : pt(0,0), size(0), angle(-1), response(0), octave(0), class_id(-1) {} 其中pt(x,y):关键点的点坐标;size():该关键点邻域直径大小;angle:角度,表示关键点的方向,值为[0,360),负值表示不使用。response:响应强度,选择响应最强的关键点; octacv:从哪一层金字塔得到的此关键点。class_id:当要对图片进行分类时,用class_id对每个关键点进行区分,默认为-1。

  3. “Ptr<FeatureDetector> detector = ”等价于 “FeatureDetector * detector =”。Ptr是OpenCV中使用的智能指针模板类,可以轻松管理各种类型的指针。

  4. 特征检测器FeatureDetetor是虚类,通过定义FeatureDetector的对象可以使用多种特征检测及匹配方法,通过create()函数调用。

  5. 描述子提取器DescriptorExtractor是提取关键点的描述向量类抽象基类。描述子匹配器DescriptorMatcher用于特征匹配,"BruteForce-Hamming"表示使用汉明距离进行匹配。

  6. computer()计算关键点的描述子向量(注意思考参数设置的合理性)。

  7. DMatch是匹配关键点描述子 类, matches用于存放匹配项。

  8. auto 可以在声明变量的时候根据变量初始值的类型自动为此变量选择匹配的类型

  9. minmax_element()返回指向范围内最小和最大元素的一对迭代器。参数1 2为起止迭代器范围,参数3是二进制函数,该函数接受范围内的两个元素作为参数,并返回可转换为bool的值。返回的值指示作为第一个参数传递的元素是否小于第二个,该函数不得修改其任何参数。

  10. drawMatches用于绘制两幅图像的匹配关键点。参数1是第一个源图像,参数2是其关键点数组;参数3是第二张原图像,参数4是其关键点数组。参数5是两张图像的匹配关键点数组,参数6用于存放函数的绘制结果。

关于此案例的主程序和CMakeLists.txt均在下方。

主程序:

#include <iostream>#include <opencv2/core/core.hpp>#include <opencv2/features2d/features2d.hpp>#include <opencv2/highgui/highgui.hpp>#include <chrono>using namespace std;using namespace cv;int main(int argc, char **argv){if(argc != 3){     //注意这里的参数为3,是因为argv[0]是指向输入的程序路径及名称:./orb_cv        cout << "usage: feature_extraction img1 img2 "<< endl;return 1;}//读取图像   Mat img_1 = imread(argv[1], CV_LOAD_IMAGE_COLOR);Mat img_2 = imread(argv[2], CV_LOAD_IMAGE_COLOR);assert(img_1.data != nullptr && img_2.data != nullptr);//在程序运行时cv::assert()计算括号内的表达式,如果表达式为FALSE (或0), 程序将报告错误,并终止执行。   //如果表达式不为0,则继续执行后面的语句。//初始化   vector<KeyPoint> keypoints_1, keypoints_2;   //关键点/角点   /**   opencv中keypoint类的默认构造函数为:  CV_WRAP KeyPoint() : pt(0,0), size(0), angle(-1), response(0), octave(0), class_id(-1) {}   pt(x,y):关键点的点坐标;// size():该关键点邻域直径大小;// angle:角度,表示关键点的方向,值为[0,360),负值表示不使用。  response:响应强度,选择响应最强的关键点;   octacv:从哪一层金字塔得到的此关键点。  class_id:当要对图片进行分类时,用class_id对每个关键点进行区分,默认为-1。  **/Mat descriptors_1, descriptors_2;      //描述子   //创建ORB对象,参数为默认值   Ptr<FeatureDetector> detector = ORB::create();Ptr<DescriptorExtractor> descriptor = ORB::create();Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce-Hamming");/**   “Ptr<FeatureDetector> detector = ”等价于 “FeatureDetector * detector =”   Ptr是OpenCV中使用的智能指针模板类,可以轻松管理各种类型的指针。  特征检测器FeatureDetetor是虚类,通过定义FeatureDetector的对象可以使用多种特征检测及匹配方法,通过create()函数调用。  描述子提取器DescriptorExtractor是提取关键点的描述向量类抽象基类。  描述子匹配器DescriptorMatcher用于特征匹配,"Brute-force-Hamming"表示使用汉明距离进行匹配。  **///第一步,检测Oriented Fast角点位置   chrono::steady_clock::time_point t1 = chrono::steady_clock::now();detector->detect(img_1, keypoints_1);     //对参数1图像进行特征的提取,并存放入参数2的数组中   detector->detect(img_2, keypoints_2);//第二步,根据角点计算BREIF描述子   descriptor->compute(img_1, keypoints_1, descriptors_1);   //computer()计算关键点的描述子向量(注意思考参数设置的合理性)   descriptor->compute(img_2, keypoints_2, descriptors_2);chrono::steady_clock::time_point t2 = chrono::steady_clock::now();chrono::duration<double> time_used = chrono::duration_cast<chrono::duration<double>>(t2 - t1);cout << "extract ORB cost = " << time_used.count() << " seconds. " << endl;Mat outimg1;drawKeypoints(img_1, keypoints_1, outimg1, Scalar::all(-1), DrawMatchesFlags::DEFAULT);imshow("ORB features", outimg1);imwrite("feaure1.png", outimg1);//第三步, 对两幅图像中的描述子进行匹配,使用hamming距离   vector<DMatch> matches;    //DMatch是匹配关键点描述子 类, matches用于存放匹配项   t1 = chrono::steady_clock::now();matcher->match(descriptors_1, descriptors_2, matches); //对参数1 2的描述子进行匹配,并将匹配项存放于matches中   t2 = chrono::steady_clock::now();time_used = chrono::duration_cast<chrono::duration<double>>(t2 - t1);cout << "match the ORB cost: " << time_used.count() << "seconds. " << endl;//第四步,匹配点对筛选   //计算最小距离和最大距离   auto min_max = minmax_element(matches.begin(), matches.end(),[](const DMatch &m1, const DMatch &m2){ return m1.distance < m2.distance; });// auto 可以在声明变量的时候根据变量初始值的类型自动为此变量选择匹配的类型   // minmax_element()返回指向范围内最小和最大元素的一对迭代器。参数1 2为起止迭代器范围   // 参数3是二进制函数,该函数接受范围内的两个元素作为参数,并返回可转换为bool的值。   // 返回的值指示作为第一个参数传递的元素是否小于第二个。该函数不得修改其任何参数。   double min_dist = min_max.first->distance;  // min_max存储了一堆迭代器,first指向最小元素   double max_dist = min_max.second->distance; // second指向最大元素printf("-- Max dist : %f \n", max_dist);printf("-- Min dist : %f \n", min_dist);//当描述子之间的距离大于两倍最小距离时,就认为匹配有误。但有时最小距离会非常小,所以要设置一个经验值30作为下限。   vector<DMatch> good_matches;  //存放良好的匹配项   for(int i = 0; i < descriptors_1.rows; ++i){if(matches[i].distance <= max(2 * min_dist, 30.0)){good_matches.push_back(matches[i]);}}//第五步,绘制匹配结果   Mat img_match;         //存放所有匹配点   Mat img_goodmatch;     //存放好的匹配点   // drawMatches用于绘制两幅图像的匹配关键点。   // 参数1是第一个源图像,参数2是其关键点数组;参数3是第二张原图像,参数4是其关键点数组   // 参数5是两张图像的匹配关键点数组,参数6用于存放函数的绘制结果   drawMatches(img_1, keypoints_1, img_2, keypoints_2, matches, img_match);drawMatches(img_1, keypoints_1, img_2, keypoints_2, good_matches, img_goodmatch);imshow("all matches", img_match);imshow("good matches", img_goodmatch);imwrite("match1.png", img_match);imwrite("goodmatch1.png", img_goodmatch);waitKey(0);return 0;}

CMakeLists.txt:

cmake_minimum_required(VERSION 2.8)project(vo1)set(CMAKE_BUILD_TYPE "Release")add_definitions("-DENABLE_SSE")#设置使用C++11编译include(CheckCXXCompilerFlag)CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)if(COMPILER_SUPPORTS_CXX11)set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")elseif(COMPILER_SUPPORTS_CXX0X)set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")else()message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")endif()list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)find_package(OpenCV 3 REQUIRED)include_directories( ${OpenCV_INCLUDE_DIRS} )add_executable(orb_cv orb_cv.cpp)target_link_libraries(orb_cv ${OpenCV_LIBS})

上述内容,如有侵犯版权,请联系作者,会自行删文。

推荐阅读:

吐血整理|3D视觉系统化学习路线

那些精贵的3D视觉系统学习资源总结(附书籍、网址与视频教程)

超全的3D视觉数据集汇总

大盘点|6D姿态估计算法汇总(上)

大盘点|6D姿态估计算法汇总(下)

机器人抓取汇总|涉及目标检测、分割、姿态识别、抓取点检测、路径规划

汇总|3D点云目标检测算法

汇总|3D人脸重建算法

那些年,我们一起刷过的计算机视觉比赛

总结|深度学习实现缺陷检测

深度学习在3-D环境重建中的应用

汇总|医学图像分析领域论文

大盘点|OCR算法汇总

重磅!3DCVer-知识星球和学术交流群已成立

3D视觉从入门到精通知识星球:针对3D视觉领域的知识点汇总、入门进阶学习路线、最新paper分享、疑问解答四个方面进行深耕,更有各类大厂的算法工程人员进行技术指导,650+的星球成员为创造更好的AI世界共同进步,知识星球入口:

学习3D视觉核心技术,扫描查看介绍,3天内无条件退款

圈里有高质量教程资料、可答疑解惑、助你高效解决问题

欢迎加入我们公众号读者群一起和同行交流,目前有3D视觉CV&深度学习SLAM三维重建点云后处理自动驾驶、CV入门、医疗影像、缺陷检测、行人重识别、目标跟踪、视觉产品落地、视觉竞赛、车牌识别等微信群,请扫描下面微信号加群,备注:”研究方向+学校/公司+昵称“,例如:”3D视觉 + 上海交大 + 静静“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进去相关微信群。原创投稿也请联系。

▲长按加群或投稿

SLAM从0到1——ORB特征提取及特征匹配相关推荐

  1. 无神经网络车牌识别(2)--特征提取与特征匹配

    特征提取 在这里其实会出现各种各样的算法,每年都会有很多的论文带来我们处理字符的新算法,如果想研究算法的话,这个可以自行翻阅论文,或者我之后再出一个算法系列的,但这里的话我主要是想把整个流程做完,所以 ...

  2. ORB特征提取详解 BRUEF rBRIEF steered BRIEF

    ORB特征提取详解 1.算法介绍 ORB(Oriented FAST and Rotated BRIEF)是一种快速特征点提取和描述的算法.这个算法是由Ethan Rublee, Vincent Ra ...

  3. Harris角点特征提取和角点特征匹配(2)

    Harris角点特征提取和特征匹配(后半部分) 前半部分点击以下链接: https://blog.csdn.net/QWER306306/article/details/123510826 本文采用H ...

  4. 特征匹配中OpenCV Dmatch类的用法解析以及非常详细的ORB特征提取与匹配解析

    首先说明一点,在SLAM中进行特征提取和匹配时,需要注意使用的OpenCV版本,在使用OpenCV2.x版本时,可以创建特征对象如下所示(省略了参数表): ORB orb; SURF surf; SI ...

  5. 【理解】ORB特征提取与ORBSLAM特征匹配简要剖析

    目录 ORB特征提取 优势: 经典FAST特征提取: 经典的BRIEF描述子: ORB特征提取的改进: 如何在FAST检测的基础上维持特征点的尺度不变性? 如何在FAST检测的基础上维持特征点的旋转不 ...

  6. ORB算法——特征提取特征匹配

    特征提取 Abstract ORB(Oriented Fast and Rotated Brief),可以用来对图像中的关键点快速创建特征向量,这些特征向量可以用来识别图像中的对象. 其中,Fast ...

  7. SLAM学习 | 论文研读《ORB: an efficient alternative to SIFT or SURF》

    SLAM学习 | 论文研读<ORB: an efficient alternative to SIFT or SURF> 1 文章翻译 Abstract(摘要) 1 Introductio ...

  8. 3D视觉(四):ORB特征提取与匹配

    3D视觉(四):ORB特征提取与匹配 根据维基百科的定义,图像特征是一组与计算任务相关的信息,计算任务取决于具体的应用.简而言之,特征是图像信息的另一种表达形式. 数字图像在计算机中以灰度值矩阵的方式 ...

  9. ORB特征提取和匹配

    ORB特征提取和匹配 1 什么是ORB特征 2 FAST关键点 3 尺度不变性 4 旋转不变性 4.1 灰度质心法 4.2 rBRIEF描述子 4.2.1 BREIF描述子 4.2.2Hamming距 ...

最新文章

  1. Java多线程:线程8锁案例分析
  2. 前端开发新手,这些书千万不要看!
  3. 喝不起奶茶,咱就为奶茶店开发个会员积分收银系统
  4. 【Matlab 图像】 app designer
  5. 用matlab求解不等方程组,Matlab:求高人指点用matlab求解非线性方程组,解出来的值不收敛,提前结束...
  6. Python 定时任务的实现方式
  7. Thrift IDL基本语法
  8. 知乎内容营销新动作:别处种草 知乎种树
  9. 单例模式 java 实现_单例模式
  10. win7 64位安装vs2013后连接远程数据库无法链接,并且导致vs崩溃。
  11. 木老师教笨笨课堂——系列讲座(从函数指针到委托) 四、C#的委托
  12. 大学c语言python_C语言和Python爬虫哪个好?老男孩IT教育
  13. URAL K-based Numbers(1-3)
  14. 上海税控盘登陆修改服务器地址,上海税控盘登陆修改服务器地址
  15. UART子系统(二) UART协议层 物理层
  16. Win10 如何将40G大文件极致压缩
  17. #4017. 复制粘贴(copypaste)
  18. CVPR 2021 预讲 · 华为诺亚专场,5 篇精华报告,覆盖NAS、蒸馏、检测和降噪
  19. puzzle(010.1)自我指涉的选择题
  20. 鸿蒙系统原创,华为鸿蒙系统.docx

热门文章

  1. 使用matlab进行mex编译时的路径问题mexopts
  2. 爱情这东西,真的有报应吗…
  3. 关于sysobjects这个表
  4. 终于明白了 DevOps 与 SRE 的区别!
  5. 什么是接口幂等性?为什么会产生这个问题?如何保证接口幂等性?
  6. 一个技术总监的忠告:精通那么多技术有毛用啊,你还不是不被重用?
  7. 编码编成翔的十八般兵器
  8. 6亿数据秒级查询,ClickHouse太快了!
  9. 甩锅!偷懒!PUA!转嫁压力!铲除异己!压榨下属!这就是职场leader真面目!...
  10. 月薪30K+的程序员都会啥,通过3000字告诉你……