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

计算机视觉opencv之指纹识别补充图片拼接思考

一、指纹识别

1.上篇博客中讲到指纹识别以及对匹配上的点标出,这次我们实现让匹配对应的点连接起来,从连接的线上反应匹配的程度

这里和上篇博客中代码一样,只不过在函数中稍改动了,添加了src_matches=[]这个变量,以及后面对其的使用

import cv2 def cv_show(name,img): cv2.imshow(name,img) cv2.waitKey(0) def verification(src,model,show_matchs=False): sift=cv2.SIFT_create() kp1,des1=sift.detectAndCompute(src,None) kp2,des2=sift.detectAndCompute(model,None) flann=cv2.FlannBasedMatcher() matches=flann.knnMatch(des1,des2,k=2) ok=[] good_matches=[] src_matches=[] model_matches=[] for m,n in matches: if m.distance<0.4*n.distance: ok.append((m,n)) good_matches.append(m) src_matches.append(kp1[m.queryIdx].pt) model_matches.append(kp2[m.trainIdx].pt) num=len(ok) if num >=50: result='认证通过' else: result='认证失败' if show_matchs and len(src_matches)>0: src_with_matches=src.copy() model_with_matches=model.copy() for (x,y) in src_matches[:100]: cv2.circle(src_with_matches,(int(x),int(y)),3,(0,0,255),-1) for (x,y) in model_matches[:100]: cv2.circle(model_with_matches,(int(x),int(y)),3,(0,0,255),-1) cv2.imshow('src_matches',src_with_matches) cv2.imshow('model_matches',model_with_matches) cv2.waitKey(0) match_img=cv2.drawMatches(src,kp1,model,kp2,good_matches[:100],None,flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS) cv2.imshow('pipei',match_img) cv2.waitKey(0)#1 return result,num,src_matches,model_matches if __name__=='__main__': src1=cv2.imread('zhiwen1.bmp') src2=cv2.imread('zhiwen2.bmp') model = cv2.imread('zhiwen_model.bmp') cv2.imshow('src1',src1) cv2.imshow('src2',src2) cv2.imshow('model',model) cv2.waitKey(0) reselt1,num1,src1_matches,model1_matches=verification(src1,model,show_matchs=True) reselt2,num2,src2_matches,model2_matches=verification(src2,model,show_matchs=True) print('src1的结果为:',reselt1,'匹配点数:{}'.format(num1)) print('src2的结果为:',reselt2,'匹配点数:{}'.format(num2))

2.指纹识别并输出对应人名

这段和之前指纹识别的是一样的

import os import cv2 # 计算两个指纹间匹配点的个数 def getNum(src, model): img1 = cv2.imread(src) img2 = cv2.imread(model) sift = cv2.SIFT_create() # orb_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 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 < 200: # src图片不一定是库里面人的指纹 ID = 9999 return ID
# 根据指纹编号,获取对应姓名 def getName(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 = "src.bmp" database = "database" ID = getID(src, database) name = getName(ID) print("识别结果为:", name)

二、图片拼接

目的让这两张图无缝衔接成一张图片

做准备:

import cv2 import numpy as np import sys def cv_show(name, img): cv2.imshow(name, img) cv2.waitKey(0) def detectAndDescribe(image): gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 将彩色图片转换成灰度图 sift = cv2.SIFT_create() # 建立SIFT生成器 # 检测SIFT特征点,并计算描述符,第二个参数为掩膜 (kps, des) = sift.detectAndCompute(gray, None) # 将结果转换成NumPy数组 kps_float = np.float32([kpc.pt for kpc in kps]) # kpc 包含两个值,分别是关键点在图像中的 x 和 y 坐标。这些坐标通常是浮点数,可以精确地描述关键点在图像中的位置。 return (kps, kps_float, des) # 返回特征点集,及对应的描述特征
'''读取拼接图片''' imageA = cv2.imread("zuo.jpg") cv_show('imageA', imageA) imageB = cv2.imread("you.jpg") cv_show('imageB', imageB)
'''计算图片特征点及描述符''' (kpsA, kps_floatA, desA) = detectAndDescribe(imageA) (kpsB, kps_floatB, desB) = detectAndDescribe(imageB)
'''建立匹配器BFMatcher,在匹配大图训练集合时使用FlannBasedMatcher速度更快。''' matcher = cv2.BFMatcher() rawMatches = matcher.knnMatch(desB, desA, k=2) good = [] matches = [] for m in rawMatches: # 当最近距离跟次近距离的比值小于0.65时,保留此匹配对 if len(m) == 2 and m[0].distance < 0.65 * m[1].distance: good.append(m) # 存储两个点在featuresA、featuresB中的索引值 matches.append((m[0].queryIdx, m[0].trainIdx)) print(len(good)) print(matches) vis = cv2.drawMatchesKnn(imageB, kpsB, imageA, kpsA, good, outImg=None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) cv_show("Keypoint Matches", vis)

计算透视变换矩阵
findHomography(srcPoints, dstPoints, method=None, ransacReprojThreshold=None, mask=None, maxIters=None, confidence=None)

  • 计算视角变换矩阵,透视变换函数,与cv2.getPerspectiveTransform()的区别在于可多个数据点变换
  • 参数srcPoints:图片A的匹配点坐标
  • 参数dstPoints:图片B的匹配点坐标
  • 参数method:计算变换矩阵的方法。
  • ransacReprojThreshold: 最大允许重投影错误阈值。该参数只有在method参数为RANSAC与RHO的时启用,默认为3

