OpenCV4中的ORB特征提取与匹配

科技   2024-09-23 23:01   江苏  

点击上方蓝字关注我们

微信公众号:OpenCV学堂

关注获取更多计算机视觉与深度学习知识

FAST特征点定位

ORB - (Oriented Fast and Rotated BRIEF)算法是基于FAST特征检测与BRIEF特征描述子匹配实现,相比BRIEF算法中依靠随机方式获取二值点对,ORB通过FAST方法,FAST方式寻找候选特征点方式是假设灰度图像像素点A周围的像素存在连续大于或者小于A的灰度值,选择任意一个像素点P,假设半径为3,周围16个像素表示如下:

假设存在连续N个点满足

则像素点P被标记为候选特征点、通常N取值为9、12,上图N=9。为了简化计算,我们可以只计算1、9、5、13四个点,至少其中三个点满足上述不等式条件,即可将P视为候选点。

BRIEF特征描述子

得到特征点数据之后,根据BRIEF算法就可以建立描述子。选择候选特征点周围SxS大小的像素块、随机选择n对像素点,定义如下:

其中P(x)是图像模糊处理之后的像素值,原因在于高斯模糊可以抑制噪声影响、提供特征点稳定性,在实际代码实现中通常用均值滤波替代高斯滤波以便利用积分图方式加速计算获得更好的性能表现。常见滤波时候使用3x3~9x9之间的卷积核。滤波之后,根据上述描述子的生成条件,得到描述子表达式如下:

作者论文提到n的取值通常为128、256或者512。得到二进制方式的字符串描述子之后,匹配就可以通过XOR方式矩形,计算汉明距离。ORB特征提取跟纯BRIEF特征提取相比较,BRIEF方式采用随机点方式得最终描述子、而ORB通过FAST得到特征点然后得到描述子。

旋转不变性

ORB比BRIEF方式更加合理,同时具有旋转不变性特征与噪声抑制效果,ORB实现选择不变性特征,是通过对BRIEF描述子的特征点区域的计算得到角度方向参数。主要原理是使用几何距公式。图像的几何距计算公式如下:

其中n=p+q称为N阶距。得到中心坐标为:

计算得到角度为:

ORB算法根据角度参数提取BRIEF描述子,实现旋转不变性特征。随机ORB算法通过贪心算法进一步发现低相关性描述子作为最终二值字符串描述子输出。通常是256位的特征描述子,完整的ORB特征描述子算法流程图如下:

OpenCV中基于ORB特征对象匹配代码演示如下:

  1. #include <opencv2/opencv.hpp>

  2. #include <iostream>

  3. #include <math.h>

  4. #define RATIO    0.4

  5. using namespace cv;

  6. using namespace std;

  7. int main(int argc, char** argv) {

  8.    Mat box = imread("D:/vcprojects/images/box.png");

  9.    Mat scene = imread("D:/vcprojects/images/box_in_scene.png");

  10.    if (scene.empty()) {

  11.        printf("could not load image...\n");

  12.        return -1;

  13.    }

  14.    imshow("input image", scene);

  15.    vector<KeyPoint> keypoints_obj, keypoints_sence;

  16.    Mat descriptors_box, descriptors_sence;

  17.    Ptr<ORB> detector = ORB::create();

  18.    detector->detectAndCompute(scene, Mat(), keypoints_sence, descriptors_sence);

  19.    detector->detectAndCompute(box, Mat(), keypoints_obj, descriptors_box);

  20.    vector<DMatch> matches;

  21.    // 初始化flann匹配

  22.    // Ptr<FlannBasedMatcher> matcher = FlannBasedMatcher::create(); // default is bad, using local sensitive hash(LSH)

  23.    Ptr<DescriptorMatcher> matcher = makePtr<FlannBasedMatcher>(makePtr<flann::LshIndexParams>(12, 20, 2));

  24.    matcher->match(descriptors_box, descriptors_sence, matches);

  25.    // 发现匹配

  26.    vector<DMatch> goodMatches;

  27.    printf("total match points : %d\n", matches.size());

  28.    float maxdist = 0;

  29.    for (unsigned int i = 0; i < matches.size(); ++i) {

  30.        printf("dist : %.2f \n", matches[i].distance);

  31.        maxdist = max(maxdist, matches[i].distance);

  32.    }

  33.    for (unsigned int i = 0; i < matches.size(); ++i) {

  34.        if(matches[i].distance < maxdist*RATIO)

  35.            goodMatches.push_back(matches[i]);

  36.    }

  37.    Mat dst;

  38.    drawMatches(box, keypoints_obj, scene, keypoints_sence, goodMatches, dst);

  39.    imshow("output", dst);

  40.    waitKey(0);

  41.    return 0;

  42. }

在OpenCV中基于BRIEF与ORB特征实现FLANN对象匹配经常会遇到一个错误如下:

原因是BRIEF与ORB特征是二进制的CV_8U而SIFT与SURF特征数据是浮点数,FLANN默认的匹配是基于浮点数运算计算距离,所以导致了类型不支持错误,这个时候只要使用如下的方法重新构造一下FLANN指针,然后调用match方法即可。
  1. Ptr<DescriptorMatcher> matcher = makePtr<FlannBasedMatcher>

  2.                          (makePtr<flann::LshIndexParams>(12, 20, 2));

运行结果:

为学患无疑,疑则进也

OpenCV4系统化学习


深度学习系统化学习

推荐阅读

OpenCV4.8+YOLOv8对象检测C++推理演示

ZXING+OpenCV打造开源条码检测应用

攻略 | 学习深度学习只需要三个月的好方法

三行代码实现 TensorRT8.6 C++ 深度学习模型部署

实战 | YOLOv8+OpenCV 实现DM码定位检测与解析

对象检测边界框损失 – 从IOU到ProbIOU

初学者必看 | 学习深度学习的五个误区


OpenCV学堂
三本书《Java数字图像处理-编程技巧与应用实践》、《OpenCV Android开发实战》、《OpenCV4应用开发-入门、进阶与工程化实践》作者。OpenCV实验大师平台 软件作者,OpenCV开发专家、OpenCV研习社创始人。
 最新文章