ORB 算法学习笔记

本博客内容来源于网络以及其他书籍,结合自己学习的心得进行重编辑,因为看了很多文章不便一一标注引用,如图片文字等侵权,请告知删除。

传统2D计算机视觉学习笔记目录------->传送门
传统3D计算机视觉学习笔记目录------->传送门

前言

休息了一天,雨天去了一次颐和园,不幸,我感冒了。所以,如果本文有任何常识性问题,请不要怀疑作者的知识水平,而是脑子有点烧糊涂了。前面我们描述完了sift以及surf算法,本片我们描述一下orb特征检测算法。

今天一看,竟然已经写了15篇文章了,也为自己的坚持点个赞 ~ (≧▽≦)/ ~ 。的的确确这段时间,对一些算法的理解也有了更深的层次,再接再厉,今晚奖励给我家猫奖励一罐小鱼干。

ORB简介

ORB 全称:Oriented FAST and Rotated BRIEF,是一种快速特征点提取和描述的算法,发布于“ORB:An Efficient Alternative to SIFT or SURF” 论文中。从名字中,我们可以看出是由两部分构成,Oriented FAST 和 Rotated BRIEF,这也以最简单的语言描述了ORB算法。ORB算法分为两部分,分别是特征点提取和特征点描述。特征提取是由FAST算法(前面已经学过)发展来的,特征点描述是根据BRIEF特征描述算法改进的。

ORB算法最大的特点就是计算速度快,计算时间大概只有SIFT的1%,SURF的10%,这主要是因为使用了FAST来加速了特征点的提取。再次是使用BRIEF算法计算描述子,该描述子特有的2进制串的表现形式不仅节约了存储空间,而且大大缩短了匹配的时间。

当然ORB算法也有一些缺点,比如尺度变换的应对能力比较低。接下来我们来看ORB的流程,来分析一下ORB特征提取的优缺点。

ORB 算法流程

1. 关键点提取

有关FAST算法,可以跳转去看另一篇来详细描述FAST特征点的笔记:FAST角点学习笔记中查看。本节主要描述ORB算法中对FAST算法的改进。

ORB对FAST的改进或者拓展,主要是为其增加了其尺度不变性以及旋转不变性。接下里来看一看怎么实现的。

1. 提取FAST特征点

通过FAST算法提取出FAST特征点,过程不在详细描述,这样我们就找到了一张图片的基本的关键点。

2. 建立金字塔

ORB实现尺度不变性,也是通过图像金字塔来实现的。ORB论文本身并没有解决尺度不变性,而是在opencv实现中添加了这部分,具体做法为设置一个比例因子scale(opencv默认取1.2)和金字塔的层数n(通常取8)。将原图像按比例因子缩小成n幅图像。缩放后的图像为:I’= I / scale^k (k=1,2,…, n)。n幅不同比例的图像提取特征点总和作为这幅图像的FAST特征点。

当然可以通过采用不同的高斯核进行高斯模糊来建立金字塔,但是时间成本就很高了。

3. 定义特征点方向

ORB实现旋转不变性,也是通过确定一个特征点的方向来实现的,我们来看看ORB是怎么来确定特征点的方向的?

ORB的论文中提出了一种利用灰度质心法来解决这个问题,通过计算一个矩来计算特征点以r为半径范围内的质心,特征点坐标到质心形成一个向量作为该特征点的方向。我们来看看具体怎么实现灰度质心法。

一个图像块(比如5x5的图像块中),对应的2x2的矩的元素表达为:

x,y分别为坐标值,I(x,y)为像素值

而该图像窗口的质心就是:

其实灰度的质心就是对所有的位置进行加权,权重就是像素值在整个图像中像素值之和的比例。

那么特征点与质心的夹角定义为FAST特征点的方向:

也就有了特征点的方向,继而实现旋转不变性。

通过上述步骤我们找到了所有的特征点,并计算出了特征点的方向,下面就看一下怎么描述这些特征点。

2. 关键点描述

ORB选择了BRIEF作为特征描述方法,并对其进行改进使其加上旋转不变性并增加其可区分性,首先我们先看看BRIEF描述子。

  • BRIEF描述子

