opencv学习笔记4:sift特征

目录

一.基本概念介绍

1.关键点

2.尺度空间

二.SIFT特征提取简介

1.SIFT特征介绍

2.SIFT特征提取的实质

3.SIFT算法分解为如下四步:

三.逐步详解

0.整体流程:

(1)定义关键点

1.构建尺度空间

——子八度(Octave)的构建逻辑:高斯模糊 +下采样 计算示例

2.关键点定位<检测DOG尺度空间极值点>

(1)满足尺度变化的连续性的前提下找极值点

(2)关键点定位

(3)移除边缘点:

①介绍主曲率:

②主曲率相差最大是边缘点

③利用海森矩阵找边缘点

3.关键点描述

 (1)确定方向的原理

代码实现:


b站sift特征课程讲的太好了,链接如下,推荐观看!

【11-2-7 尺度不变特征变换SIFT】 https://www.bilibili.com/video/BV161UKYjE5z/?share_source=copy_web&vd_source=c5e7aba5c7851f39874c555b41af81df

一.基本概念介绍

1.关键点

关键点指的是图像中具有独特性质的点,这些点能代表图像的关键信息,具有相对稳定性和可重复性,即使图像发生一些变化(如旋转、缩放、光照改变等),仍然能被准确识别出来。

比如在一张风景照片中,山顶的顶点、建筑的拐角点,这些点在图像中的位置和特性比较突出,能够帮助计算机快速定位和理解图像的结构。

2.尺度空间

尺度空间是在多个尺度下观察目标,然后加以综合的分析、理解和应用。简单理解,就是让计算机能够像人一样,从不同 “距离” 或 “分辨率” 去观察图像。

想象一下,你看一幅画,站得远(大尺度,低分辨率),只能看到画的整体轮廓和大致结构;站得近(小尺度,高分辨率),就能看到画的细节,比如笔触、颜色的细微变化。在计算机视觉中,通过构建尺度空间,可以模拟这种不同距离观察图像的效果。

具体实现上,通常是对图像进行一系列不同程度的高斯模糊(用不同参数的高斯滤波器对图像进行处理),然后对模糊后的图像进行降采样(缩小图像尺寸),得到一组不同尺度的图像,这些图像就构成了尺度空间。这样一来,图像中的特征在不同尺度下都能被捕捉到,有助于发现那些具有尺度不变性的特征。

二.SIFT特征提取简介

1.SIFT特征介绍

SIFT (Scale-invariant feature transform) 尺度不变特征转换,它用来侦测与描述影像中的局部性特征,它在空间尺度中寻找极值点,并提取出其位置、尺度、旋转不变量

2.SIFT特征提取的实质

在不同的尺度空间上查找关键点(特征点),并计算出关键点的方向。SIFT所查找到的关键点是一些十分突出、不会因光照、仿射变换和噪音等因素而变化的点,如角点、边缘点、暗区的亮点及亮区的暗点等。

3.SIFT算法分解为如下四步

尺度空间极值检测:搜索所有尺度上的图像位置。通过高斯差分函数来识别潜在的对于尺度和旋转不变的关键点。

关键点定位:在每个候选的位置上,通过一个拟合精细的模型来确定位置和尺度。关键点的选择依据于它们的稳定程度。

关键点方向确定:基于图像局部的梯度方向,分配给每个关键点位置一个或多个方向。所有后面的对图像数据的操作都相对于关键点的方向、尺度和位置进行变换,从而保证了对于这些变换的不变性。

关键点描述:在每个关键点周围的邻域内,在选定的尺度上测量图像局部的梯度。这些梯度作为关键点的描述符,它允许比较大的局部形状的变形或光照变化。

三.逐步详解

0.整体流程:

(1)定义关键点

  1. 构建图像金字塔(八度)和高斯金字塔(层)。Construct image pyramid (octave) and Gaussian pyramid (layer)
  2. 计算相邻高斯之间的差异,获得DoG 。 calculate diff between adjacent Gaussian, get DoG
  3. 构建图像金字塔(八度)和高斯金字塔(层)计算相邻高斯之间的差异,获得DoG 。 Construct image pyramid (octave) and Gaussian pyramid (layer)calculate diff between adjacent Gaussian, get DoG
  4. 使用基于黑森矩阵的标准进行更正、删除低对比度点并删除边缘点。orrection, remove low contrast points, and remove edge pointsusing criterion based on Hessian Matrix.

1.构建尺度空间

这是一个初始化操作,尺度空间理论目的是模拟图像数据的多尺度特征。

作用:模拟人眼在不同距离看到的圈像,以便更好地找出图像的本质特征。
(近清晰、远模糊)(越远尺度越大)

