OpenCV-Python教程:41.特征匹配

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV-Python教程:41.特征匹配相关的知识,希望对你有一定的参考价值。

参考技术A Brute-Force匹配器基础

Brute-Force匹配器很简单,它取第一个集合里一个特征的描述子并用第二个集合里所有其他的特征和他通过一些距离计算进行匹配。最近的返回。

对于BF匹配器,首先我们得用cv2.BFMatcher()创建BF匹配器对象.它取两个可选参数,第一个是normType。它指定要使用的距离量度。默认是cv2.NORM_L2。对于SIFT,SURF很好。(还有cv2.NORM_L1)。对于二进制字符串的描述子,比如ORB,BRIEF,BRISK等,应该用cv2.NORM_HAMMING。使用Hamming距离度量,如果ORB使用VTA_K == 3或者4,应该用cv2.NORM_HAMMING2

第二个参数是布尔变量,crossCheck模式是false,如果它是true,匹配器返回那些和(i, j)匹配的,这样集合A里的第i个描述子和集合B里的第j个描述子最匹配。两个集合里的两个特征应该互相匹配,它提供了连续的结果,

当它创建以后,两个重要的方法是BFMatcher.match()和BFMatcher.knnMatch()。第一个返回最匹配的,第二个方法返回k个最匹配的,k由用户指定。当我们需要多个的时候很有用。

想我们用cv2.drawKeypoints()来画关键点一样,cv2.drawMatches()帮我们画匹配的结果,它把两个图像水平堆叠并且从第一个图像画线到第二个图像来显示匹配。还有一个cv2.drawMatchesKnn来画k个最匹配的。如果k=2,它会给每个关键点画两根匹配线。所以我们得传一个掩图,如果我们想选择性的画的话。

让我们各看一个SURF和ORB的例子(都使用了不同的距离度量)

使用ORB描述子的Brute-Force匹配

这里我们会看到如何匹配两个图片的里的特征。在这个例子里,我有一个查询图像和一个训练图像,我们用特征匹配来在训练图像里找查询图像。

我们使用SIFT描述子来匹配特征,所以让我们先加载图像,找到描述子。

接着我们用距离度量cv2.NORM_HAMMING创建一个BFMatcher对象,crossCheck设为真。然后我们用Matcher.match()方法来获得两个图像里最匹配的。我们按他们距离升序排列,这样最匹配的(距离最小)在最前面。然后我们画出最开始的10个匹配(为了好看,你可以增加)

下面是结果:

什么是匹配器对象?

matches = bf.match(des1, des2)的结果是DMatch对象列表。这个DMatch对象有下面的属性:

·DMatch.distance - 描述子之间的距离。越低越好

·DMatch.trainIdx - 训练描述子里的描述子索引

·DMatch.queryIdx - 查询描述子里的描述子索引

·DMatch.imgIdx - 训练图像的索引

用SIFT描述子和比率测试的Brute-Force 匹配

这次,我们使用BFMatcher.knnMatch()来获得k个最匹配的。在这个例子里,我们设置k=2这样我们可以应用比率检测。

看下面的结果

基于FLANN的匹配器

FLANN是快速估计最近邻的库。它包含了一些为大数据集内搜索快速近邻和高维特征的优化算法。它在大数据集的时候比BFMatcher更快。

对于基于FLANN的匹配器,我们需要传两个字典指定要用的算法,他们相关的参数等。第一个是IndexParams。对于更多算法,要传的信息参看FLANN的文档。作为总结,对于像SIFT,SURF等的算法,你可以传下面的:

当使用ORB,你可以传下面的。注释里的值是推荐的值。但是在有些情况下不提供需要的结果。其他的值工作正常。

第二个字典是SearchParams,它指定了索引里的树应该被递归遍历的次数。更高的值带来更高的准确率。但是也花更多时间,如果你想改变值,search_params = dict(checks=100).

通过这些信息,我们可以开始了:

结果:

END

OpenCV-Python教程:38.FAST角点检测算法

参考技术A 理论

我们看到了一些特征检测算法,他们很多都不错,但是从实时应用的角度看,他们都不够快,一个最好的例子是SLAM(同步定位与地图创建)移动机器人没有足够的计算能力。

作为解决方案,FAST(加速切片测试特征)算法被提出,Edward Rosten和Tom Drummond 2006年在他们的论文“Machine learning for high-speed corner detection”提出,并在2010年最后修订,算法的基本大意如下:

使用FAST进行特征检测

1.选择一个图像里的像素p用来识别是不是一个兴趣点,它的强度是Ip

2.选择一个合适的阈值t

3.在要测试的像素周围找16个像素的圆

4.现在如果存在一个在圆内(16像素的)的n个连续像素集合,他们都比Ip + t要亮,或者都比Ip - t 要暗(用白虚线显示),那p就是角, n取12。

5.用一个高速测试来排除大量非角。这个测试只检查1,9,5和13位置的像素(首先1和9会测试是否他们太亮或者太暗,如果是,再检查5和13)。如果p是角,那么至少3个都比Ip+t要亮或者比Ip-t要暗,如果不是这样,那么p不可能是角。这个检测器展现了高性能,但是有几个缺陷:

·当n< 12时不能拒绝很多备选点

·像素的选择不是可选的,因为它的效率依赖问题和角的分布。

·高速测试的结果被丢弃了

·会检测出多个爱挨在一起的特征

机器学习角点检测

1.选择一组图像进行训练(最好从目标应用范围内)

2.运行FAST算法来对每个图像进行特征点查找

3.对每个特征点,存下周围的16个像素作为向量。所有图像做完以后得到特征向量P。

4.这16个像素里的每个像素(设为x)可以有下面的三个状态:

5.根据这些状态,特征向量P被分成3个子集,Pd, Ps, Pb.

6.定义个新的布尔变量Kp,如果p是角就是真反之为假。

7.使用ID3算法(决策树分类)来查询每个子集,对于每个true类用变量Kp,它选择x来得出一个备选像素是否是角的信息。

8.对所有子集迭代直到为0

9.创建的决策树用来对其他图形做fast检测

非极大值抑制

在临近位置检测多个兴趣点是另一个问题,可以使用非极大值抑制来解决。

1.计算一个分数函数,V是所有检测到的特征点,V是p和16个围着的像素值得绝对差。

2.计算两个相邻关键点的V值

3.丢掉V值低的那个

总结:

它比其他存在的角点算法要快几倍

但是它对高噪点情况来说不健壮,依赖阈值

OpenCV里的FAST特征检测

它和其他OpenCV里的特征检测类似,如果你愿意,你可以指定阈值,是否使用非极大值抑制,要用的邻居等。

对于邻居,定义了三个标志位, cv2.FAST_FEATURE_DETECTOR_TYPE_5_8, cv2.FAST_FEATURE_DETECTOR_TYPE_7_12和cv2.FAST_FEATURE_DETECTOR_TYPE_9_16.

看结果,第一个图像显示了使用了非极大值抑制的FAST,第二个是没有使用非极大值抑制的。

END

以上是关于OpenCV-Python教程:41.特征匹配的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV-Python实战(12)——一文详解AR增强现实

opencv-python下简单KNN分类识别

[OpenCV-Python] OpenCV 中图像特征提取与描述 部分 V

OpenCV-Python实战(15)——面部特征点检测详解(仅需5行代码学会3种面部特征点检测方法)

OpenCV-Python17.OpenCV的图像轮廓——轮廓特征

OpenCV-Python之——图像SIFT特征提取