BRIEF算法计算出来的是一个二进制串的特征描述符。它是在每一个特征点的邻域内,选择n对像素点pi、qi(i=1,2,…,n)。然后比较每个点对的灰度值的大小。如果I(pi)> I(qi),则生成二进制串中的1,否则为0。所有的点对都进行比较,则生成长度为n的二进制串。一般n取128、256或512,通常取256。

为了增强抗噪性,一般会先对图像进行高斯平滑。ORB算子采用5x5的子窗口进行平滑。

那么这n个点对如何选取呢?
在点周围选取点对(p,q)的方法有以下5种:

  1. 在图像块内平均采样;
  2. p和q都符合(0,S2/25)的高斯分布;
  3. p符合(0,S2/25)的高斯分布,而q符合(0,S2/100)的高斯分布;
  4. 在空间量化极坐标下的离散位置随机采样;
  5. 把p固定为(0,0),q在周围平均采样。

BRIEF作者采用的是第二种。而ORB作者没有选择以上任意方式,而是一种新的方式,我们在下面再说。

BRIEF流程简单实时性较好,论文中生成512个描述子用时8.18ms,并且其描述子是二进制码,其匹配也比较快。但是,当BRIEF对于旋转过大时,比如超过30度时,匹配正确率迅速下降直到45度时为0。所以需要增加其描述子的旋转不变性。

  • BRIEF算法改进

在描述基础BRIEF算法时,我们提出了两个问题,一个是增加其旋转不变性,一个是选点方式。

  • steered BRIEF 增加其旋转不变性

所谓steered BRIEF 就是对挑选出的点对加上一个旋转角度θ。对于任何一个特征点来说,它的BRIEF描述子是一个长度为𝑛的二值码串,这个二值码串是由特征点邻域𝑛个点对生成的,我们现在讲这2𝑛个点(𝑥𝑖,𝑦𝑖),𝑖=1,2,.....,2𝑛组成一个矩阵𝑆:

使用邻域方向𝜃和对应的旋转矩阵𝑅𝜃,构建𝑆的一个校正版本𝑆𝜃:

其中

即我们把坐标轴旋转]𝑡ℎ𝑒𝑡𝑎,计算以主方向为坐标系的匹配点对,如下图:

steered BRIEF加入了旋转不变性,但同时特征描述量的可区分行就下降了,所以就有了ORB作者提出的rBRIEF。

  • rBRIEF 增加其可区分性

我们在上边说过ORB没有使用BRIEF 5种选取点对方法中的任意一种,那么ORB用的是什么方式?
ORB使用统计学习的方法来重新选择点对集合,目的是增大其特征描述量的可区分行。这里我们先不解释其具体的实验流程(主要是我还没有完全理解),但是通过其实验,选出来的点对对特征点描述的区分度变高了。

至此ORB算法计算完毕。

OpenCV ORB特征效果展示[代码]

