opencv-096-描述子匹配

知识点

图像特征检测首先会获取关键点,然后根据关键点周围像素ROI区域的大小,生成描述子,完整的描述子向量就表示了一张图像的特征,是图像特征数据,这种方式也被称为图像特征工程,即通过先验模型与合理计算得到图像特征数据的过程,有了特征数据我们就可以利用特征数据实现对象检测与对象识别,这个最简单一个方法就是特征匹配,OPenCV提供了两种图像特征匹配的算法

  • 暴力匹配
  • FLANN匹配

其中FLANN是一种高效的数值或者字符串匹配算法,SIFT/SURF是基于浮点数的匹配,ORB是二值匹配,速度更快。对于FLANN匹配算法,当使用ORB匹配算法的时候,需要重新构造HASH。这个在C++的代码种做了演示。暴力匹配在Python代码种做了演示。对匹配之后的输出结果,根据距离进行排序,就会得到距离比较的匹配点,这个才是好的特征匹配。

代码(c++,python)

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
#define RATIO 0.4
using namespace cv;
using namespace std;

int main(int argc, char** argv) {
Mat box = imread("D:/images/box.png");
Mat scene = imread("D:/images/box_in_scene.png");
if (scene.empty()) {
printf("could not load image...\n");
return -1;
}
imshow("input image", scene);
vector<KeyPoint> keypoints_obj, keypoints_sence;
Mat descriptors_box, descriptors_sence;
Ptr<ORB> detector = ORB::create();
detector->detectAndCompute(scene, Mat(), keypoints_sence, descriptors_sence);
detector->detectAndCompute(box, Mat(), keypoints_obj, descriptors_box);

vector<DMatch> matches;
// ��ʼ��flannƥ��
// Ptr<FlannBasedMatcher> matcher = FlannBasedMatcher::create(); // default is bad, using local sensitive hash(LSH)
Ptr<DescriptorMatcher> matcher = makePtr<FlannBasedMatcher>(makePtr<flann::LshIndexParams>(12, 20, 2));
matcher->match(descriptors_box, descriptors_sence, matches);

// ����ƥ��
vector<DMatch> goodMatches;
printf("total match points : %d\n", matches.size());
float maxdist = 0;
for (unsigned int i = 0; i < matches.size(); ++i) {
printf("dist : %.2f \n", matches[i].distance);
maxdist = max(maxdist, matches[i].distance);
}
for (unsigned int i = 0; i < matches.size(); ++i) {
if (matches[i].distance < maxdist*RATIO)
goodMatches.push_back(matches[i]);
}

Mat dst;
drawMatches(box, keypoints_obj, scene, keypoints_sence, goodMatches, dst);
imshow("output", dst);

waitKey(0);
return 0;
}
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
"""
描述子匹配
"""

import cv2 as cv

box = cv.imread("images/box.png")
box_in_scene = cv.imread("images/box_in_scene.png")
cv.imshow("box", box)
cv.imshow("box_in_scene", box_in_scene)

# 创建ORB特征检测器
orb = cv.ORB_create()

# 得到特征关键点和描述子
kp1, des1 = orb.detectAndCompute(box, None)
kp2, des2 = orb.detectAndCompute(box_in_scene, None)

# 暴力匹配
bf = cv.BFMatcher(cv.NORM_HAMMING, crossCheck=True)
matchers = bf.match(des1, des2)

# 绘制匹配
matchers = sorted(matchers, key=lambda x: x.distance)
result = cv.drawMatches(box, kp1, box_in_scene, kp2, matchers[:15], None)
cv.imshow("orb-match", result)

cv.waitKey(0)
cv.destroyAllWindows()

结果

代码地址

github