Opencv之sift特征检测和FLANN 匹配器进行指纹特征匹配
sift特征检测和FLANN 匹配器进行指纹匹配
目录
- sift特征检测和FLANN 匹配器进行指纹匹配
- 1 sift特征检测
- 1.1 概念
- 1.2 优缺点
- 2 FLANN 匹配器
- 2.1 概念
- 2.2 工作原理与匹配方式
- 2.3 FLANN 匹配器的使用步骤
- 2.4 优缺点
- 3 函数
- 3.1 特征检测匹配
- 3.2 匹配符合条件点并绘制
- 3 代码测试
- 3.1 单个指纹模板匹配
- 3.2 多个指纹匹配
1 sift特征检测
1.1 概念
SIFT(尺度不变特征变换)是一种用于图像处理中检测和描述图像中局部结构的算法。它是由David Lowe在1999年提出的,并在2004年进行了详细阐述。SIFT特征具有尺度不变性,这意味着即使图像的尺度发生变化,SIFT特征也能保持稳定。
1.2 优缺点
SIFT特征的优点:
- 尺度不变性:能够适应图像的尺度变化。
- 旋转不变性:能够适应图像的旋转变化。
- 对光照、仿射变换和噪声具有一定的鲁棒性。
SIFT特征的缺点:
- 计算复杂度较高,实时性较差。
- 对于非线性变换和大幅度的视角变化,SIFT特征的性能可能会下降。
2 FLANN 匹配器
2.1 概念
FLANN 匹配器(Fast Library for Approximate Nearest Neighbors,快速近似最近邻搜索库)是 OpenCV 中用于高效匹配特征描述符的工具。它通过近似算法加速最近邻搜索,特别适合处理高维数据(如 SIFT 或 SURF 描述符)。
2.2 工作原理与匹配方式
- 最近邻搜索:
- 给定一个特征描述符集合,FLANN 的目标是找到与查询描述符最接近的匹配点。
- 精确的最近邻搜索(如暴力匹配)在高维数据中计算量很大,FLANN 通过近似算法加速搜索。
- 近似算法:
- FLANN 使用了一种基于树结构的算法(如 KD-Tree 或 Hierarchical K-Means Tree)来组织数据,从而快速缩小搜索范围。
- 通过牺牲一定的精度,换取更快的搜索速度。
- 匹配方式:
- FLANN 支持两种匹配方式:
- 单匹配:为每个查询描述符找到一个最近邻。
- KNN 匹配:为每个查询描述符找到 K 个最近邻。
2.3 FLANN 匹配器的使用步骤
-
创建 FLANN 匹配器:
使用 cv2.FlannBasedMatcher 创建 FLANN 匹配器对象。 -
准备特征描述符:
使用特征检测算法(如 SIFT、SURF 或 ORB)提取图像的特征描述符。 -
进行匹配:
使用 knnMatch 方法进行 KNN 匹配,返回每个查询描述符的 K 个最近邻。 -
筛选匹配点:
根据距离比例或其他条件筛选出可靠的匹配点。
2.4 优缺点
优点:
- 高效:比暴力匹配(Brute-Force Matcher)更快,特别适合处理高维数据。
- 灵活:支持多种算法和参数配置,可以根据需求调整精度和速度。
缺点:
- 近似匹配:结果是近似的,可能存在一定的误差。
- 参数调优:需要根据具体任务调整参数,否则可能影响匹配效果。
3 函数
3.1 特征检测匹配
- 特征关键点检测
- sift = cv2.SIFT_create(),创建 SIFT 特征检测器
- kp1, des1 = sift.detectAndCompute(src, None),检测并计算 src 图像的关键点(kp1) 和描述符(des1 )
- 匹配器匹配
- flann = cv2.FlannBasedMatcher(),创建FLANN 匹配器
- matches = flann.knnMatch(des1, des2, 2) , 使用 KNN 算法进行特征(des1, des2)匹配,k=2 表示每个描述符返回两个最佳匹配
3.2 匹配符合条件点并绘制
ok = [] # 存储符合条件的匹配点
ok_n = [] # 存储对应的次佳匹配点# 遍历所有匹配点
for m, n in matches:
# 如果最佳匹配点的距离小于次佳匹配点距离的 0.65 倍,则认为是一个好的匹配if m.distance < 0.65 * n.distance:ok.append(m) # 将好的匹配点加入 ok 列表ok_n.append(n) # 将对应的次佳匹配点加入 ok_n 列表# 计算好的匹配点的数量
num = len(ok)# 如果好的匹配点数量大于等于 400,则认为验证通过
if num >= 400:result = '认证通过' # 设置验证结果为通过# 遍历所有匹配点for m, n in matches:# 再次筛选好的匹配点if m.distance < 0.65 * n.distance:ok.append(m)x1 = int(kp1[m.queryIdx].pt[0])y1 = int(kp1[m.queryIdx].pt[1])x2 = int(kp2[n.queryIdx].pt[0])y2 = int(kp2[n.queryIdx].pt[1])src = cv2.circle(src, (x1, y1), 3, (0, 0, 255), -1)model = cv2.circle(model, (x2, y2), 3, (0, 0, 255), -1)
3 代码测试
3.1 单个指纹模板匹配
图片1:

