OpenCV学习笔记-brute_force特征匹配

Brute-Force匹配器也就是蛮力匹配器,顾名思义,它的工作原理是:在第一幅图像上选取一个关键点,然后依次与第二幅图像的每个关键点进行(描述符)距离测试,最后返回距离最近的关键点。

对于BF匹配器,我们首先要使用cv.BFMatcher()创建一个BFMatcher对象。它有两个可选参数。

第一个是normType,它用来指定要使用的距离测试类型。
默认值为cv.NORM_L2,这个类型很适合SIFT和SURF等(cv.NORM_L1也可以)。对于使用二进制描述符的ORB,BRIEF,BRISK算法等,要使用cv.NORM_HAMMING,这样就会返回两个测试对象间的汉明距离。如果ORB算法的参数设置为MTA_K==3或4,normType就应该设置为cv.NORM_HAMMING2。

第二个参数是布尔变量corssCheck,默认值为False。如果设置为True,匹配条件就会更加严格,只有到A中的第i个特征点与B中的第j个特征点距离最近,并且B中的第j个特征点到A中的第i个特征点也是最近(A中没有其他的点到j的距离最近)时才会返回最佳匹配(i, j)。也就是这两个特征点要互相匹配才行。这样就能提供统一的结果,这可以用来代替D.Lowe在SIFT文章中提出的比值测试方法。

BFMatcher对象有两个方法,bf.match()和bf.knnMatch()。第一个方法会返回最佳匹配。第二个方法为每个关键点返回k个匹配(降序排列之后取前K个),其中K是由用户设定的。结果出了匹配之外还要做其他事情的话可能会用上(比如进行比值测试)。

返回对象是一个DMatch对象列表。这个DMatch对象具有下列属性:
1、DMatch.distance - 描述符之间的距离。越小越好。

2、 DMatch.trainIdx- 目标图像中描述符的索引。
3、DMatch.queryIdx - 查询图像中描述符的索引。
4、DMatch.imgIdx - 目标图像的索引。

就像使用cv.drawKeyPoints()绘制关键点一样,我们使用cv.drawMatches()来绘制匹配的点。它会将两幅图像水平排列,然后在最近匹配的点之间绘制直线(从原图像到目标图像)。如果前面使用的是bf.knnMatch(),就使用函数cv.drawMatchsKnn()为每个关键点和它的K个最佳匹配点绘制匹配线。如果k等于2,就会为每个关键点绘制2条最佳匹配直线。如果我们要选择性绘制的话就给函数传入一个掩模。

具体代码:
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt


img1 = cv.imread('img/box.png', 0)
img2 = cv.imread('img/box_in_scene.png', 0)
def orb_bf_demo():
    #创建ORB对象
    orb = cv.ORB_create()
    kp1, des1 = orb.detectAndCompute(img1, None)
    kp2, des2 = orb.detectAndCompute(img2, None)
    #创建bf对象,并设定初始值
    bf = cv.BFMatcher(cv.NORM_HAMMING, crossCheck=True)

    matches = bf.match(des1, des2)

    #将匹配结果按特征点之间的距离进行降序排列
    matches = sorted(matches, key= lambda x:x.distance)

    #前10个匹配
    img3 = cv.drawMatches(img1, kp1, img2, kp2, matches[:10], None, flags=2)

    cv.namedWindow('img',cv.WINDOW_AUTOSIZE)
    cv.imshow('orb_img',img3)

def sift_bf_demo():
    #创建SIFT对象
    sift = cv.xfeatures2d.SIFT_create()

    kp1, des1 = sift.detectAndCompute(img1, None)
    kp2, des2 = sift.detectAndCompute(img2, None)
    #使用默认参数 cv.Norm_L2 ,crossCheck=False
    bf = cv.BFMatcher()
    matches = bf.knnMatch(des1, des2, k=2)
    #比值测试,首先获取与A距离最近的点B(最近)和C(次近),只有当B/C小于阈值时(0.75)才被认为是匹配
    #因为假设匹配是一一对应的,真正的匹配的理想距离是0
    good = []
    for m, n in matches:
        if m.distance < 0.75*n.distance:
            good.append([m])
    img3 = cv.drawMatchesKnn(img1, kp1, img2, kp2, good, None, flags=2)
    cv.namedWindow('img', cv.WINDOW_AUTOSIZE)
    cv.imshow('sift_img', img3)
orb_bf_demo()
sift_bf_demo()
cv.waitKey(0)
cv.destroyAllWindows()

效果:
都选取前十个最佳匹配

使用ORB描述符进行BF匹配:
使用SIFT进行BF匹配:

猜你喜欢

转载自blog.csdn.net/qq_36387683/article/details/80577737
今日推荐