高斯卷积核是实现尺度变换的唯一线性核(高斯模糊请看https://blog.youkuaiyun.com/zhang_si_hang/article/details/148469435?fromshare=blogdetail&sharetype=blogdetail&sharerId=148469435&sharerefer=PC&sharesource=zhang_si_hang&sharefrom=from_link——>大标题四“高斯滤波”),于是一副二维图像的尺度空间定义为:

(公式含义:对原始图像 I 进行不同尺度( σ 不同)的高斯模糊,得到的结果 L 就是该图像在对应尺度下的 “尺度空间表示”

其中 G(x,y,σ) 是尺度可变高斯函数

(x,y)是空间坐标,是尺度坐标。σ大小决定图像的平滑程度,σ 越大,图像越模糊(对应 “大尺度”),σ 越小,图像越清晰(对应 “小尺度”)。为了有效的在尺度空间检测到稳定的关键点,提出了高斯差分尺度空间(DOG scale-space)(Difference of Gaussians)。利用不同尺度的高斯差分核与图像卷积生成。

下图所示不同σ下图像尺度空间:

图像金字塔的建立:对于一幅图像I,建立其在不同尺度(scale)的图像,也成为子八度(octave),这是为了scale-invariant,也就是在任何尺度都能够有对应的特征点,第一个子八度的scale为原图大小,后面每个octave为上一个octave降采样的结果,即原图的1/4(长宽分别减半),构成下一个子八度(高一层金字塔)。
下面我们构建图像的高斯金字塔,它采用高斯函数对图像进行模糊以及降采样处理得到的,高斯金字塔构建过程中,为了尽可能多的保留原始图像信息,一般需对原始图像进行扩大两倍采样,即升采样(升采样不是必须的,可以直接使用原尺寸),在扩大的图像的基础之上构建高斯金字塔,然后对该尺寸下图像进行高斯模糊,几幅模糊之后的图像集合构成了一个Octave(子八度),然后对该Octave下选择一幅图像进行下采样,长和宽分别缩短一倍,图像面积变为原来四分之一。这幅图像就是下一个Octave的初始图像,在初始图像的基础上完成属于这个Octave的高斯模糊处理,以此类推完成整个算法所需要的所有八度构建,这样这个高斯金字塔就构建出来了

——子八度(Octave)的构建逻辑:高斯模糊 +下采样 计算示例

利用LoG(高斯拉普拉斯方法),即图像的二阶导数,可以在不同的尺度下检测图像的关键点信息,从而确定图像的特征点。但LoG的计算量大,效率低。所以我们通过两个相邻高斯尺度空间的图像的相减(相邻两层高斯模糊图像对应像素值直接对应相减得到高斯差分图像),得到DoG(高斯差分)来近似LoG。

为了计算DoG我们构建高斯差分金字塔,该金字塔是在上述的高斯金字塔的基础上构建而成的,建立过程是:在高斯金字塔中每个Octave中相邻两层相减就构成了高斯差分金字塔(相邻两层高斯模糊图像对应像素值直接对应相减得到高斯差分图像)。如下图所示:

左边是高斯金字塔图,每一列就是一个octave,右边是每个octave相邻两层减出来的高斯差分金字塔

2.关键点定位<检测DOG尺度空间极值点>

(1)满足尺度变化的连续性的前提下找极值点

为了寻找尺度空间的极值点,每一个采样点要和它所有的相邻点比较,看其是否比它的图像域和尺度域的相邻点大或者小。如图所示,中间的检测点和它同尺度的8个相邻点和上下相邻尺度对应的9×2个点共26个点比较,以确保在尺度空间和二维图像空间都检测到极值点。 一个点如果在DOG尺度空间本层以及上下两层的26个领域中是最大或最小值时,就认为该点是图像在该尺度下的一个特征点(看上面那个狗的图,相邻两层减出来的高斯差分金字塔,值大的),如图所示。

同一组中的相邻尺度(由于k的取值关系,肯定是上下层)之间进行寻找

s=3的情况

在极值比较的过程中,每一组图像的首末两层是无法进行极值比较的,为了满足尺度变化的连续性(下面有详解),我们在每一组图像的顶层继续用高斯模糊生成了 3 幅图像,高斯金字塔有每组S+3层图像。DOG金字塔每组有S+2层图像.

(2)关键点定位

由于DoG对噪声和边缘比较敏感,因此在上面高斯差分金字塔中检测到的局部极值点需经过进一步的检验才能精确定位为特征点。

阈值处理:找到极值点后防止波动产生错误的极值点,这个点可能会因为波动比附近的点大一点,但就是大一点点,则可以进行阈值处理D(x,y,σ) = L(x, y,kσ) - L(x,y,σ) >T,目的是让极值点比附近的点大的足够多才能认定是极值点,大一点的会小于T,就舍弃,不是极值点

还要通过二次函数拟合矫正极值点:使用尺度空间的泰勒级数展开来获得极值的准确位置, 如果极值点的 灰度值小于阈值(一般为0.03或0.04)就会被忽略掉。 在 OpenCV 中这种阈值被称为 contrastThreshold。

(3)移除边缘点

介绍主曲率

先回忆曲率:看下图左边图,曲率是描述一个曲线的弯曲程度,曲率圆的半径越小、曲率越大、曲线越弯曲。

主曲率:用于描述曲面在某点处的弯曲程度,以下是详细介绍:在曲面上的任意一点,都可以做出无数个包含该点法线的平面,这些平面与曲面相交会得到一系列的曲线,这些曲线在该点处的曲率称为法曲率。在所有的法曲率中,存在最大值和最小值 ,这两个值就被称为该点处的主曲率(最大最小曲率的面正好相差90°),通常记为k1和k2。

②主曲率相差最大是边缘点

边缘点的灰度值正常情况是右图的①灰度值跳度很大是边缘点,但由于高斯模糊平滑了,灰度值变成了②

变成三维就是左图红圈是边缘点,用横竖两个面去截这个点可以得到两个主曲率,横着截面由于截出的就是一条直线,曲率为0;竖着截就成了右边的②,则这个曲线变化很急剧,曲率最大,因此我们找到了两个主曲率。而边缘点处的两个主曲率差异很大

③利用海森矩阵找边缘点

海森矩阵:

海森矩阵的特征值和主曲率成正比,则只需要知道海森矩阵的两个特征值,特征值的差就是两个主曲率的差(上面三维图的海森矩阵就是右边这个二维矩阵,两个自变量x、y是平面上的横坐标和纵坐标,函数就是这个灰度值):

α和β是两个特征值/两个一大一小的主曲率,海森矩阵H和两个特征值的关系如下图

假设α=γβ,γ是系数

(H的迹)²/H的行列式=(特征值之和)²/特征值之积,最终推导出和γ的关系

又得知两个主曲率差距在γ=10时视为边缘点,则代入γ=10推导出该公式>12.1时为边缘点。

3.关键点描述

 (1)确定方向的原理

(本图解释梯度,先看本图的下面一个图)

计算关键点周围8×8区域的每个像素的梯度,并把每个4×4区域的像素点的梯度分成8个方向,根据每个像素点的方向和梯度幅值累加到对应方向(蓝色的直方图),可以根据直方图画出8个方向的幅值(右下角的图)

再把四个区域8个方向的幅值累加起来又得到一个直方图,如下图,最终由灰度值最大的方向确定为主方向。

(2)实际的sift确定方向的

Usually we use more grid to grasp more characteristics,e.g., we consider 16 grids, where each corresponding toa vector of 8

通常我们使用更多的网格来掌握更多的特征,例如,我们考虑16个网格,其中每个网格对应8的一个载体;也就是每个网格有8 方向的梯度直方图,每个方向区间就是描述子的一个维度,一共16个网格,16×8维=128维,所以一个sift描述子一共128维

即:每一个关键点要计算16×16区域的网格的梯度来确定该关键点的方向

解释左侧图像:

  • ①圆圈的中心怎么确定的?——就是关键点位置
  • ②圆圈大小由什么决定?——小圆是高斯差分金字塔上更高层的关键点(图像更小但同是16×16范围内的视野更大),更宏观;大圆是高斯差分金字塔上低层的关键点,更细节。
  • ③圆圈内的直线就是关键点的主方向

代码实现:

import cv2
import matplotlib.pyplot as plt

# 1. 读取图像(转为灰度图,SIFT通常在单通道图上操作)
img = cv2.imread("test_image.jpg")  # 替换为你的图像路径
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 转为灰度图

# 2. 初始化SIFT检测器
sift = cv2.SIFT_create()  # OpenCV 4.x写法;3.x可使用cv2.xfeatures2d.SIFT_create()

# 3. 检测关键点并计算描述子
# kp:关键点列表(包含位置、尺度、方向等信息)
# des:描述子矩阵,形状为(n, 128),n为关键点数量,每个关键点对应128维特征
kp, des = sift.detectAndCompute(gray, None)  # None表示不使用掩码

# 4. 打印特征信息
print(f"检测到的关键点数量:{len(kp)}")
print(f"描述子形状:{des.shape}(每个关键点对应128维特征)")

# 5. 在图像上绘制关键点并显示
# drawKeypoints参数:原图、关键点、输出图、颜色、绘制模式
img_with_kp = cv2.drawKeypoints(
    img, 
    kp, 
    None, 
    color=(0, 255, 0),  # 关键点用绿色标记
    flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS  # 显示关键点的尺度和方向
)

# 转换为RGB格式(OpenCV默认BGR,matplotlib需RGB)
img_with_kp_rgb = cv2.cvtColor(img_with_kp, cv2.COLOR_BGR2RGB)

# 显示结果
plt.figure(figsize=(10, 6))
plt.imshow(img_with_kp_rgb)
plt.title("SIFT Key Points")
plt.axis("off")
plt.show()

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值