图片2:

模板:

代码展示:
import cv2
def cv_chow(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 = cv2.FlannBasedMatcher()matches = flann.knnMatch(des1, des2, 2)ok = []ok_n = []for m, n in matches:if m.distance < 0.65 * n.distance:ok.append(m)ok_n.append(n)## m,n,在kp的ptnum = len(ok)if num>=400:result = '认证通过'for m, n in matches:if m.distance < 0.65 * n.distance:ok.append(m)x1 = int(kp1[m.queryIdx].pt[0])y1 = int(kp1[m.queryIdx].pt[1])x2 = int(kp2[n.queryIdx].pt[0])y2 = int(kp2[n.queryIdx].pt[1])src = cv2.circle(src, (x1, y1), 3, (0, 0, 255), -1)model = cv2.circle(model, (x2, y2), 3, (0, 0, 255), -1)cv_chow('src', src)cv_chow('model', model)else:result = '认证失败'return resultif __name__=='__main__':src1 = cv2.imread('zhiwen1.bmp')cv_chow('src1',src1)src2 = cv2.imread('zhiwen2.bmp')cv_chow('src2', src2)model = cv2.imread('zhiwenp.bmp')cv_chow('model_', model)result1 = verification(src1,model)result2 = verification(src2, model)print(f'src1验证结果:{result1}')print(f'src2验证结果:{result2}')
运行结果:


3.2 多个指纹匹配
指纹文件库:

代码展示:
import osdef 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, 2)ok = []for m, n in matches:if m.distance < 0.8 * n.distance:ok.append(m)num = len(ok)return numdef getID(src,database):max = 0for file in os.listdir(database):print(file)model = os.path.join(database,file)num = getNum(src,model)print(f'文件名:{file},匹配点个数:{num}')if num>max:max = numname = fileID = name[0]if max<100:ID = 9999return IDdef getname(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 = "scrpp.bmp"database = "database//database"ID = getID(src,database)name = getname(ID)print(f'识别结果:{name}')
运行结果:

相关文章:
Opencv之sift特征检测和FLANN 匹配器进行指纹特征匹配
sift特征检测和FLANN 匹配器进行指纹匹配 目录 sift特征检测和FLANN 匹配器进行指纹匹配1 sift特征检测1.1 概念1.2 优缺点 2 FLANN 匹配器2.1 概念2.2 工作原理与匹配方式2.3 FLANN 匹配器的使用步骤2.4 优缺点 3 函数3.1 特征检测匹配3.2 匹配符合条件点并绘制 3 代码测试3.1…...
rust学习~tokio的io
await Suspend execution until the result of a Future is ready. 暂停执行,直到一个 Future 的结果就绪。 .awaiting a future will suspend the current function’s execution until the executor has run the future to completion. 对一个 Future 使用 .awa…...
FPGA开发,使用Deepseek V3还是R1(2):V3和R1的区别
以下都是Deepseek生成的答案 FPGA开发,使用Deepseek V3还是R1(1):应用场景 FPGA开发,使用Deepseek V3还是R1(2):V3和R1的区别 FPGA开发,使用Deepseek V3还是R1&#x…...
本地部署大数据集群前置准备
1. 设置VMware网段 虚拟网络编辑器——更改设置——选择VMnet8——子网改成192.168.88.0——NAT设置——网关设置为192.168.88.2 2. 下载CentOS操作系统 下载CentOS 7.6(1810)版本 3. 在VMware中安装CentOS操作系统 创建新的虚拟机——典型——安装光盘映像文件——输入账…...
Spring Boot整合RabbitMQ
1. 环境准备 Spring Boot 2.1.3.RELEASERabbitMQ 3.xJDK 8 或以上Maven 3.5 2. 安装Erlang、RabbitMQ 2.1 安装前准备 RabbitMQ 依赖 Erlang 环境,需确保两者的版本匹配,官方兼容性参考:RabbitMQ & Erlang 版本对照表。 2.2 下载安…...
CDefView::_OnFSNotify函数分析
进入CDefView::_OnFSNotify函数时状态栏 _UpdateStatusBar函数之后增加一个对象,变成7个对象。 LRESULT CDefView::_OnFSNotify(LONG lNotification, LPCITEMIDLIST* ppidl) { LPITEMIDLIST pidl; LPCITEMIDLIST pidlItem; // we may be registered for no…...
精准汇报:以明确答复助力高效工作
在工作场景中,汇报工作是一项至关重要的沟通环节,它不仅关乎工作进展的有效传达,更影响着团队协作的顺畅度和整体工作效率。而汇报工作的关键,就在于给予明确肯定的答复,摒弃“应该”“可能”这类模糊词汇,…...
Java自动拆箱装箱/实例化顺序/缓存使用/原理/实例
在 Java 编程体系中,基本数据类型与包装类紧密关联,它们各自有着独特的特性和应用场景。理解两者之间的关系,特别是涉及到拆箱与装箱、实例化顺序、区域问题、缓存问题以及效率问题。 一、为什么基本类型需要包装类 泛型与集合的需求 Java…...
软件工程---基于构件的软件工程
基于构件的软件工程(CBSE)是一种软件开发方法,通过重用现有的软件构件来构建系统,从而提高开发效率和软件质量。这种方法强调软件系统的模块化设计和构建复用,使得软件开发过程更加高效和灵活。 企业软件开发…...
AMD RDNA3 GPU架构解析
本文会通过把AMD的RDNA3架构为例比喻为**“施工公司”**工作模式,深入理解GPU如何高效处理顶点着色、像素计算等任务。 一、施工公司的组织架构 1. 施工公司(WGP)与施工队(CU) WGP(Work Group Processor&…...
docker关闭mysql端口映射的使用
需求 项目中的数据库为mysql,如果将端口映射到宿主机上,容易被工具扫描出,且随着国产化的进程推进,mysql将不被允许。为了提高安全性与满足项目需求,这里采用隐藏mysql端口方式,不映射宿主机端口ÿ…...
关于对机器中的人工智能进行基准测试
大家读完觉得有帮助记得及时关注和点赞!!! 抽象 最近的基准研究声称,AI 在各种认知任务上的表现已经接近甚至超过人类的“水平”。然而,本立场文件认为,当前的 AI 评估范式不足以评估类似人类的认知能力。我…...
CSS - 妙用Sass
官方文档:https://www.sass.hk/docs/ 1.例1: each $theme in $themeList {$themeKey: map-get($theme, key);media screen and (weex-theme: $themeKey) {.btnText {max-width: 150px;include font(map-get($theme, medFont),map-get($theme, subFontS…...
MS模块创新
1. 动态分支权重融合 创新思路:引入通道注意力机制,自动学习高频/低频分支的融合权重 class DynamicMS(nn.Module):def __init__(self, in_channels1):super().__init__()# 原高频/低频分支保持不变self.high_freq ... # 与原MS模块相同self.low_freq…...
私有化部署DeepSeek并SpringBoot集成使用(附UI界面使用教程-支持语音、图片)
私有化部署DeepSeek并SpringBoot集成使用(附UI界面使用教程-支持语音、图片) windows部署ollama Ollama 是一个开源框架,专为在本地机器上便捷部署和运行大型语言模型(LLM)而设计 下载ollama 下载地址(…...
MFC中CMutex类和CSingleLock类,配合使用疑惑
在使用CMutex过程中,看到别人使用了CSingleLock类,想着明明CMutex已经可以实现线程同步了,为什么还有使用CSingleLock类呢? 在MFC中,虽然CMutex类本身可以实现线程同步,但通常会与CSingleLock类一起使用&am…...
残差收缩模块
1. 多尺度阈值生成 创新思路:融合不同尺度的统计信息(如平均池化最大池化)生成更鲁棒的阈值。 class MultiScaleShrinkage(nn.Module):def __init__(self, channel, reduction4):super().__init__()# 多尺度池化分支self.avg_pool nn.Adap…...
HOW - 在Windows浏览器中模拟MacOS的滚动条
目录 一、原生 CSS 代码实现模拟 macOS 滚动条额外优化应用到某个特定容器 二、Antd table中的滚动条场景三、使用第三方工具/扩展 如果你想让 Windows 里的滚动条 模拟 macOS 的效果(细窄、圆角、隐藏默认轨道)。 可以使用以下几种方案: 一…...
Unity 打包后EXE运行出现Field to Load il2cpp的一种情况
Unity版本2021.3.13f1c1 #if DEVELOPMENT_BUILDA1 A1 10600;#else#endif 使用 #if DEVELOPMENT_BUILD然后在下面面板使用Development Build。打包后会运行游戏EXE出现Field to Load il2cpp。 解决办法是换成IF ELSE,自己代码设置个开关、 文心一言: …...
Windows 环境下 Nginx、PHP 与 ThinkPHP 开发环境搭建
Windows 环境下 Nginx、PHP 与 ThinkPHP 开发环境搭建 目录 安装 Nginx 和 PHP配置 Nginx配置 PHP启动服务ThinkPHP 配置常见问题排查 1. 安装 Nginx 和 PHP 安装 Nginx 访问 Nginx 官网 下载 Windows 版本解压到指定目录,如 C:\nginx 安装 PHP 访问 PHP 官网…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释
以Module Federation 插件详为例,Webpack.config.js它可能的配置和含义如下: 前言 Module Federation 的Webpack.config.js核心配置包括: name filename(定义应用标识) remotes(引用远程模块࿰…...
WEB3全栈开发——面试专业技能点P4数据库
一、mysql2 原生驱动及其连接机制 概念介绍 mysql2 是 Node.js 环境中广泛使用的 MySQL 客户端库,基于 mysql 库改进而来,具有更好的性能、Promise 支持、流式查询、二进制数据处理能力等。 主要特点: 支持 Promise / async-await…...
