opencv笔记--ORB

    ORB detector 使用 FAST detector 和 BRIEF descriptor 基本思路。在介绍 ORB 之前,首先对 FAST 与 BRIEF 进行说明。

    1 FAST

       FAST(Featrues from Accelerated Segment Test),其基本思想是比较当前点与周边点差异,当周边有连续不少于一半的点均比中间点亮或者暗,则认为该点为一个特征点。其中,亮或暗的定义为:

      1)当  时,周边点比中间点亮;

      2)当  时,周边点比中间点暗;

      3)当  时,周边点与中间点相似;

      使用以上定义,可以迅速找到图像中候选特征点。

      由于需要满足不少于一半的连续周边点亮于或暗于中间点,可以首先检测水平与垂直方向上四个点,当少于两个连续点满足条件,则该点一定不是候选特征点。如此可以提升计算效率。

      当完成候选特征点扫描后,会发现存在许多临近特征点,可以使用如下评分进行非极大值抑制:

      

       以上即为 FAST 的基本思想,opencv 实现在 cv::FastFeatureDetector 中,参数 threshold 定义了亮或暗,nonmaxSuppression 确定是否排除临近点。

    2 BRIEF

       BRIEF 对特征点生成描述特征向量。在 SIFT 与 SURF 中均使用了块特征描述方案,使用不同小块的方向梯度直方图构成特征向量。BRIEF 使用点特征描述特征点,基本思想为:

       1)在特征点区域内随机生成 N 个点对,这N个点对生成方式有很多种,但一旦生成,对于所有特征点描述均使用相同的点对模式;

       2)由于需要对孤立点进行比较,所以首先平滑图像以抑制噪声;

       3)构造 N 位向量,第 k 个点对生成第 k 位向量,当点对中前一个点大于后一个点,其值为  1,反之为 0;

       opencv 实现在 cv::BriefDescriptorExtractor 中,参数 bytes 确定特征点描述向量长度为 bytes * 8。

       结合 FAST 与 BRIEF,可以实现类似 SIFT 与 SURF 的功能,以下给出简单使用代码:

       

 1 cv::FastFeatureDetector detector(20);
 2 std::vector<cv::KeyPoint> keypoints1, keypoints2;
 3 detector.detect(img1, keypoints1);
 4 detector.detect(img2, keypoints2);
 5 
 6 cv::BriefDescriptorExtractor brief;
 7 cv::Mat descriptors1, descriptors2;
 8 brief.compute(img1, keypoints1, descriptors1);
 9 brief.compute(img2, keypoints2, descriptors2);
10 
11 // 不同于SIFT与SURF,这里使用汉明距离
12 cv::BFMatcher matcher(cv::NORM_HAMMING);
13 std::vector<DMatch> matches;
14 matcher.match(descriptors1, descriptors2, matches);

      其匹配结果如下:

        

      

   

3 ORB

       ORB 主要思想如下:

       1)使用 FAST 提取候选特征点;

       2)为了克服 FAST 可能产生的边缘响应,使用 Harris corner measure 保留角点响应,剔除边缘响应(边缘响应不利于匹配);

       3)按以上方法在不同层级图像金字塔上搜索候选特征点;

       4)使用归一化图像描述特征点方向 

       5)使用特征点方向生成 BRIEF 特征点描述向量;

       6)使用汉明距离计算特征点之间相似度;

       opencv 提供  cv::ORB 实现特征点提取与描述,其构造函数参数如下:

       nfeatures 表示需要提取的特征点数量;

       scaleFactor,nlevels  为图像金字塔参数;

       firstLevel 表示从第几层开始搜索特征点,一般为 0;

       patchSize 确定特征点尺寸,edgeThreshold 应不小于 patchSize,该参数忽略边界特征点;

       scoreType 确定使用 FAST 评分机制或者 Harris corner 评分机制;

       WTA_K 控制比较点个数,当为 2 时,即为 FAST 对点对比较方式;

       以下给出简单使用代码:

       

 1 cv::Mat img1 = cv::imread("a.bmp", cv::IMREAD_GRAYSCALE);
 2 cv::Mat img2 = cv::imread("b.bmp", cv::IMREAD_GRAYSCALE);
 3 
 4 std::vector<cv::KeyPoint> keypoints1, keypoints2;
 5 cv::Mat descriptors1, descriptors2;
 6 
 7 cv::ORB orb(100, 1.5, 4);
 8 orb.operator()(img1, cv::noArray(), keypoints1, descriptors1);
 9     orb.operator()(img2, cv::noArray(), keypoints2, descriptors2);
10 
11 cv::BFMatcher matcher(cv::NORM_HAMMING);
12 std::vector<DMatch> matches;
13 matcher.match(descriptors1, descriptors2, matches);
14 
15 cv::Mat img_matches;
16 cv::drawMatches(img1, keypoints1, img2, keypoints2, matches, img_matches);
17 cv::imwrite("c.jpg", img_matches);
18 
19 double min_dist = 100;
20 
21 for (int i = 0; i < matches.size(); i++)
22 {
23     double dist = matches[i].distance;
24     if (dist < min_dist) min_dist = dist;
25         
26 }
27 
28 // Draw only "good" matches (i.e. whose distance is less than 2*min_dist,
29 // or a small arbitary value ( 0.02 ) 
30 std::vector< DMatch > good_matches;
31 
32 for (int i = 0; i < matches.size(); i++)
33 {
34     if (matches[i].distance <= max(2 * min_dist, 0.02))
35     {
36         good_matches.push_back(matches[i]);
37     }
38 }
39 
40 cv::drawMatches(img1, keypoints1, img2, keypoints2, good_matches, img_matches);
41 cv::imwrite("d.jpg", img_matches)

     其匹配结果如下:

     

     

     

     参考资料 Learning OpenCV 3   Adrian Kaehler & Gary Bradski

原文地址:https://www.cnblogs.com/luofeiju/p/13578179.html