利用sift提取特征完成指纹识别
直接使用sift的方法detectAndCompute()分别返回验证图src和模板图model的关键点keypoint和关键点的描述符descripter,此过程可同时完成“Detect”与“Compute”。调用上一步自定义的getNum()方法得到该图片与database中的图片匹配的关键点个数,并将与每个指纹照片的匹配点个数打印出来。目标:捕捉待识别指纹与指纹库(database)中所有指
目录
一.指纹识别案例
目标:捕捉待识别指纹与指纹库(database)中所有指纹图片的相似度,找出匹配度最高的指纹。
待识别指纹src.BMP:
关键实现流程与技术要点:
- 文件遍历: 使用
os.listdir()
遍历指纹库文件夹内的所有指纹图片文件(如 .bmp 格式)。 - 路径构建: 利用
os.path.join()
将文件夹路径与单个文件名组合,生成可被程序读取的完整图像路径。 - SIFT特征提取与匹配: 类似于指纹验证,使用
cv2.SIFT_create()
提取待识别指纹和每一张库图的特征点,并利用FLANN
进行特征匹配。 - 匹配阈值判断: 设置了匹配成功点的数量阈值。当两个图像之间匹配到的“共同点”总数大于或等于当前记录的最大值时,才会更新最大值和对应的指纹文件名。
- 最终结果判定: 通过匹配成功的点数达到预设的最小阈值才能判定识别结果有效;若所有指纹的匹配点数均低于该阈值,则返回一个特殊ID(如“9999”)表示未找到匹配指纹。
1.计算两个指纹之间的匹配点个数
1.特征提取:
直接使用sift的方法detectAndCompute()分别返回验证图src和模板图model的关键点keypoint和关键点的描述符descripter,此过程可同时完成“Detect”与“Compute”。
2.匹配原则
匹配以k=2的方式进行,即对待匹配的描述符,寻找其在另一组描述符中最近邻和次近邻。
3.匹配成功依据:
只有当一个匹配的距离(d1)远远小于其对应的次近邻距离(d2)时,才认为该匹配是有效的。项目中设定的判据是d1 < d2 * 0.8。
最后返回匹配成功的关键点数量
'''------计算两个指纹之间的匹配点个数--------'''
def getNum(src, model):
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,n))
num=len(ok)
return num
2.获取指纹编号
'''------获取指纹编号--------'''
def getID(src, database):
max=0
for file in os.listdir(database):
model=os.path.join(database,file)
num=getNum(src,model)
print("文件名:",file,"匹配点个数:",num)
if num>max:
max=num
name=file
ID=name[0]
if max<100:#src不一定是库里面人的指纹
ID=9999
return int(ID)
利用os.listdir()遍历database中的所有指纹照片,再os.path.join()得到路径
调用上一步自定义的getNum()方法得到该图片与database中的图片匹配的关键点个数,并将与每个指纹照片的匹配点个数打印出来
通过if条件保存最大的匹配点个数和指纹文件名
最后返回文件名的索引[0]并转化为int型,方便后续字典取值
3.根据指纹编号获取对应姓名
def getName(ID):
nameID={
0:'张三',1:'李四',2:'王五',3:'赵六',4:'朱老七',5:'钱八',
6:'曹久',7:'王林',8:'andy',9:'john',9999:'没找到'
}
return nameID.get(ID)
实际就是定义一个字典根据传进来的ID值来获取对应的姓名
4.调用各方法
if __name__=='__main__':
src='src.BMP.bmp'
database='database'
ID=getID(src,database)
name=getName(ID)
print('识别结果为:',name)
二.在验证图和模板图上画出对应的关键点
我们只需要在计算匹配成功的关键点时做出改进即可
kp1_indexs和kp2_index2分别保存匹配成功的关键点索引
queryIdx可以返回匹配成功后验证图上对应的关键点索引
trainIdx可以返回匹配成功后模板图上对应的关键点索引
最后对这些索引遍历,利用索引来取出对应的关键点,pt属性可以返回该关键点对应的x,y坐标
cv.circle()在图上画出对应的远点,需传入圆心(x,y)即上面得到的关键点坐标和边界
def verification(src,model):
sift=cv2.SIFT_create()
kp1,des1=sift.detectAndCompute(src,None)
kp2, des2 = sift.detectAndCompute(model, None)
#创建FLANN匹配器
flann=cv2.FlannBasedMatcher()
matches=flann.knnMatch(des1,des2,k=2)
ok=[]
kp1_indexs = []
kp2_indexs = []
for m,n in matches:
if m.distance<0.4*n.distance:
ok.append((m,n))
kp1_indexs.append(m.queryIdx)
kp2_indexs.append(m.trainIdx)
for index_des1 in kp1_indexs:
(x,y)=kp1[index_des1].pt
cv2.circle(src, (int(x),int(y)),3,(0,0,255),-1)
for index_des2 in kp2_indexs:
(x,y)=kp2[index_des2].pt
cv2.circle(model, (int(x),int(y)),3,(0,0,255),-1)
完整代码:
import cv2
def cv_show(name,img):
cv2.imshow(name,img)
cv2.waitKey(0)
def verification(src,model):
sift=cv2.SIFT_create()
kp1,des1=sift.detectAndCompute(src,None)
kp2, des2 = sift.detectAndCompute(model, None)
#创建FLANN匹配器
flann=cv2.FlannBasedMatcher()
matches=flann.knnMatch(des1,des2,k=2)
ok=[]
kp1_indexs = []
kp2_indexs = []
for m,n in matches:
if m.distance<0.4*n.distance:
ok.append((m,n))
kp1_indexs.append(m.queryIdx)
kp2_indexs.append(m.trainIdx)
for index_des1 in kp1_indexs:
(x,y)=kp1[index_des1].pt
cv2.circle(src, (int(x),int(y)),3,(0,0,255),-1)
for index_des2 in kp2_indexs:
(x,y)=kp2[index_des2].pt
cv2.circle(model, (int(x),int(y)),3,(0,0,255),-1)
if __name__=='__main__':
src1=cv2.imread('src1.bmp')
src2=cv2.imread('src2.bmp')
model=cv2.imread('model.bmp')
cv_show('src1',src1)
cv_show('model',model)
result1=verification(src1,model)
cv_show('src1', src1)
cv_show('model', model)
补充说明:
cv2.drawMatchesKnn(src1,kp1,model,kp2,ok,None,flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)函数可以画出验证图与模板图关键点的对应关系
matched_image=cv2.drawMatchesKnn(src1,kp1,model,kp2,ok,None,flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
cv_show('matched_image',matched_image)
更多推荐
所有评论(0)