当前位置: 首页 > news >正文

利用OpenCV进行指纹识别的案例

代码实现:

import cv2def 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)# 创建FLANN匹配器flann = cv2.FlannBasedMatcher()# 使用k近邻匹配(des1中的每个描述符与des2中的最近两个描述符进行匹配)matches = flann.knnMatch(des1, des2, k=2)ok = []for m, n in matches:# 根据Lowe's比率测试,选择最佳匹配if m.distance < 0.8 * n.distance:ok.append((m,n))# 统计通过筛选的匹配数量num = len(ok)if num >= 500:result = "认证通过"else:result = "认证失败"return resultif __name__ == "__main__":src1 = cv2.imread("src1.BMP")cv_show(name='src1', img=src1)src2 = cv2.imread("src2.BMP")cv_show(name='src2', img=src2)model = cv2.imread("model.BMP")cv_show(name='model', img=model)result1 = verification(src1, model)result2 = verification(src2, model)print("src1验证结果为:", result1)print("src2验证结果为:", result2)

一、整体代码功能定位

这段代码的核心目标是基于 SIFT 特征匹配实现 “图像认证”
通过对比 “源图像”(src1/src2)与 “模板图像”(model)的特征相似度,判断源图像是否与模板匹配(匹配数≥500 则 “认证通过”,否则 “失败”)。
典型应用场景:商品防伪(模板为正品图像,源图为待检测商品图)、图像版权核验、同一物体一致性判断等。

二、逐模块代码解析

1. 工具函数 cv_show(name, img):简化图像显示
def cv_show(name, img):cv2.imshow(name, img)cv2.waitKey(0)

作用:封装 OpenCV 的图像显示逻辑,避免重复编写imshowwaitKey,提升代码复用性。

关键参数

name:图像显示窗口的名称(如 “src1”);

img:待显示的图像矩阵(OpenCV 读取的np.array类型)。

核心细节

cv2.waitKey(0):等待用户按下任意键后关闭窗口(若省略此句,窗口会一闪而过,无法观察图像);

注意:若图像读取失败(如路径错误),img会为None,调用此函数会报错,建议后续加 “图像读取有效性判断”(见优化点)。

2. 核心认证函数 verification(src, model):特征匹配与认证判断

这是代码的核心,分为特征提取→特征匹配→匹配过滤→结果判断四步,每一步都对应特征检测的关键技术:

步骤 1:创建 SIFT 特征提取器并提取特征
# 创建SIFT特征提取器
sift = cv2.SIFT_create()
# 提取源图像、模板图像的关键点(kp)和描述符(des)
kp1, des1 = sift.detectAndCompute(src, None)    # 源图像(src)
kp2, des2 = sift.detectAndCompute(model, None)  # 模板图像(model)

技术关联:呼应之前博客中 SIFT 的特性 —— 具备尺度不变性、旋转不变性,对光照 / 噪声鲁棒,适合需要稳定特征的认证场景。

关键概念

kp(关键点):存储特征点的位置、尺度(大小)、方向等空间信息;

des(描述符):128 维向量,描述关键点周围像素的纹理 / 灰度分布(SIFT 的核心,用于特征匹配);

None:掩膜参数,表示对全图像提取特征(若需仅检测图像局部,可传入掩膜矩阵)。

注意点:SIFT 属于opencv-contrib-python模块,若未安装会报错;且 SIFT 存在专利问题,商用需提前确认授权。

步骤 2:初始化 FLANN 匹配器并执行 K 近邻匹配
# 创建FLANN匹配器(快速最近邻搜索库)
flann = cv2.FlannBasedMatcher()
# K近邻匹配:每个源图像描述符找模板图像中2个最近邻
matches = flann.knnMatch(des1, des2, k=2)

匹配器选择逻辑
FLANN(Fast Library for Approximate Nearest Neighbors)是 “近似最近邻匹配”,比 “暴力匹配(BFMatcher)” 速度快 10-100 倍,适合 SIFT 这种高维描述符(128 维)的匹配,避免计算量过大。

参数k=2的意义
为每个des1(源图像描述符)在des2(模板图像描述符)中找2 个距离最近的匹配项—— 这是为后续 “Lowe's 比率测试” 做准备(过滤错误匹配的核心手段)。

细节对比:之前博客中 ORB 用 FLANN 时手动设置了index_params(LSH 算法),此处未设则用默认参数,对 SIFT 的 128 维浮点描述符,默认会选择适合浮点数据的匹配策略(如 KD 树),无需额外配置。

