BF匹配器有两种匹配方法,普通的match和基于KNN的match方法(knn是k-nearest-ner***or的缩写,用在这里也就只是对距离进行排序,然后取最小的前k个而已)。第一个只返回最好的匹配结果,第二个返回k个最好的匹配结果,k是用户指定的。第二种在某些时候会很有用。CV2.drawMatches是帮助我们来画出匹配结果的一个函数。它会把最好的匹配结果点对用线连起来。drawMatchKnn可以把最好的k个结果显示出来,还是用连线的方式,如果我们只想显示某些特定连线,可以用掩码。
我们这里还是简单了解一下BRISK和汉明距离。
参考https://blog.csdn.net/hujingshuang/article/details/47045497
BRISK
尺度空间的创建都是大同小异。
中间在特征点检测和FAST有不同之处,还多了亚像素插值的过程,还有一种叫做FREAK的算法,参考https://blog.csdn.net/hujingshuang/article/details/47060677
和https://blog.csdn.net/lhanchao/article/details/52744514
FREAK
这个做法和ORB中rBRIEF的做法类似。
也就是说其实FREAK是一种特征描述方法。然后来看看什么叫做汉明距离:
汉明距离是使用在数据传输差错控制编码里面的,汉明距离是一个概念,它表示两个(相同长度)字对应位不同的数量,我们以d(x,y)表示两个字x,y之间的汉明距离。对两个字符串进行异或运算,并统计结果为1的个数,那么这个数就是汉明距离。
opencv中的特征匹配
我们先来认识一下上面用到的函数或者类。
上面是两种特征匹配和描述算子的用法。匹配器:
k是我们可以指定的参数。还有画出匹配结果的函数(knn的也在下面):
matchcolor是线的颜色,如果给-1就会产生随机的颜色。
好的,然后我们看一个例子,虽然官方用的是SURF和ORB,不过我就用这一讲的BRISK和FREAK来尝试一下。
用的是
这两幅图。上面的代码会有版本的一些问题,请参看我下面的代码:
我们得到的matches是一些匹配完的结果。这个结果应该是点集的形式。matches是一个列表,里面的元素是DMatch类的实例对象。
这个类有这么几种属性。
第六个参数outImg不能少,我们其实已经在左边给过了,所以这里给None。
可以看出来,有些地方还是完全不搭边的点还是匹配到一起了。比如图中那些斜线。再试一试FREAK:
感觉交叉的线还是很多呢。接下来是尝试kNN:
可以看到左边图像上一个点确实有5条线出发呢。
这样也是可以的。
但是注意不能前后矛盾:
crossCheck=True的时候,就已经注定后面的k=1,如果后面k不等于1,就会在knnMatch这里报错。不是knn的画图函数画不出n个点的结果,即使k=1(这个应该是matches和knnMatches的结果不太一样)
如果是knnMatch的结果,列表的元素还是一个列表,里面存放着k个DMatch类实例对象。
我们还可以显示一定数量的匹配对。这个时候其实很简单,我们只需要:
它显示的就只有10个点对的连接了,其它点还会标出来,但是不会连接。不过匹配效果不是很好呢。
官方文档里面的:matches=sorted(matches,key=lambdax:x.distance)是根据距离来排序。参考https://www.cnblogs.com/wuchenyu/p/9114195.html
这个匹配效果就好多了,毕竟我们选择的是最好的10对点,不过为什么matches顺序被打乱了,还能知道对应点是谁呢?因为原来kp1,kp2和matches有某种对应关系,打乱了会怎么样?关于这一点,不要忘了:
这里面是存有序号的,也就是说只要原来的kp1,kp2顺序不被打乱,就能对应起来。我打乱一下试试:
明显就不对应了。
在用knn的时候还可以设定条件:
bf=CV2.BFMatcher()
matches=bf.knnMatch(des1,des2,k=2)
good=[]
form,ninmatches:
ifm.distance