al+大数据每日学习笔记27

2026年8月26日

SIFT+FLANN 指纹特征匹配知识点总结

项目用途:指纹识别,利用SIFT 提取局部特征 + FLANN 快速匹配 + Lowe 比率筛选完成指纹比对、指纹库检索、匹配点可视化。

一、核心知识点

1. SIFT 特征(尺度不变特征变换)

作用:提取图像关键点(特征点)+ 生成描述子 (des),对缩放、旋转有一定鲁棒性,适合指纹这类细节特征匹配。

sift.detectAndCompute(img,mask)

返回:kp关键点列表,des描述符(特征向量数组)

kpi.pt 获取第 i 个关键点坐标**(x,y)**

OpenCV 调用:sift = cv2.SIFT_create()

2. FLANN 匹配器

FLANN:快速近似最近邻搜索,比暴力匹配 BFMatcher 速度快,适合描述符数量大的场景(指纹特征点很多)。

flann = cv2.FlannBasedMatcher()

flann.knnMatch(des1, des2, k=2): k 近邻匹配,每个特征点返回 2 个最匹配结果,用于 Lowe 筛选。

3. Lowe's ratio test(比率测试,核心过滤算法)

作用:剔除错误匹配,滤除歧义匹配点

复制代码
if m.distance < ratio * n.distance:
    保留匹配

m :第一近匹配;n :第二近匹配

distance: 描述符之间欧式距离,距离越小特征越相似

ratio 常用阈值:0.4 ~ 0.8;阈值越小筛选越严格,保留匹配点越少。

4. OpenCV 关键点与匹配可视化

cv2.circle() :在图像上绘制关键点圆圈标记

cv2.drawMatchesKnn() :拼接两张图,画出匹配点之间连线

flags=cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS :不绘制无匹配的关键点

**cv2.imshow() / cv2.waitKey(0):**图片显示。

5. 指纹库检索业务逻辑

遍历指纹库文件夹,逐个与待识别图片计算有效匹配点数

记录最大匹配点数量,得到最相似指纹文件名

设置匹配点阈值(例 200/500):低于阈值判定库中无该指纹;

文件名字符串切片拿到编号,映射字典得到人名。

二、代表性关键代码片段

片段 1:SIFT 提取特征 + FLANN k 近邻匹配 + Lowe 筛选

复制代码
import cv2

# 1.创建SIFT
sift = cv2.SIFT_create()
# 2.提取关键点、描述符
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)

# 3.FLANN匹配器
flann = cv2.FlannBasedMatcher()
matches = flann.knnMatch(des1, des2, k=2)

# 4.Lowe比率测试筛选优秀匹配点
good_matches = []
ratio = 0.8
for m, n in matches:
    if m.distance < ratio * n.distance:
        good_matches.append(m)

# 获取有效匹配数量
match_count = len(good_matches)
print("有效匹配点数量:", match_count)

片段 2:标记关键点 + 绘制匹配连线

复制代码
# 在原图绘制匹配到的关键点
for match in good_matches:
    # queryIdx:第一张图关键点索引;trainIdx:第二张图关键点索引
    x1, y1 = kp1[match.queryIdx].pt
    x2, y2 = kp2[match.trainIdx].pt
    cv2.circle(img1, (int(x1), int(y1)), 3, (0, 0, 255), -1)
    cv2.circle(img2, (int(x2), int(y2)), 3, (0, 0, 255), -1)

# 绘制匹配连线图
match_img = cv2.drawMatchesKnn(img1, kp1, img2, kp2, [[m] for m in good_matches], None,
                               flags=cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS)
cv2.imshow("匹配结果", match_img)
cv2.waitKey(0)

片段 3:指纹库遍历检索(核心业务)

复制代码
import os

def search_fingerprint(src_path, db_path):
    max_num = 0
    best_file = ""
    for filename in os.listdir(db_path):
        full_path = os.path.join(db_path, filename)
        # getNum:计算两张图片有效匹配点数,即上面片段1逻辑
        cnt = getNum(src_path, full_path)
        print(f"{filename} 匹配点:{cnt}")
        if cnt > max_num:
            max_num = cnt
            best_file = filename
    # 阈值判断,匹配不足判定未找到
    if max_num < 200:
        return 9999, "未找到指纹"
    else:
        fid = best_file[0]
        return fid, max_num

片段 4:简单认证逻辑

复制代码
def verify_fingerprint(src_img, template_img, thresh=500):
    sift = cv2.SIFT_create()
    kp1, des1 = sift.detectAndCompute(src_img, None)
    kp2, des2 = sift.detectAndCompute(template_img, None)
    flann = cv2.FlannBasedMatcher()
    matches = flann.knnMatch(des1, des2, k=2)
    good = [m for m,n in matches if m.distance < 0.8*n.distance]
    if len(good) >= thresh:
        return "认证通过"
    else:
        return "认证失败"

三、整体流程总结

读取指纹图片 → SIFT检测关键点+计算描述子 → FLANN k=2近邻匹配 → Lowe比率过滤错误匹配 → 统计有效匹配点数量 → 和阈值比较: ①单张比对:直接输出认证通过/失败 ②指纹库识别:遍历全部模板,取匹配点最多的模板,映射得到人员姓名 ③可视化:画关键点、画匹配连线

相关推荐
吃好睡好便好39 分钟前
判断函数的使用
学习·算法·matlab·生活·判断函数
浪兎兎1 小时前
Vue CLI笔记
前端·vue.js·笔记
摇滚侠1 小时前
《SpringBoot 3:入门与应用实战》第 9 章 使用 WebMvc 开发应用 阅读笔记 20
spring boot·笔记·后端
蒸蒸yyyyzwd1 小时前
cpp web server 面试可能问题总结
c++·笔记·八股
阳光宅男@李光熠1 小时前
【电子通识】排阻和普通电阻有什么区别?
笔记·学习
m4Rk_1 小时前
【论文阅读】Agent 记忆机制(54):MINJA——普通用户如何仅通过查询污染 Agent 的长期记忆
论文阅读·人工智能·学习·开源·github
Είναι η κοπέλα2 小时前
知识蒸馏:把大模型的能力“搬“进小模型,原理与一次完整实战
人工智能·笔记
动词ing2 小时前
【学习笔记】字符串(遍历+反转+替换+子串匹配+KMP)+题目解析
学习·算法
Ztt6666666662 小时前
太白壶以浅青为底,紫红垂下来才有神采
经验分享·笔记·其他·百度·微信公众平台