【CV】ORB源码详解-描述子的建立

本文深入解析OpenCV中ORB(Oriented FAST and Rotated BRIEF)特征提取器的描述子计算部分。通过源码分析,了解ORB如何通过oFAST提取特征点并利用rBreaf计算旋转不变性描述子。文中详细探讨了ORB的创建、检测、计算等关键步骤,展示了OpenCV实现ORB的主要流程和关键函数。
摘要由CSDN通过智能技术生成

【CV】ORB源码详解-描述子的建立

项目中最近需要在嵌入式上实现orb,由于板子的运算器对之没有优化,所以不能用opencv的代码。为了实现这个需求笔者查阅相关资料,阅读opencv3.2中相关的源码(很幸运能看懂),在此进行总结,以备使用。

首先ORB是一种提取图像特征并通过一定方法计算描述子,以用来进行匹配的方法。注意orb只解决了提取特征并计算描述子的问题。而后续的匹配是有其他方法的,不属于orb的范畴,匹配既可以用orb也可以用sift,surf等其他方法。

ORB这个名字是oFast与rBreaf的缩写。其中oFAST指FAST Keypoint Orientation,rBreaf指Rotation-Aware Brief。如名字,ORB其实是分两个部分的:提特征点,算描述子。而这两个部分在我看来是可以分开的。

提特征点其实就告诉算描述子过程在哪里去算,并为算描述子提供了关键信息——特征点的方向。论文原文中用的是oFast去提取特征点。显然可以用其他方法代替(比如板子上带的硬件加速的Shi-Tomasi-like特征提取API),至于特征点的方向,还是用oFast的灰度质心法。这和特征提取也是分开的。

算描述子应该算是论文中提出的精髓了。也有很多相关的文章去介绍。比如这篇就讲解的很详细。

http://blog.csdn.net/lhanchao/article/details/52612954

那么,我的文章就到头了吗?显然不是,文章题名为源码详解。所以本文就OpenCV对ORB的具体实现(只讨论算描述子部分),从源码出发以期对这个算法彻头彻尾的理解透。那就开始正文吧。

OpenCV中ORB的代码调用框架

在开始理描述子计算过程之前,有必要提一提ORB到底是怎么用的,要不然到最后分析了一堆不知道分析的是哪里。

从调用说起

从很多博客上可以看到提取ORB特征进行调用的文章。对于OpenCV 的C++接口来说,其调用套路也就是几步,首先创建一个句柄,这个句柄能够执行特征提取的两大步:提取、算描述子。典型代码片段如下:

 Ptr<Feature2D> featurehdl = ORB::create();

当然create()里面可以加入很多参数这里不展开。之后呢就是通过这个句柄(其实也就是个智能指针)去提取特征点,算描述子。

vector<KeyPoint> keypoints;
Mat descriptors;
Mat image= imread("../image/xxxxxx.jpg");
featurehdl->detect(image,keypoints);
featurehdl->compute(image,keypoints,descriptors);

然后就得到了一组描述符descriptors。在原图上和测试图上分别这么做就得到了一对匹配点。接着调用match相关的接口去匹配就能匹配成功,不展开。本文就仔细分析createdetectcompute这几个调用到底干了些什么。

create

talk is cheap。

Ptr<ORB> ORB::create(int nfeatures, float scaleFactor, int nlevels, int edgeThreshold,
           int firstLevel, int wta_k, int scoreType, int patchSize, int fastThreshold)
{
    return makePtr<ORB_Impl>(nfeatures, scaleFactor, nlevels, edgeThreshold,
                             firstLevel, wta_k, scoreType, patchSize, fastThreshold);
}

其实create的时候,代码new了一个ORB_Impl类的指针(为何没直接new而是makePtr,其实就是一个模板函数,可以方便地new各种类的指针吧)。各个类的继承关系是这样的:ORB_Impl->ORB->Feature2D,很明了,想扩展其他描述子只需继承Feature2D就行。跟进去可以看到构造函数是什么事情都不干的,只是用参数初始化了一些成员变量而已。

detect

void Feature2D::detect( InputArray image,
                        std::vector<KeyPoint>& keypoints,
                        InputArray mask )
{
    CV_INSTRUMENT_REGION()

    if( image.empty() )
    {
        keypoints.clear();
        return;
    }
    detectAndCompute(image, mask, keypoints, noArray(), false);
}

detect是一个虚函数,但在ORBORB_Impl里都没有相关定义,所以走的就是基类的方法,显然其中调用了detectAndCompute函数。从名字上看这个函数实现了detectcompute,想必是从参数上去控制这个函数干什么事情。

compute

既然这两个方法调一个函数那就把这两个调用先写上来最后再分析那个大函数吧。

void Feature2D::compute( InputArray image,
                         std::vector<KeyPoint>& keypoints,
                         OutputArray descriptors )
{
    CV_INSTRUMENT_REGION()

    if( image.empty() )
    {
        descriptors.release();
        return;
    }
    detectAndCompute(image, noArray(), keypoints, descriptors, true);
}

void ORB_Impl::detectAndCompute( InputArray _image, InputArray _mask,
                                 std::vector<KeyPoint>& keypoints,
                                 OutputArray _descriptors, bool useProvidedKeypoint
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值