这个利用了前面学到的SIFT特征检测来实现的,然后这里主要就是引入了一个新的匹配器。这里
匹配是用KNN算法进行匹配的。下面来看下细节。
介绍函数
由于要频繁展示,所以这里定义了一个函数。
def cv_show(name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
导入图片
if __name__ == "__main__":
# 读取图像
src1 = cv2.imread("zhiwen3.bmp")
src2 = cv2.imread("zhiwen2.bmp")
model = cv2.imread("zhiwen1.bmp")
# 检查图像是否成功加载
if src1 is None or src2 is None or model is None:
print("错误: 无法加载图像文件")
else:
# 显示图像(需要指定窗口名称)
cv_show('src1', src1)
cv_show('src2', src2)
cv_show('model', model)
# 进行认证验证
result1 = verification(src1, model)
result2 = verification(src2, model)
print("src1验证结果为:", result1)
print("src2验证结果为:", result2)
可以看到这里导入了三张图片,一张目标图片,两张图片。然后打印出结果
匹配函数
def verification(src, model):
# 创建SIFT特征提取器
sift = cv2.SIFT_create()
这里创建了一个SIFT特征提取器,前面一篇文章讲过的。
# 检测关键点和计算描述符
kp1, des1 = sift.detectAndCompute(src, None) # 源图像 第二个参数 掩膜
kp2, des2 = sift.detectAndCompute(model, None) # 模板图像
然后这里返回了重要信息kp和des
kp
- 位置信息 (
pt
):关键点在图像中的坐标位置 (x, y)(重要,后面要用来标注出匹配点) - 尺度信息 (
size
):关键点被检测到的尺度级别 - 方向信息 (
angle
):关键点的主方向,用于实现旋转不变性 - 响应强度 (
response
):表示该特征点的显著程度
des
描述符的特点:
- 通常是高维向量(如SIFT描述符是128维)
- 描述了关键点周围区域的视觉外观
- 对光照变化、旋转、尺度变化具有一定的不变性
- 相似的图像区域会产生相似的描述符向量
# 检查是否有足够的特征点
if des1 is None or des2 is None or len(des1) < 2 or len(des2) < 2:
return "认证失败(特征点不足)"
检测看数量够不够匹配了,有时候特征太少,匹配不成功出现异常。
# 创建FLANN匹配器
flann = cv2.FlannBasedMatcher()
# 使用K近邻匹配
matches = flann.knnMatch(des1, des2, k=2)
建立了一个FLANN匹配器,用于直接传入两个的描述符的特点,然后就可以匹配了
# 应用Lowe's比率测试筛选优质匹配
good_matches = []
for m, n in matches:
if m.distance < 0.7 * n.distance: # 通常使用0.7-0.8的比率
good_matches.append(m)
这里我们前面参数k=2,是检测我们这个点对应匹配两个点,然后去计算这两个点距离我们点的欧氏距离,然后得出如果两个距离很接近就说明我们点匹配失败。
# 统计优质匹配数量
num = len(good_matches)
得到匹配点的个数,这里也可以看作匹配度
# 可视化匹配结果(可选)
img_match = cv2.drawMatches(src, kp1, model, kp2, good_matches, None,
flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
cv_show('匹配结果', img_match)
这里是可视化结果的一个方法。
# 根据匹配数量判断认证结果
if num >= 500: # 阈值可根据实际情况调整
result = "认证通过"
else:
result = "认证失败"
return f"{result} (匹配点: {num})"
总体代码
import cv2
import numpy as np # 需要添加此导入
def cv_show(name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
def verification(src, model):
# 创建SIFT特征提取器
sift = cv2.SIFT_create()
# 检测关键点和计算描述符
kp1, des1 = sift.detectAndCompute(src, None) # 源图像 第二个参数 掩膜
kp2, des2 = sift.detectAndCompute(model, None) # 模板图像
# 检查是否有足够的特征点
if des1 is None or des2 is None or len(des1) < 2 or len(des2) < 2:
return "认证失败(特征点不足)"
# 创建FLANN匹配器
flann = cv2.FlannBasedMatcher()
# 使用K近邻匹配
matches = flann.knnMatch(des1, des2, k=2)
# 应用Lowe's比率测试筛选优质匹配
good_matches = []
for m, n in matches:
if m.distance < 0.7 * n.distance: # 通常使用0.7-0.8的比率
good_matches.append(m)
# 统计优质匹配数量
num = len(good_matches)
# 可视化匹配结果(可选)
img_match = cv2.drawMatches(src, kp1, model, kp2, good_matches, None,
flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
cv_show('匹配结果', img_match)
# 根据匹配数量判断认证结果
if num >= 500: # 阈值可根据实际情况调整
result = "认证通过"
else:
result = "认证失败"
return f"{result} (匹配点: {num})"
if __name__ == "__main__":
# 读取图像
src1 = cv2.imread("zhiwen3.bmp")
src2 = cv2.imread("zhiwen2.bmp")
model = cv2.imread("zhiwen1.bmp")
# 检查图像是否成功加载
if src1 is None or src2 is None or model is None:
print("错误: 无法加载图像文件")
else:
# 显示图像(需要指定窗口名称)
cv_show('src1', src1)
cv_show('src2', src2)
cv_show('model', model)
# 进行认证验证
result1 = verification(src1, model)
result2 = verification(src2, model)
print("src1验证结果为:", result1)
print("src2验证结果为:", result2)