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

计算机视觉进阶教学之特征检测

目录

简介

一、harris角点检测

二、sift特征检测

三、指纹识别

1. 导入库和基础函数定义

2. 核心验证函数verification

2.1 特征提取

2.2 特征匹配

2.3 匹配筛选(Lowe's 比率测试)

2.4 认证判断

3. 主程序执行


简介

        在计算机视觉的技术体系中,特征检测是连接图像底层像素与高层语义理解的核心桥梁,更是实现目标跟踪、图像匹配、三维重建等复杂任务的关键基石。无论是自动驾驶中的障碍物识别,还是无人机航拍的场景拼接,亦或是手机相机的智能美颜与防抖,背后都离不开高效、鲁棒的特征检测技术支撑。对于渴望从 “入门” 迈向 “进阶” 的计算机视觉学习者而言,吃透特征检测的原理、算法与实践,是突破技术瓶颈、提升工程能力的必经之路。

一、harris角点检测

        Harris角点检测算法是一种常用的计算机视觉算法,用于检测图像中的角点。该算法通过计算图像中每个像素的局部自相关矩阵,来判断该像素是否为角点。

角点检测算法的基本思想:

        使用一个固定的小窗口在图像上进行任意方向的滑动,比较滑动前与滑动后两种情况,窗口中的像素灰度变化程度,如果存在任意方向上的滑动,都有着较大灰度变化(sobel算子),那么我们可以认为该窗口中存在角点。

# 角点指图像中局部区域与周围区域有较大灰度变化的点或像素。
# cornerHarris(img, blockSize, ksize, k[, dst[, borderType]]) -> dst
#     • img: 输入图像。
#     • blockSize: 角点检测中要考虑的邻域大小。
#     • ksize: Sobel求导中使用的窗口大小。
#     • k: Harris角点检测方程中的自由参数,取值参数为 [0.04, 0.06]。
# dst: 返回numpy.ndarray对象,大小和src相同,值越大,对应像素是角点的概率越高
img = cv2.imread('dama.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
dst = cv2.cornerHarris(gray, blockSize=4, ksize=3, k=0.04)
# 标记检测到的角点
img[dst > 0.05 * dst.max()] = [0, 0, 255]
# 这里通过对角点响应进行阈值处理,标记出检测到的角点
cv2.imshow('img', img)
cv2.waitKey(0)
dst = cv2.cornerHarris(gray, blockSize=4, ksize=3, k=0.04)
  • gray:输入的灰度图像
  • blockSize=4:角点检测时考虑的邻域大小为 4x4
  • ksize=3:Sobel 算子的窗口大小为 3x3,用于计算图像梯度
  • k=0.04:Harris 检测方程中的自由参数,在 [0.04, 0.06] 范围内
img[dst > 0.05 * dst.max()] = [0, 0, 255]
  • 找到dst中的最大值(最可能是角点的点)
  • 设定阈值为最大值的 5%(0.05 * dst.max ())
  • 对于所有响应值大于该阈值的像素,在原始图像上将其颜色设置为红色 [0, 0, 255](注意 OpenCV 中颜色顺序是 BGR)

二、sift特征检测

        SIFT(Scale Invariant Feature Transform)尺度不变特征变换。SIFT特征具有对旋转、尺度缩放、亮度变化等保持不变性,是一种非常稳定的局部特征。

SIFT算法具的特点:

  • 1、图像的局部特征,对旋转、尺度缩放、亮度变化保持不变,对视角变化、仿射变换、噪声也保持一定程度的稳定性。
  • 2、独特性好,信息量丰富,适用于海量特征库进行快速、准确的匹配。
  • 3、多量性,即使是很少几个物体也可以产生大量的SIFT特征
  • 4、高速性,经优化的SIFT匹配算法甚至可以达到实时性 5、扩招性,可以很方便的与其他的特征向量进行联合。

# 特征提取SIFT
# 检测图像中的关键点
# cv2.SIFT_create() #cv2.xfeatures2d.SIFT_create()#创建一个sift特征的提取对象
# sift.detect()img在图像中查找关键点man = cv2.imread('dama.jpg')
man_gray = cv2.cvtColor(man, cv2.COLOR_BGR2GRAY)
sift = cv2.SIFT_create()  # SIFT对象
kp = sift.detect(man_gray)
# kp: 检测到的(x, y)
# 坐标。
# kp.size: 关键点的大小(尺度)。
# kp.angle: 关键点的方向。
# kp.response: 关键点的响应值。
# kp.octave: 关键点所在的金字塔层级。
# 绘制关键点
# drawKeypoints(image, keypoints, outImage, color=None, flags=None)
# image: 原始图片
# keypoints: 从原图中获得的关键点,这也是画图时所用到的数据
# outputImage: 输出图像,可以是原始图片,也可以是None
# color: 画笔的颜色,通过修改(b,g,r)的值,更改画笔的颜色,b=蓝色,g=绿色,r=红色。
# flags: 绘图功能的标识设置  绘制富有信息的关键点。man_sift = cv2.drawKeypoints(man, kp, outImage=None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imshow('man_sift', man_sift)
cv2.waitKey(0)# 使用sift.compute()计算关键点描述符,方便后期的特征匹配
kp, des = sift.compute(man, kp)
print(np.array(kp).shape, des.shape)
# 输出关键点的形状和描述符的形状。
# np.array(kp).shape 表示关键点的数量和属性。
# des.shape 表示描述符的数量和属性。
sift = cv2.SIFT_create()  # 创建SIFT特征提取对象
kp = sift.detect(man_gray)  # 检测图像中的关键点
  • cv2.SIFT_create():创建一个 SIFT 特征提取器实例

  • sift.detect():在灰度图像上检测关键点,返回一个包含所有关键点的列表

    每个关键点(kp中的元素)包含以下重要属性:

    • kp.pt:关键点的 (x, y) 坐标
    • kp.size:关键点的大小(尺度)
    • kp.angle:关键点的方向(0-360 度)
    • kp.response:关键点的响应值(响应值越高,关键点越显著)
    • kp.octave:关键点所在的金字塔层级(与尺度相关)
man_sift = cv2.drawKeypoints(man, kp, outImage=None, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
  • cv2.drawKeypoints():在图像上绘制检测到的关键点
  • 参数说明:
    • man:原始彩色图像
    • kp:之前检测到的关键点
    • outImage=None:输出图像,设为 None 表示函数会自动创建
    • flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS:绘制 "丰富" 的关键点,不仅显示位置,还会显示关键点的尺度(圆圈大小)和方向(箭头)

三、指纹识别

        使用OpenCV进行指纹识别是一个复杂且挑战性的任务,因为指纹识别通常需要高精度的特征提取和匹配算法。虽然OpenCV提供了多种图像处理和计算机视觉的工具,但直接使用OpenCV的内置功能(如SIFT、SURF、ORB等特征检测器)进行指纹识别可能并不总是足够有效。

        下面代码实现了一个基于 SIFT 特征匹配的图像认证系统,通过比较源图像与模板图像的特征相似性来判断是否认证通过。

model.bmp/src1.bmp

src2.bmp

1. 导入库和基础函数定义

import os
import cv2def cv_show(name, img):cv2.imshow(name, img)cv2.waitKey(0)

2. 核心验证函数verification

2.1 特征提取
# 创建SIFT特征提取器
sift = cv2.SIFT_create()
# 检测关键点和计算描述符(特征向量) 源图像
kp1, des1 = sift.detectAndCompute(src, None)  # 第二个参数: 掩膜
# 检测关键点和计算描述符 模板图像
kp2, des2 = sift.detectAndCompute(model, None)
  • sift.detectAndCompute():同时完成关键点检测和描述符计算
    • kp1/kp2:分别是源图像和模板图像的关键点列表
    • des1/des2:分别是源图像和模板图像的特征描述符矩阵
    • 第二个参数None表示不使用掩膜(即处理整幅图像)
2.2 特征匹配
# 创建FLANN匹配器
flann = cv2.FlannBasedMatcher()
# 使用k近邻匹配(des1中的每个描述符与des2中的最近两个描述符进行匹配)
matches = flann.knnMatch(des1, des2, k=2)
  • FLANN(Fast Library for Approximate Nearest Neighbors)是一种快速近似最近邻匹配算法,比暴力匹配更高效
  • knnMatch(k=2):为每个特征点在另一幅图像中寻找最近的 2 个匹配点
2.3 匹配筛选(Lowe's 比率测试)
# 进行比较筛选
ok = []
for m, n in matches:# 根据Lowe's比率测试,选择最佳匹配if m.distance < 0.8 * n.distance:ok.append((m, n))
  • Lowe's 比率测试:如果最佳匹配(m)与次佳匹配(n)的距离比值小于阈值(这里是 0.8),则认为是好的匹配
  • 原理:真正的匹配点通常具有明显优于其他匹配的距离值
  • ok列表存储通过筛选的优质匹配对

2.4 认证判断
# 统计通过筛选的匹配数量
num = len(ok)
if num >= 500:result = "认证通过"
else:result = "认证失败"
return result
  • 通过统计优质匹配的数量来判断图像是否匹配
  • 这里设置阈值为 500,当匹配数超过该值时认为认证通

3. 主程序执行

if __name__ == "__main__":src1 = cv2.imread("src1.BMP")cv_show('src1', src1)src2 = cv2.imread("src2.BMP")cv_show('src2', src2)model = cv2.imread("model.BMP")cv_show('model', model)result1 = verification(src1, model)result2 = verification(src2, model)print("src1验证结果为:", result1)print("src2验证结果为:", result2)
  • 读取两个源图像(src1.BMP、src2.BMP)和一个模板图像(model.BMP)
  • 分别显示这三个图像
  • 调用verification函数分别比较 src1 与 model、src2 与 model 的匹配程度
  • 输出两个源图像的认证结果

        根据上面那个基础的我们进行优化一下能够通过比较输入指纹与数据库中指纹的匹配程度,识别出对应的人员信息。


# """============计算两个指纹间匹配点的个数============="""
# 1个用法
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"""============获取指纹编号============="""
# 1个用法
def getID(src, database):max = 0for file in os.listdir(database):model = os.path.join(database, file)num = getNum(src, model)print("文件名:", file, "匹配点个数:", num)if num > max:max = numname = fileID = name[0]if max < 100:  # src图片不一定是库里面人的指纹ID = 9999return ID"""============根据指纹编号,获取对应姓名============="""
# 1个用法
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)

主函数流程:

  1. 定义待识别指纹图像路径和数据库路径
  2. 调用getID函数获取最匹配的指纹 ID
  3. 调用getName函数将 ID 转换为姓名
  4. 输出最终的识别结果

系统工作原理总结

  1. 输入一个待识别的指纹图像
  2. 与数据库中所有指纹图像逐一进行 SIFT 特征匹配
  3. 统计每个匹配的有效特征点数量
  4. 找到匹配点最多的指纹作为识别结果
  5. 通过预设的 ID - 姓名映射表,返回最终的人员姓名


文章转载自:

http://LHWd3Hjm.cszbj.cn
http://rsdjCC8g.cszbj.cn
http://boicQq7S.cszbj.cn
http://XyQhGPSJ.cszbj.cn
http://pRYHvplB.cszbj.cn
http://cvuU1EBM.cszbj.cn
http://XiItz17s.cszbj.cn
http://UN81pJVl.cszbj.cn
http://ecwrCvql.cszbj.cn
http://fVHshzKO.cszbj.cn
http://KgadVM6i.cszbj.cn
http://4h0ADVsp.cszbj.cn
http://qGbwqx2T.cszbj.cn
http://PTtiuV8z.cszbj.cn
http://1154RgdH.cszbj.cn
http://T8P8R6bV.cszbj.cn
http://SoS4mUMt.cszbj.cn
http://zcdtLRO4.cszbj.cn
http://6nMfPAG9.cszbj.cn
http://7rGHl1vA.cszbj.cn
http://FURGQIBz.cszbj.cn
http://9Gs1aY8E.cszbj.cn
http://Vykt5eZy.cszbj.cn
http://gQBcyT2q.cszbj.cn
http://ErUU7IRf.cszbj.cn
http://UMVPD8bB.cszbj.cn
http://6eCMvh4Y.cszbj.cn
http://Cct0yEOF.cszbj.cn
http://JoNJz7Ax.cszbj.cn
http://13pyl3s2.cszbj.cn
http://www.dtcms.com/a/380952.html

相关文章:

  • 基于OpenVinoSharp和PP-Vehicle的车辆检测
  • [论文阅读] 人工智能 | 软件工程 - 软件测试 | 从黑盒到透明:AUTOSTUB用进化算法打通符号执行的“最后一公里”
  • zmq源码分析之io_thread_t
  • 什么是财报自动识别?5分钟OCR识别录入1份财务报表
  • 《Html模板》HTML数学题目生成器 - 让数学练习更简单(附源码)
  • leetcode29( 有效的括号)
  • SpringBoot实现WebSocket服务端
  • AI赋能与敏捷融合:未来电源项目管理者的角色重塑与技能升级——从华为实战看高技术研发项目的管理变革
  • 从入门到了解C++系列-----C++11 新语法
  • 数据结构(C语言篇):(十二)实现顺序结构二叉树——堆
  • zmq源码分析之mailbox
  • AI智能体时代的可观测性
  • Transformer架构详解:革命性深度学习架构的原理与应用
  • PAT乙级_1114 全素日_Python_AC解法_含疑难点
  • 一、HTML 完全指南:从零开始构建网页
  • 【硬件-笔试面试题-87】硬件/电子工程师,笔试面试题(知识点:解决浪涌电压)
  • Spring的注解
  • Java Class Analyzer MCP Server:让AI精准理解Java依赖的利器
  • 创建自己的Docker镜像,使用工具:GitHub(远程仓库)、GitHub Desktop(版本控制工具)、VSCode(代码编辑器)
  • Windows11安装Docker Desktop
  • FastJson解析对象后验签失败问题分析
  • 【Vue2手录12】单文件组件SFC
  • Pinia
  • MySQL按时间Range分区
  • python发送请求SSL验证设置
  • 关于栈和队列的OJ练习
  • WebGIS包括哪些技术栈?怎么学习?
  • 15、优化算法工程实践 - 从数学理论到AI训练的核心引擎
  • VS2019 Community 社区版下载链接
  • 高低压隔离器的技术演进与行业赋能