步骤 3:Lowe's 比率测试筛选有效匹配
ok = []
for m, n in matches:# 筛选条件:最佳匹配距离 < 0.8 × 次佳匹配距离if m.distance < 0.8 * n.distance:ok.append((m,n))

核心目的:过滤 “错误匹配”。
原理:若一个源图像特征点的 “最佳匹配”(m)和 “次佳匹配”(n)距离非常接近,说明这个特征点的匹配可信度低(可能是噪声或相似纹理干扰);反之,若最佳匹配远优于次佳匹配,则大概率是正确匹配。

阈值0.8的影响

阈值越小:筛选越严格,有效匹配数越少,但错误率低;

阈值越大:筛选越宽松,匹配数越多,但错误率可能上升;

ok列表:存储通过筛选的 “(最佳匹配,次佳匹配)” 对,后续统计长度即 “有效匹配数”。

步骤 4:根据匹配数判断认证结果
num = len(ok)
if num >= 500:result = "认证通过"
else:result = "认证失败"
return result

判断逻辑:通过 “有效匹配数” 间接反映源图像与模板图像的相似度—— 相似度越高,重叠区域越大,有效匹配数越多;反之则少。

阈值500的说明
这是经验值,需根据实际场景校准:

若图像尺寸大、纹理丰富(如细节多的产品图),特征点多,匹配数易达标,500合理;

若图像尺寸小、纹理少(如纯色背景的 logo),匹配数可能不足,需调低阈值(如100200);建议通过 “正样本”(已知与模板匹配的图)和 “负样本”(不匹配的图)测试,确定最优阈值(如取正样本最小匹配数的 90% 作为阈值)。

3. 主程序 if __name__ == "__main__"::流程执行与结果输出
if __name__ == "__main__":# 读取3张BMP图像(源图1、源图2、模板图)src1 = cv2.imread("src1.BMP")cv_show(name='src1', img=src1)src2 = cv2.imread("src2.BMP")cv_show(name='src2', img=src2)model = cv2.imread("model.BMP")cv_show(name='model', img=model)# 分别验证两个源图与模板图的匹配度result1 = verification(src1, model)result2 = verification(src2, model)# 输出认证结果print("src1验证结果为:", result1)print("src2验证结果为:", result2)

图像读取

读取BMP格式(无压缩、画质高,避免压缩导致的特征失真,适合特征检测);

潜在风险:若图像路径错误(如文件不在代码同级目录)、文件损坏,src1/src2/model会为None,后续detectAndCompute会报错(需加判断,见优化点)。

图像显示
调用cv_show显示 3 张图,目的是直观确认图像是否正确读取(如是否颠倒、是否为空白图),避免因图像读取问题导致认证结果误判。

结果输出
分别输出src1src2model的匹配结果,可快速判断哪个源图像与模板更相似(如src1认证通过,说明其与model相似度高)。

三、代码潜在问题与优化建议

  1. 增加图像读取有效性判断
    若图像读取失败(img is None),后续代码会崩溃,建议在读取后加判断:

    src1 = cv2.imread("src1.BMP")
    if src1 is None:print("src1图像读取失败!请检查路径或文件格式")exit()  # 或其他处理逻辑
    
  2. SIFT 专利问题优化
    若需商用,建议替换为无专利的ORB算法,只需修改特征提取部分:

    # 替换SIFT为ORB
    orb = cv2.ORB_create(nfeatures=2000)  # 增加特征点数量,补偿ORB精度
    kp1, des1 = orb.detectAndCompute(src, None)
    kp2, des2 = orb.detectAndCompute(model, None)
    
  3. 匹配数阈值500的动态优化
    固定阈值500通用性差,建议用 “相对比例” 替代绝对数值,例如:

    # 有效匹配数占总特征点的比例 ≥ 30% 则通过
    total_kp = min(len(kp1), len(kp2))  # 取源图和模板图特征点数量的较小值
    if num / total_kp >= 0.3:result = "认证通过"
    

    (比例0.3需根据样本校准,更适应不同尺寸 / 纹理的图像)。

  4. 可视化匹配结果
    目前仅显示原始图像,可增加 “绘制匹配线” 的功能,直观观察匹配质量

    # 在verification函数中添加匹配可视化(需传入cv_show)
    img_matches = cv2.drawMatchesKnn(src, kp1, model, kp2, ok, None, matchColor=(255,0,0))
    cv_show("Matches", img_matches)
    

    (通过观察蓝色匹配线是否集中在重叠区域,可判断匹配是否正确)。