findHomography的四种方法:

  • H = cv2.findHomography(ptsA, ptsB, 0),0 - 使用所有匹配点计算变换矩阵,最小二乘。
  • H = cv2.findHomography(ptsA, ptsB, cv2.RANSAC, 5.0),RANSAC - 随机采样少量点计算模型,测试其他点是否符合。
  • H = cv2.findHomography(ptsA, ptsB, cv2.LMEDS), LMEDS - 最小化误差的中位数,而不是平均值
  • H = cv2.findHomography(ptsA, ptsB, cv2.RHO), RHO - RANSAC的改进版,使用更智能的采样策略

findHomography返回值解释:

  • 返回值:中值为变换矩阵,mask是掩模标志,指示哪些点对应内点,哪些是外点。
  • 内点:指那些与估计的模型非常接近的数据点,通常是正确匹配或真实数据。
  • 外点:指那些与估计的模型不接近的数据点,通常是错误匹配或噪声数据。
'''透视变换''' if len(matches) > 4: # 当筛选后的匹配对大于4时,计算视角变换矩阵。 # 获取匹配对的点坐标 ptsB = np.float32([kps_floatB[i] for (i, _) in matches]) # matches是通过阈值筛选之后的特征点对象 ptsA = np.float32([kps_floatA[i] for (_, i) in matches]) # kps_floatA是图片A中的全部特征点坐标 H, mask = cv2.findHomography(ptsB, ptsA, cv2.RANSAC, 10) else: print('图片未找到4个以上的匹配点') sys.exit() result = cv2.warpPerspective(imageB, H, (imageB.shape[1] + imageA.shape[1], imageB.shape[0])) cv_show('resultB', result) # 将图片A传入resultB后显示 result[0:imageA.shape[0], 0:imageA.shape[1]] = imageA cv_show('result', result) cv2.imwrite('pingjie.jpg', result)

展示zuo和you,并对匹配上的特征进行连线,这点和指纹识别是一样。

展示you图经过透视之后的变化以及最后拼接成功的结果。我们能看出还是有拼接痕迹的,就比如纸箱处。

三、思考

上面我们图像拼接是对b图进行透视转化,把透视的b图拼接在a图的右侧,思考我们能不能对图a进行透视,把a图拼接在b图的左侧。得到下面这种结果的拼接。

http://www.cnnetsun.cn/news/1331073.html

相关文章:

  • Ostrakon-VL-8B中小企业应用:无算法团队也能运行的专业级视觉合规系统
  • Bidili Generator惊艳效果:物理光照模拟——全局光照、次表面散射生成实测
  • 【学习记录】1.PS.2.如何给图片打马赛克?
  • 基于博途V16的程序:传送带机械手工件搬运监控系统
  • SAP(以 ECC6 为例)和 Oracle EBS 均支持资产负债重分类业务,且二者都围绕企业会计准则要求设计功能,核心逻辑与金蝶一致 —— 按往来明细余额方向调整报表列示,不影响总账科目余额。但二
  • 牛奶制冷罐液体制冷储存设备乳品饮料储存罐
  • LLM大规模数据的组织检索方法
  • Simulink仿真漂移机理分析(二):相图分析
  • 全球爆火的龙虾杀入科研智能体赛道,字节跳动、微软以及英伟达等巨头也早已布局AI4Science领域
  • leetcode 1395. Count Number of Teams 统计作战单位数
  • 数字:从物理化学的研究工具到现代科学的通用语言
  • C语言-Day1
  • 告别绘图软件!Paperxie AI 科研绘图:10 次免费额度,让理工科论文可视化一步到位
  • Day1 | 704、35
  • CLIP ViT-H-14开源大模型部署教程:630M参数图像特征提取实战
  • ESP32-S3桌面数字看板设计:硬件选型与双端协同架构
  • 探秘RestTemplateBuilder:为何连接超时设置频频‘失效’及最佳实践
  • 海康SDK实战:视频通道编码ID配置与优化指南
  • 告别论文焦虑:Paperxie 如何用四大降重神器破解毕业论文重复率与 AIGC 难题
  • 【力扣-42. 接雨水】Python笔记
  • 从零开始:基于Anything V5的Stable Diffusion二次元绘画环境配置
  • 从规范到高效:GitLab MR流程的团队协作实战指南
  • OpenHarmony智能WiFi开关:Hi3861嵌入式设计与分布式控制实现
  • 华为路由器实战:OSPF NSSA区域配置避坑指南(附完整拓扑实验)
  • 从被欺凌者到守护者:为什么受伤的你,更适合成为技术世界的“监管者”?
  • 《全球芯片图鉴》:全球最值得了解的芯片厂商清单
  • 计算机毕业设计源码:Python旅游评论数据采集分析平台 可视化 SnowNLP Selenium爬虫 旅游 旅行 出游 大数据 大模型 agent(建议收藏)✅
  • 基于卷积神经网络U-Net实现生物医学影像分割(PyTorch框架)
  • Comsol 二维光子晶体计算:缺陷模 BIC 的探索之旅
  • 智能音箱设计必看:LTK5209双声道功放的7大实战技巧(含EMI优化方案)