文章目录
前言
本文通过Python代码实现了一个基于SIFT特征和FLANN匹配器的指纹识别系统,能够从数据库中快速匹配目标指纹并输出识别结果。
指纹识别代码解释
一、环境依赖与工具函数
import cv2
import os
def 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 = 0
for file in os.listdir(database):
model = os.path.join(database, file)
num = get_num(src, model)
print("文件名:", file, "匹配点个数", num)
if num > max:
max = num
name = file
ID = 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 result
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)
num=len(ok)
return num
def get_ID(src,database):
max=0
for file in os.listdir(database):
model = os.path.join(database,file)
num=get_num(src,model)
print("文件名:",file,"匹配点个数",num)
if num>max:
max=num
name=file
ID=name[0]
if max <100:
ID=9999
return ID
def get_name(ID):
nameID={0:'张三',1:'李四',2:'王五',3:'赵六',4:'朱七',5:'钱八',
6:'曹九',7:'王二麻子',8:'andy',9:'anna',9999:'未找到目标'}
name=nameID.get(int(ID))
return name
if __name__ == '__main__':
src='../data/newzw.bmp'
database='../data/database'
ID=get_ID(src,database)
name=get_name(ID)
print('识别结果为:',name)
需注意自己的指纹库与待识别的指纹路径需要更改,要与自己的实际路径一致。
总结
本代码实现了一套完整的指纹识别系统,结合SIFT的稳定性与FLANN的高效匹配,适用于小规模数据库的快速身份认证场景。