四、代码核心逻辑总结

这段代码的本质是 **“特征相似度量化判断”**,流程可概括为:
图像读取 → SIFT特征提取(关键点+描述符) → FLANN K近邻匹配 → Lowe's过滤错误匹配 → 统计有效匹配数 → 按匹配数阈值判断认证结果

它利用了 SIFT 的尺度 / 旋转不变性,确保在不同拍摄角度、距离下仍能稳定匹配;FLANN 匹配器则保证了处理速度,适合批量认证场景。理解这些逻辑后,你可根据实际需求调整算法(如换 ORB)、阈值(如匹配数 / 比例)或增加可视化,让代码更贴合具体业务。


文章转载自:

http://Qqyy5HBn.xrpwk.cn
http://jkkKDhQ4.xrpwk.cn
http://fRlayAOy.xrpwk.cn
http://KMQETsGt.xrpwk.cn
http://i3Ccow4j.xrpwk.cn
http://reQ5WU6x.xrpwk.cn
http://3vzlaeqX.xrpwk.cn
http://emjxVlpO.xrpwk.cn
http://PZu8Ey6N.xrpwk.cn
http://2daYYstS.xrpwk.cn
http://IUSysAcp.xrpwk.cn
http://qk4SiJAh.xrpwk.cn
http://QUhRFu81.xrpwk.cn
http://8Eem9Su9.xrpwk.cn
http://WGMncVd6.xrpwk.cn
http://IweFQX47.xrpwk.cn
http://PxplDqon.xrpwk.cn
http://6tIVean8.xrpwk.cn
http://UQimSNVb.xrpwk.cn
http://8lX1jXgz.xrpwk.cn
http://MHluY6Dt.xrpwk.cn
http://SY5xwdT6.xrpwk.cn
http://mEgOWMQC.xrpwk.cn
http://FLgQybos.xrpwk.cn
http://3yA0ZX1F.xrpwk.cn
http://zNglAgkL.xrpwk.cn
http://sm9W3Dzr.xrpwk.cn
http://3JzP5UzW.xrpwk.cn
http://UJZXbY6v.xrpwk.cn
http://ECyCvSJY.xrpwk.cn
http://www.dtcms.com/a/380301.html

相关文章:

  • 知识点 | “比选”和“询价”
  • HarmonyOS多媒体开发:音视频播放与录制全解析
  • Linux文件IO——系统IO
  • Class51 深度循环神经网络
  • URLSearchParams
  • 使用 C# 设置 Excel 单元格格式
  • (二) Claude Code接入免费的Gemini-2.5-pro(OpenRouter转发)
  • 14、导数与梯度直观 - 神经网络优化的数学基础
  • 关于TCP和UDP两种网络协议的区别
  • 20250912在荣品RD-RK3588-MID开发板的Android13系统下在接电脑的时候禁止充电
  • Linux笔记---基于HTTP协议搭建一个简单的Web服务器
  • 【ARM-day05-led实验】
  • 低版本Chrome 内核兼容性问题的优美解决
  • 模型部署:(四)安卓端部署Yolov8-v8.2.99实例分割项目全流程记录
  • 使用自定义LLM和Embedding模型部署Vanna:基于RAG的Text-to-SQL生成
  • DataCollatorForCompletionOnlyLM解析(93)
  • 淘宝RecGPT:通过LLM增强推荐
  • Vue3 中使用 DOMPurify 对渲染动态 HTML 进行安全净化处理
  • 比较 iPhone:全面比较 iPhone 17 系列
  • 【Doris】集群介绍
  • 从“能写”到“能干活”:大模型工具调用(Function-Calling)的工程化落地指南
  • golang程序内存泄漏分析方法论
  • Go 语言 MQTT 消息队列学习指导文档
  • 基于数据挖掘技术构建电信5G客户预测模型的研究与应用
  • 【AI】pickle模块常见用途
  • 智慧园区,智启未来 —— 重塑高效、绿色、安全的产业新生态
  • MySQL 8新特性
  • 腾讯开源Youtu-GraphRAG
  • QT M/V架构开发实战:QStringListModel介绍
  • 【数据结构】Java集合框架:List与ArrayList