#include <opencv2/opencv.hpp>
#include <iostream>
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/features2d/features2d.hpp>
void extracte_orb(cv::Mat input,std::vector<cv::KeyPoint> &keypoint,cv::Mat &descriptor){
    cv::Ptr<cv::ORB> f2d = cv::ORB::create(500);
    f2d->detect(input,keypoint);
    cv::Mat image_with_kp;
    f2d->compute(input,keypoint,descriptor);
    cv::drawKeypoints(input, keypoint, image_with_kp, cv::Scalar::all(-1),cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
    cv::imwrite("orb"+std::to_string(random())+".png",image_with_kp);
}

void match_two_image(cv::Mat image1,cv::Mat image2, std::vector<cv::KeyPoint> keypoint1,std::vector<cv::KeyPoint> keypoint2,cv::Mat descriptor1,cv::Mat descriptor2){
    cv::BFMatcher matcher(cv::NORM_HAMMING);
    std::vector<cv::DMatch> matches;
    matcher.match(descriptor1,descriptor2, matches);
    cv::Mat good_matches_image;
    cv::drawMatches(image1, keypoint1, image2, keypoint2,
                    matches, good_matches_image, cv::Scalar::all(-1), cv::Scalar::all(-1),
                    std::vector<char>(), cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
    cv::imwrite("good_matches_image.png",good_matches_image);
    {
        std::vector <cv::KeyPoint> RAN_KP1, RAN_KP2;
        std::vector<cv::Point2f> keypoints1, keypoints2;
        for (int i = 0; i < matches.size(); i++) {
            keypoints1.push_back(keypoint1[matches[i].queryIdx].pt);
            keypoints2.push_back(keypoint2[matches[i].trainIdx].pt);
            RAN_KP1.push_back(keypoint1[matches[i].queryIdx]);
            RAN_KP2.push_back(keypoint2[matches[i].trainIdx]);
        }

        std::vector<uchar> RansacStatus;
        cv::findFundamentalMat(keypoints1, keypoints2, RansacStatus, cv::FM_RANSAC);
        std::vector <cv::KeyPoint> ransac_keypoints1, ransac_keypoints2;
        std::vector <cv::DMatch> ransac_matches;
        int index = 0;
        for (size_t i = 0; i < matches.size(); i++)
        {
            if (RansacStatus[i] != 0)
            {
                ransac_keypoints1.push_back(RAN_KP1[i]);
                ransac_keypoints2.push_back(RAN_KP2[i]);
                matches[i].queryIdx = index;
                matches[i].trainIdx = index;
                ransac_matches.push_back(matches[i]);
                index++;
            }
        }
        cv::Mat after_ransac_sift_match;
        cv::drawMatches(image1, ransac_keypoints1, image2, ransac_keypoints2,
                        ransac_matches, after_ransac_sift_match, cv::Scalar::all(-1), cv::Scalar::all(-1),
                        std::vector<char>(), cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
        cv::imwrite("after_ransac_orb_match.png",after_ransac_sift_match);
    }
}

int main(int argc, char *argv[])
{
    cv::Mat image1 = cv::imread(argv[1]);
    cv::Mat image2 = cv::imread(argv[2]);
    std::vector<cv::KeyPoint> keypoint1,keypoint2;
    cv::Mat descriptor1, descriptor2;
    extracte_orb(image1,keypoint1,descriptor1);
    extracte_orb(image2,keypoint2,descriptor2);
    match_two_image(image1,image2,keypoint1,keypoint2,descriptor1,descriptor2);
    return 0;
}

因为orb难以应对我们类似SIFT或surf那么大的仿射变换,所以不得不换了仿射变换小的照片

原图1 orb识别效果 原图2 orb识别效果
初步匹配效果 ransac后匹配效果

总结

总体来说ORB在上述实验实例中的效果还是很好的。我们已经讲完SIFT,SURF还有ORB,我们来对比一下这三个算法。
计算速度: ORB>>SURF>>SIFT(各差一个量级)
旋转鲁棒性: SURF>ORB~SIFT(~表示差不多)
模糊鲁棒性: SURF>ORB~SIFT
尺度变换鲁棒性: SURF>SIFT>ORB(ORB尺度变换性很弱)
在日常应用中,有SURF基本就不用考虑SIFT,SURF基本就是SIFT的全面升级版,当然也有其他SIFT的改进版比如Affine SIFT的效果就要比SUFR要好更多,但是计算时间也有延长,而ORB的强点在于计算时间。ORB主要还是在VSLAM中应用较多,场景变化不明显,但是需要高速的计算时间,这正好符合ORB。

特征点到此结束,继续加油

重要的事情说三遍:

如果我的文章对您有所帮助,那就点赞加个关注呗 ( * ^ __ ^ * )

如果我的文章对您有所帮助,那就点赞加个关注呗 ( * ^ __ ^ * )

如果我的文章对您有所帮助,那就点赞加个关注呗 ( * ^ __ ^ * )

传统2D计算机视觉学习笔记目录------->传送门
传统3D计算机视觉学习笔记目录------->传送门

任何人或团体、机构全部转载或者部分转载、摘录,请保留本博客链接或标注来源。博客地址:开飞机的乔巴

作者简介:开飞机的乔巴(WeChat:zhangzheng-thu),现主要从事机器人抓取视觉系统以及三维重建等3D视觉相关方面,另外对slam以及深度学习技术也颇感兴趣,欢迎加我微信或留言交流相关工作。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容