计算机视觉系列(三):ORB特征点

图像的特征点

图像的特征点可以理解为图像中比较有代表性的点,这些点在相机视角发生少量变化后会保持不变,于是我们就可以在各个图像中找到相同的点。在SLAM的视觉里程计中,我们需要通过一帧帧连续拍摄的图像来对相机的运动进行估计,因此需要对每一帧图像中提取出特征点,通过这些点对相机的位姿估计进行讨论。

ORB特征点

ORB特征点(Oriented FAST and Rotated BRIEF)是对FAST关键点BRIEF特征描述子的一种结合与改进。

  • FAST关键点是一种角点,主要检测局部像素区域灰度变化明显的地方,因为只检测亮度,所以速度非常快;
  • BRIEF是一种二进制描述子,在提取完关键点后,对每个关键点计算描述子,用来描述关键点周围像素的信息,描述子的设计原则是“ 外观相似的特征应该具有相似的描述子”。
FAST关键点

虽然FAST关键点速度非常快,但是快有快的缺陷。首先,FAST关键点没有方向信息,因此当图像发生旋转之后,关键点对应的描述子会发生变化;此外,FAST关键点不具有尺度不变性,也就是说不同距离对着同一个物体拍照,远处看起来像关键点的地方,距离近了就可能不是关键点了。对于这两个问题,ORB特征点采用了如下方法进行解决。

  • 对于尺度问题,构建 图像金字塔,得到不同尺度下的不同分辨率图像,对于每一层图像提取特征点,最后再匹配到原图像,这样就实现了关键点的尺度不变性;
  • 对于旋转问题,ORB特征点采用了灰度质心法计算特征点的方向,通过特征点的方向实现关键点的旋转不变性。

举个例子

OpenCV提取图像特征点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <opencv2/opencv.hpp>
#include <iostream>
#include <chrono>
using namespace cv;
using namespace std;

#define EDGE_THRESHOLD 19

int main()
{
std::vector<cv::KeyPoint> keypoints;
Mat descriptors;
cv::Ptr<cv::FeatureDetector> detector = cv::ORB::create();
cv::Ptr<cv::DescriptorExtractor> descriptor = cv::ORB::create();

Mat image = imread("../distorted.png", IMREAD_COLOR);
//-- 第一步:检测 Oriented FAST 角点位置
detector->detect(image, keypoints);

//-- 第二步:根据角点位置计算 BRIEF 描述子
descriptor->compute(image, keypoints, descriptors);

Mat outimg;
drawKeypoints(image, keypoints, outimg, cv::Scalar::all(-1), cv::DrawMatchesFlags::DEFAULT);
imshow("原图", image);
imshow("OpenCV函数提取的ORB特征点", outimg);
imwrite("OpenCV提取的ORB特征点.jpg", outimg);
waitKey(0);
return 0;
}

运行结果:

原图
OpenCV提取的特征点