Opencv之sift特征检测和FLANN 匹配器进行指纹特征匹配

sift特征检测和FLANN 匹配器进行指纹匹配

目录

  • [sift特征检测和FLANN 匹配器进行指纹匹配](#sift特征检测和FLANN 匹配器进行指纹匹配)
    • [1 sift特征检测](#1 sift特征检测)
      • [1.1 概念](#1.1 概念)
      • [1.2 优缺点](#1.2 优缺点)
    • [2 FLANN 匹配器](#2 FLANN 匹配器)
      • [2.1 概念](#2.1 概念)
      • [2.2 工作原理与匹配方式](#2.2 工作原理与匹配方式)
      • [2.3 FLANN 匹配器的使用步骤](#2.3 FLANN 匹配器的使用步骤)
      • [2.4 优缺点](#2.4 优缺点)
    • [3 函数](#3 函数)
      • [3.1 特征检测匹配](#3.1 特征检测匹配)
      • [3.2 匹配符合条件点并绘制](#3.2 匹配符合条件点并绘制)
    • [3 代码测试](#3 代码测试)
      • [3.1 单个指纹模板匹配](#3.1 单个指纹模板匹配)
      • [3.2 多个指纹匹配](#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 匹配符合条件点并绘制

python 复制代码
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:

模板:

代码展示:

python 复制代码
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的pt
    num = 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 result

if __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 多个指纹匹配

指纹文件库:

代码展示:

python 复制代码
import os

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, 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):
        print(file)
        model = os.path.join(database,file)
        num = getNum(src,model)
        print(f'文件名:{file},匹配点个数:{num}')
        if num>max:
            max = num
            name = file
    ID = name[0]
    if max<100:
        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 = "scrpp.bmp"
    database = "database//database"
    ID = getID(src,database)
    name = getname(ID)
    print(f'识别结果:{name}')

运行结果:

相关推荐
张较瘦_1 小时前
[论文阅读] 人工智能 + 软件工程 | 需求获取访谈中LLM生成跟进问题研究:来龙去脉与创新突破
论文阅读·人工智能
一 铭2 小时前
AI领域新趋势:从提示(Prompt)工程到上下文(Context)工程
人工智能·语言模型·大模型·llm·prompt
顾道长生'3 小时前
(Arxiv-2025)通过动态 token 剔除实现无需训练的高效视频生成
计算机视觉·音视频·视频生成
云泽野5 小时前
【Java|集合类】list遍历的6种方式
java·python·list
麻雀无能为力5 小时前
CAU数据挖掘实验 表分析数据插件
人工智能·数据挖掘·中国农业大学
时序之心5 小时前
时空数据挖掘五大革新方向详解篇!
人工智能·数据挖掘·论文·时间序列
IMPYLH6 小时前
Python 的内置函数 reversed
笔记·python
.30-06Springfield6 小时前
人工智能概念之七:集成学习思想(Bagging、Boosting、Stacking)
人工智能·算法·机器学习·集成学习
说私域7 小时前
基于开源AI智能名片链动2+1模式S2B2C商城小程序的超级文化符号构建路径研究
人工智能·小程序·开源
永洪科技7 小时前
永洪科技荣获商业智能品牌影响力奖,全力打造”AI+决策”引擎
大数据·人工智能·科技·数据分析·数据可视化·bi