暴力特征匹配(Brute-Force Feature Matching) 是 OpenCV 中最基本、最直观的特征点匹配方法。它的原理非常简单:对查询图像中的每一个特征描述子,都要与训练图像中的所有描述子计算一次距离,从中选出距离最近的一个(或 k 个)作为匹配点。因为采取了穷举的搜索策略,所以称为“暴力”匹配。
在 OpenCV 中,主要通过 cv::BFMatcher 类来实现,它既支持单次最优匹配,也支持 k 近邻匹配,配合一些筛选策略(如交叉检验、Lowe’s ratio test)可以得到相当干净、准确的匹配结果。
| 优点 | 缺点 |
|---|---|
| 实现简单,总能找到全局最近邻 | 当特征点数量很大时计算量巨大 (O(N²)) |
| 匹配结果绝对精确(就所给距离度量而言) | 对高维大数据集几乎不可用 |
| 配合交叉检验、比率测试后鲁棒性好 | 不能处理实时、海量特征场景 |
通常,在特征点数量 < 几千 时,暴力匹配表现良好且简单可靠;当特征点超过数万 时,更适合使用 FLANN(快速近似最近邻)匹配器。
我们获取到图像特征点和描述子之后,可以将两幅图像进行特征匹配。
BF(Brute-Force)暴力特征匹配方法,通过枚举的方式进行特征匹配。
暴力匹配器很简单。它使用第一组(即第一幅图像)中一个特征的描述子,并使用一些距离计算将其与第二组中的所有其他特征匹配。并返回最接近的一个。
BFMatcher(normType, crossCheck)o normType计算距离的方式。
-NORM_L1,L1距离,即绝对值,SIFT和SURF使用
.NORML2,L2距离,默认值.即平方.SIFT和SURF使用
·HAMMING汉明距离.ORB使用ocrossCheck:是否进行交叉匹配,默认False.使用match函数进行特征点匹配,返回的对象为DMatch对象.该对象具有以下属性:
o DMatch.distance -描述符之间的距离。越低,它就越好。
o DMatch.trainldx-训练描述符中描述符的索引
o DMatch.queryldx-查询描述符中描述符的索引
o DMatch.imgldx-训练图像的索引
具体演示代码如下:
#暴力特征匹配
import cv2
print(cv2.getVersionString())
import numpy as np
from utils import plt_showimg
img1 = cv2.imread('./images/opencv1.png')
img2 = cv2.imread('./images/opencv2.png')
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# 创建特征检测对象
sift = cv2.SIFT_create()
#计算描述子
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)
#进行暴力匹配
# 匹配描述子
# bf = cv2.BFMatcher(cv2.NORM_L2, crossCheck=True)
bf = cv2.BFMatcher(cv2.NORM_L1)
# bf = cv2.BFMatcher(cv2.NORM_HAMMING)
# matches = bf.match(des1, des2)
# # 除了match可以进行匹配,还可以使用knnMatch
matches = bf.knnMatch(des1, des2, k=2)
print(len(matches))
# 绘制匹配结果
# result = cv2.drawMatches(img1, kp1, img2, kp2, matches, None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
# result = cv2.drawMatches(img1, kp1, img2, kp2, matches, None)
good = []
for m, n in matches:
#设定阈值,距离小于对方距离的0.7倍,我们认为是好的匹配点
if m.distance < 0.7 * n.distance:
good.append(m)
print(len(good))
result = cv2.drawMatchesKnn(img1, kp1, img2, kp2, [good], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
# 显示结果
plt_showimg(result, 'result')
展示效果图如下:

全部评论