OpenCv高阶(六)——指纹识别
文章目录
- 前言
- 指纹识别代码解释
- 一、环境依赖与工具函数
- 二、核心验证函数:verification()
- 三、相似特征统计函数:get_num()
- 四、数据库搜索函数:get_ID()
- 五、ID转姓名映射函数:get_name()
- 六、主程序流程
- 完整代码
- 总结
前言
本文通过Python代码实现了一个基于SIFT特征和FLANN匹配器的指纹识别系统,能够从数据库中快速匹配目标指纹并输出识别结果。
指纹识别代码解释
一、环境依赖与工具函数
import cv2
import osdef cv_show(name, img):cv2.imshow(name, img)cv2.waitKey(0)
功能说明:
cv_show() 是一个可视化辅助函数,用于显示图像并等待键盘输入后关闭窗口。
虽然主流程未调用此函数,但在调试阶段可用于查看中间图像处理结果(如关键点匹配效果)。
二、核心验证函数:verification()
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的点,K值就是设置点的个数matches=flann.knnMatch(des1,des2,k=2)#match的参数:match的值会显示,测试的第几个点与模板第几个点之间的距离。#distance:使用欧式距离计算距离#queryIdx: 测试图像的特征点描述符的下标(第几个特征点的描述符),同时也是描述符对应特征点的下标,测试的第几个点,#trainIdx:样本(模板)图像的特征点描述符下标,同时也是描述符对应特征点的下标,模板图片的第几个点#进行比较筛选ok=[]#因为前面设置了K近邻的点数,所以match有两个值,一个是距离比较近,另一个则很远,这种情况是比较符合的,如果两个点距离待匹配图像#特征点的距离相差不多,则这个点不符合要求,应该过滤掉。for m,n in matches:#这里的if表示距离较近的距离小于较长距离的0.8,则表示两个距离相差很大。if m.distance < 0.8 *n.distance:ok.append(m)num=len(ok)#如何模板图和待识别图有超过500以上的特征可以被分为一类,则说明认证成功,否则认证失败if num >=500:result = "认证成功"else:result="认证失败"return result
功能解析:
特征提取:
使用SIFT算法提取输入图像(src)和模板图像(model)的关键点(kp)和描述符(des)。
SIFT对旋转、缩放、光照变化具有鲁棒性,适合指纹特征识别。
特征匹配:
采用FLANN快速近似最近邻匹配器加速特征匹配过程。
knnMatch()返回每个特征点的最近2个邻域匹配结果。
筛选优质匹配:
根据Lowe’s比率测试(0.8阈值)过滤误匹配,保留高置信度匹配对。
认证逻辑:
若优质匹配数≥500,则认为认证成功,否则失败。
三、相似特征统计函数:get_num()
def get_num(src, model):""":param src: 要识别指纹的路径:param model: 模板路径:return: 返回模板与测试图片之间,相似特征的数量"""img1 = cv2.imread(src)img2 = cv2.imread(model)sift = cv2.SIFT_create()kp1, des1 = sift.detectAndCompute(img1, None)kp2, des2 = sift.detectAndCompute(img2, None)flann = cv2.FlannBasedMatcher()matches = flann.knnMatch(des1, des2, k=2)ok = []for m, n in matches:if m.distance < 0.8 * n.distance:ok.append(m)return len(ok)
功能解析:
与verification()逻辑相似,但返回具体匹配数量而非认证结果。
用于后续遍历数据库时量化两个指纹的相似度。
四、数据库搜索函数:get_ID()
def get_ID(src, database):max = 0for file in os.listdir(database):model = os.path.join(database, file)num = get_num(src, model)print("文件名:", file, "匹配点个数", num)if num > max:max = numname = fileID = name[0]return 9999 if max < 100 else ID
实现逻辑:
遍历数据库:
遍历指定database路径下的所有模板文件,逐个计算与输入指纹的匹配数。
最佳匹配筛选:
记录最高匹配数对应的文件名,并提取文件名首字符作为用户ID(假设文件名格式为ID_name.jpg)。
阈值判定:
若最高匹配数<100,返回9999表示未找到匹配。
五、ID转姓名映射函数:get_name()
def get_name(ID):nameID = {0: '张三', 1: '李四', 2: '王五', 3: '赵六', 4: '朱七', 5: '钱八', 6: '曹九', 7: '王二麻子', 8: 'andy', 9: 'anna', 9999: '未找到目标'}return nameID.get(int(ID))
功能说明:
通过预设字典将数字ID映射为真实姓名,增强结果可读性。
六、主程序流程
if __name__ == '__main__':src = '../data/newzw.bmp'database = '../data/database'ID = get_ID(src, database)name = get_name(ID)print('识别结果为:', name)
执行步骤:
指定待识别指纹路径(src)和模板数据库路径(database)。
调用get_ID()搜索最佳匹配,获得用户ID。
将ID转换为姓名并输出结果。
指纹库
待识别的指纹
最终识别结果
匹配原理,通过比较能匹配上的点的个数,匹配上的点数越多说明指纹越相近,越可能是同一个人的指纹。
完整代码
import cv2
import os
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)#创建Flann匹配器flann = cv2.FlannBasedMatcher()#使用K近邻匹配(des1中的每个描述符周围距离它最近的des2的点,K值就是设置点的个数matches=flann.knnMatch(des1,des2,k=2)#match的参数:match的值会显示,测试的第几个点与模板第几个点之间的距离。#distance:使用欧式距离计算距离#queryIdx: 测试图像的特征点描述符的下标(第几个特征点的描述符),同时也是描述符对应特征点的下标,测试的第几个点,#trainIdx:样本(模板)图像的特征点描述符下标,同时也是描述符对应特征点的下标,模板图片的第几个点#进行比较筛选ok=[]#因为前面设置了K近邻的点数,所以match有两个值,一个是距离比较近,另一个则很远,这种情况是比较符合的,如果两个点距离待匹配图像#特征点的距离相差不多,则这个点不符合要求,应该过滤掉。for m,n in matches:#这里的if表示距离较近的距离小于较长距离的0.8,则表示两个距离相差很大。if m.distance < 0.8 *n.distance:ok.append(m)num=len(ok)#如何模板图和待识别图有超过500以上的特征可以被分为一类,则说明认证成功,否则认证失败if num >=500:result = "认证成功"else:result="认证失败"return resultdef get_num(src,model):""":param src: 要识别指纹的路径:param model: 模板路径:return: 返回模板与测试图片之间,相似特征的数量"""img1=cv2.imread(src)img2=cv2.imread(model)sift=cv2.SIFT_create()kp1,des1=sift.detectAndCompute(img1,None)kp2,des2=sift.detectAndCompute(img2,None)flann=cv2.FlannBasedMatcher()matches=flann.knnMatch(des1,des2,k=2)ok=[]for m,n in matches:if m.distance<0.8*n.distance:ok.append(m)num=len(ok)return numdef get_ID(src,database):max=0for file in os.listdir(database):model = os.path.join(database,file)num=get_num(src,model)print("文件名:",file,"匹配点个数",num)if num>max:max=numname=fileID=name[0]if max <100:ID=9999return IDdef get_name(ID):nameID={0:'张三',1:'李四',2:'王五',3:'赵六',4:'朱七',5:'钱八',6:'曹九',7:'王二麻子',8:'andy',9:'anna',9999:'未找到目标'}name=nameID.get(int(ID))return nameif __name__ == '__main__':src='../data/newzw.bmp'database='../data/database'ID=get_ID(src,database)name=get_name(ID)print('识别结果为:',name)
需注意自己的指纹库与待识别的指纹路径需要更改,要与自己的实际路径一致。
总结
本代码实现了一套完整的指纹识别系统,结合SIFT的稳定性与FLANN的高效匹配,适用于小规模数据库的快速身份认证场景。