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

计算机视觉(opencv)实战二十——SIFT提取图像特征


🔑 SIFT(尺度不变特征变换)详解与实践

1. SIFT 简介

SIFT(Scale-Invariant Feature Transform,尺度不变特征变换)是 David Lowe 在 1999 年提出的一种局部特征提取算法,它能够在图像中检测到一系列稳定的“关键点”,并为每个关键点生成一段具有独特性的特征描述符。

SIFT 的最大优点是对尺度、旋转、亮度变化和一定程度的仿射变换具有不变性,因此在目标识别、图像拼接、三维重建等任务中非常有用。


2. SIFT 算法原理

SIFT 主要分为 四个步骤

2.1 尺度空间极值检测

  • 目标:在不同尺度下找到潜在的关键点。

  • 方法

    1. 构建高斯金字塔:对原始图像多次高斯模糊,下采样,得到不同分辨率的图像。

    2. 构建高斯差分金字塔(DoG):对相邻的高斯模糊图像做差分,得到 DoG 图像。

    3. 在 DoG 图像中寻找局部极值:每个像素与其 3×3 邻域和相邻尺度层的像素比较,如果是最大或最小值,就认为是关键点候选。

2.2 关键点精确定位

  • 对候选关键点使用泰勒展开精确拟合,剔除对比度过低或位于边缘的点,保留稳定的关键点。

2.3 方向分配

  • 在关键点邻域内计算梯度方向直方图,为每个关键点分配一个或多个主方向。

  • 这样可以实现旋转不变性。

2.4 关键点描述符生成

  • 以关键点为中心,选取一定区域,计算梯度幅值和方向。

  • 将区域划分为 4×4 个小块,每个小块计算 8 个方向的梯度直方图,共 4×4×8=128 维特征向量。

  • 对向量进行归一化,增强对光照变化的鲁棒性。

总结:SIFT 特征点是局部、稳定且可重复检测的点,每个点有一个 128 维描述符,适合做特征匹配。


3. SIFT 代码解析

图片准备:

以下代码展示了如何用 OpenCV 检测图像中的 SIFT 特征点,并可视化结果。

import cv2
import numpy as np# 1. 读取图像并转为灰度
man = cv2.imread('face1.jpg')  # 读入彩色图像
man_gray = cv2.cvtColor(man, cv2.COLOR_BGR2GRAY)  # 转为灰度,SIFT 对灰度图操作# 2. 创建 SIFT 特征检测器
sift = cv2.SIFT_create()  # 也可写成 cv2.xfeatures2d.SIFT_create()# 3. 检测关键点
kp = sift.detect(man_gray)  
# kp 是一个列表,每个元素是 cv2.KeyPoint 对象,包含关键点信息
# 常用属性:
# kp.pt:关键点坐标 (x, y)
# kp.size:关键点的尺度大小
# kp.angle:关键点的方向
# kp.response:关键点的响应值
# kp.octave:关键点所在金字塔层级# 4. 绘制关键点
man_sift = cv2.drawKeypoints(man, kp, outImage=None,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS
)
cv2.imshow('sift', man_sift)
cv2.waitKey(0)# 5. 计算描述符
kp, des = sift.compute(man, kp)
print(np.array(kp).shape, des.shape)
# np.array(kp).shape 显示关键点数量
# des.shape 表示描述符的维度,一般是 (关键点数量, 128)

运行结果:


4. 运行结果与说明

  • 可视化效果:你会看到图像上绘制了许多带方向的小圆圈,这些就是检测到的关键点,每个箭头方向表示主方向。

  • 输出形状

    • np.array(kp).shape:关键点个数,例如 (245,) 表示一共检测到 245 个关键点。

    • des.shape:描述符矩阵,例如 (245, 128),说明有 245 个关键点,每个用 128 维向量描述。


展示 描述符计算两张不同角度图的匹配效果

