解读《十四讲》到现在已经是第七讲了,基本上用于SLAM的数学知识已经差不多够了。我相信如果你先前没有接触过开源的SLAM框架的话,前面学习的这些数学知识的应用,可能你不会有一个很深刻的认识,但是往后的内容我们会一点一点的用上这些数学知识。
这一讲我们要开始接触到SLAM的前端了,作者在这一讲中提到了很多细小的知识点,但是很多却一句话带过,并没有进一步的介绍,这一讲我也要着重介绍一下这些被一句话带过的知识点。
另外这一讲多是一些可以看到效果的东西,所以理论性会低一些,大家不用担心难以学习,稍加耐心,一定都能理解。大家也要重视这一讲的内容,这一讲几乎涵盖了前端的所有内容了。
这一讲的题目叫作: 视觉里程计。我们有必要去理解一下题目的意思,在中文字典中对于里程计的解释:测量行程的装置。所以视觉里程计就是通过视觉的方法测量行程的装置。值得注意的是,这里对装置的定义很宽泛,并不是真正的一种设备,通过计算机编程完成测量行程的任务,也等同于是装置。
为了完成测量行程的目的,作者介绍了一些准备工作,首先介绍了特征点,关于特征点作者介绍地很清楚,我在这里只是总结一下:
特征点实际上就是照片中一些比较有代表性的点,至于什么叫有代表性,不同的方法有不同的定义,但是特征点选取需要遵循下面几条规则:
作者还指出,特征点由两部分组成,一个是关键点,另外一个是用来描述这个关键点的描述子。
关于特征点作者指出常见的特征点有:ORB、SURF、SIFT等,其中作者详细的介绍了ORB特征点。
下面我先总结一下ORB特征点,然后再扩展一下作者提到的另外几种特征点。
如果你先前了解过ORB-SLAM系统,那么你对ORB特征点一定不会陌生,它就应用于ORB-SLAM系统,用来提取特征点,而且在效率和可重复性上都取得了很好的效果。
ORB特征点是在FAST关键点的基础上进行改进的,加入了BRIEF描述子,关于这个作者解释的很清楚了。但是其中省略一些内容的解释,我下面给大家补上。
作者在书中提到: 我们可以指定最终要提取的角点数量,对原始FAST角点分别计算Harris响应值。那么啥是Harris响应值呢?其实Harris响应值就代表了这个关键点在局部窗口内是一个是什么状态,响应值越大就越是一个好的角点。其实这里面的理论也不简单,我推荐一个博客给大家看,写的挺好的《Harris角点检测原理详解》,如果你觉得比较难理解,可以暂且放一边,OpenCV已经帮我们写好了,你只要会用就行了。
关于关于图像金字塔和尺度不变形的理解,我有写过一个博客,大家可以参考一下《图像金字塔在ORB-SLAM中的应用详解,如何解决特征点尺度不变性》
灰度质心的提出,就是为了解决关键点没有方向的问题,关于灰度质心的计算方法作者已经给出了公式,关于灰度质心法更为直观的意义,我画了一个示意图,如下图。首先遍历每一个方格中的像素值,计算出整个窗口里面的质心,原点和质心所成的直线与横轴的夹角,就是这个关键点的方向角。
描述子的种类也很多,作者主要介绍了BRIEF描述子,关于它的介绍,总结起来就是:在一个窗口中随机的选取很多对像素点,一对像素点中如果前面大于后面,那么就取1,否则就取0,对于很多对像素点,那么就可以得到一串01组成的数列,这个数列就是BRIEF描述子。像素点对的选取,作者书中介绍到是随机选取,实际上在ORB-SALM中,这种像素点对的选取并不是随机的,当你阅读到相关内容的时候,你就了解了,这里你暂时有个印象。
在这里我还推荐一种叫做FREAK的描述子,大家可以作为扩展内容了解一下。FREAK也是一种基于二进制编码的图像特征描述子,它计算较快,对噪声鲁棒,具有尺度不变性和旋转不变性,该算法还有一个突出特点就是受到人眼视网膜视觉机理的启发而提出。细致内容参考这篇博客《【特征检测】FREAK特征提取算法》
关于SIFT特征点,大家可以参考这篇博客《SIFT算法详解》
SURF特征点,请参考这篇博客《SURF特征提取分析》
前面作者介绍了特征点由关键点和描述子组成,可以想象的出来,如果两张图片,非常相似,那么我在一张图片中提取的特征点,理论上来说是可以在第二张图片中找到,这个找对应特征点的过程就叫做特征匹配。
特征匹配我们最先想到的最简单的方法就是,第一张图片中的一个特征点去和另外一张图片中的特征点进行一一比对,然后重复这个过程知道第一张图片中的所有特征点都进行了匹配操作。
虽然这个过程会耗时一点儿,但是最起码是可以行得通的。在不同的SLAM系统中,有不同的方法来加速这种匹配过程,ORB-SLAM就是在一个对应区域内进行搜索,这样就大大的降低了搜索时间。
那么什么样的两个特征点才算匹配上了呢?作者在文中提到了汉明距离,汉明距离是用来描述两个描述子有多大的差异,比方说,一个描述子是100101011010,另外一个描述子是000110000101,然后比较两个描述子对应位子是否相同,有几个不同就表示两个描述子之间的距离是几,前面这两个描述子的距离是:8。
实践部分的代码,还是很简单的,理解上没有什么难度,不过还是建议大家将代码多敲两遍,记住这个过程,将来你自己写SLAM的时候,也是这个流程,只不过会再加一些提高速度和鲁棒性的技巧。
这里解释ORB构造器的代码:
Ptr<ORB> orb = ORB::creat(500,1.2f,8,31,0,2,ORB::HARRIS_SCORE,31,20)
这个函数原型和参数表如下:
create(int nfeatures=500, float scaleFactor=1.2f, int nlevels=8,
int edgeThreshold=31, int firstLevel=0, int WTA_K=2,
int scoreType=ORB::HARRIS_SCORE, int patchSize=31, int fastThreshold=20);
参数解释:
nfeatures
:提取特征点的数量;
scaleFactor
:图像金字塔金字塔的缩放比;
nlevel
:金字塔的层数;
edgeThreshold
:距离图片边界在这个值以内的区域,不检测特征点;
firstLevel
:金字塔的哪一层存放原图;
WTA_K
:描述子采用什么样的描述方法,2就代表用0和1描述,3代表用0、1、2描述;
scoreType
:关键点的响应值类型;
patchSize
:在距离关键点多大的半径内(单位:像素)计算描述子;
fastThreshold
:FAST关键点在提取时候,中心点的亮度阈值。
喜欢的事自然可以坚持,不喜欢的怎么也长久不了,人生本来如此……