import cv2
import numpy as np# 1. 读取两张图像(可以用同一张图的不同视角或同一场景的两张图)
img1 = cv2.imread('face1.jpg')  # 查询图像
img2 = cv2.rotate(img1, cv2.IMREAD_GRAYSCALE)  # 目标图像# 转为灰度图
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)# 2. 创建 SIFT 检测器
sift = cv2.SIFT_create()# 3. 检测关键点并计算描述符
kp1, des1 = sift.detectAndCompute(gray1, None)
kp2, des2 = sift.detectAndCompute(gray2, None)print(f"图1关键点数:{len(kp1)}, 描述符形状:{des1.shape}")
print(f"图2关键点数:{len(kp2)}, 描述符形状:{des2.shape}")# 4. 绘制关键点
img1_kp = cv2.drawKeypoints(img1, kp1, None,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
img2_kp = cv2.drawKeypoints(img2, kp2, None,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)cv2.imshow('Image 1 KeyPoints', img1_kp)
cv2.imshow('Image 2 KeyPoints', img2_kp)
cv2.waitKey(0)# 5. 特征匹配(使用BF匹配器 + KNN筛选)
bf = cv2.BFMatcher(cv2.NORM_L2, crossCheck=False)
matches = bf.knnMatch(des1, des2, k=2)  # KNN 匹配,每个点找两个最相近的匹配# 6. Lowe比率测试,筛选优质匹配
good_matches = []
for m, n in matches:if m.distance < 0.75 * n.distance:good_matches.append(m)print(f"匹配到的特征点数:{len(good_matches)}")# 7. 绘制匹配结果
match_img = cv2.drawMatches(img1, kp1, img2, kp2,good_matches, None,flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)cv2.imshow("SIFT Feature Matching", match_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果:


5. 应用场景

  • 图像拼接:匹配两张图的 SIFT 特征,计算单应矩阵完成拼接。

  • 目标识别:提取特征后可用于训练分类器,识别目标物体。

  • 三维重建:利用多视图中的特征点匹配,恢复场景结构。


总结
SIFT 是一种鲁棒、稳定的局部特征描述子,对缩放、旋转、光照变化都不敏感。通过 cv2.SIFT_create() + detect() + compute() 可以轻松获得关键点和描述符,后续可用于图像匹配和目标识别。


文章转载自:

http://4TOBMlPK.rkfxc.cn
http://7riLbX4x.rkfxc.cn
http://BWDDv2lA.rkfxc.cn
http://8kXZnGJh.rkfxc.cn
http://vzGBo9QE.rkfxc.cn
http://cQAISzW5.rkfxc.cn
http://X45MnqC9.rkfxc.cn
http://oWkXPTX6.rkfxc.cn
http://L4O3SkTw.rkfxc.cn
http://wbpL79uE.rkfxc.cn
http://xv2QT04E.rkfxc.cn
http://aJW4QUjM.rkfxc.cn
http://YaMvZdW6.rkfxc.cn
http://ijBsgsHc.rkfxc.cn
http://3x0FLpv7.rkfxc.cn
http://lNvRyLyp.rkfxc.cn
http://X4QDpd73.rkfxc.cn
http://UahPz6Zs.rkfxc.cn
http://6ZRSJS9I.rkfxc.cn
http://cyY6pNHa.rkfxc.cn
http://eWK5K8lC.rkfxc.cn
http://059Ron3t.rkfxc.cn
http://ErP3hXqe.rkfxc.cn
http://FyoufgH1.rkfxc.cn
http://8P1wajsc.rkfxc.cn
http://48gXzqOi.rkfxc.cn
http://ghS8TKYg.rkfxc.cn
http://3hYNdbIR.rkfxc.cn
http://M0vkUixu.rkfxc.cn
http://njNM9FuE.rkfxc.cn
http://www.dtcms.com/a/384003.html

相关文章:

  • Android开发-SharedPreferences
  • SpringBoot的自动配置原理及常见注解
  • Java内部类内存泄漏解析:`this$0`引用的隐秘风险
  • 快速掌握Dify+Chrome MCP:打造网页操控AI助手
  • 【cpp Trip第1栈】vector
  • 详解 new 和 delete
  • 基于PassGAN的密码训练系统设计与实现
  • 避开Java日期格式化陷阱:`yyyy`与`YYYY`的正确使用
  • SpringCloud与Dubbo实战对决:从协议到治理的全维度选型指南(一)
  • SAP HANA Scale-out 04:CalculationView优化
  • 删除文件夹里的网盘图标
  • MPC模型预测控制:一种先进的控制策略
  • 【数据集】基于观测的全球月度网格化海表pCO₂与海气CO₂通量产品及其月气候平均值
  • RS485简介
  • Claude Code vs Codex
  • 多语言编码Agent解决方案(5)-IntelliJ插件实现
  • 光纤入户技术:原理、策略与市场博弈
  • DeerFlow实践: 日程管理智能体应用框架设计
  • spring、springboot、springCloud
  • Thymeleaf
  • 美团首款AI Agent产品“小美”公测,AI会带来什么?
  • 在 UE5 中配置 SVN 版本工具
  • Qwen3 模型结构解析
  • class_8:java继承
  • Django模型与数据库表映射的两种方式
  • 国产化监控方案:金仓数据库 + Nagios 从零搭建指南,核心指标实时掌握
  • 【Linux探索学习】第一篇Linux的基本指令(1)——开启Linux学习第一篇
  • 关于android.permission.CAPTURE_AUDIO_OUTPUT
  • Android安卓项目调试之Gradle 与 Gradle Wrapper的概念以及常用gradle命令深度详解-优雅草卓伊凡
  • Redis和数据库的一致性