目录
2.利用sift.detectAndCompute()检测关键点并计算
0、关于SIFT的介绍
SIFT,即尺度不变特征变换,一种局部特征描述子,它在空间尺度中寻找极值点,并提取出其位置、尺度、旋转不变量。SIFT特征包括兴趣点检测器和描述子。SIFT描述子具有非常强的稳健性,这在很大程度上也是SIFT特征能够成功和流行的主要原因。自从SIFT出现后,许多与他本质上使用相同描述子的方法也相继出现。现在,SIFT描述符常和许多不同的兴趣点检测器相结合,有时甚至在整幅图像上密集使用。SIFT特征对于尺度、旋转和亮度都具有不变性,因此,它可以用于三维视角和噪声的可靠匹配。
1、兴趣点
高斯核是唯一可以产生多尺度空间的核函数——《Scale-space theory:A basic tool for analysing structures at different scales》
SIFT是采用高斯差分函数来定位兴趣点:
其中:
sigma为尺度空间因子,它决定了图像的模糊的程度。大尺度表现得是图像得概貌信息,小尺度表现得是图像得细节信息。
是指二维的高斯核,也就是
大家对于它应该还是比较熟悉吧;
是使用
模糊的灰度图像;
k是决定相差尺度的常数。
兴趣点是在图像位置和尺度变化下 D(x,σ) 的最大值和最小值点。这些候选位置点通过滤波去除不稳定点。基于一些准则,比如认为低对比度和位于边上的点不是兴趣点,这样可以去除一些候选的兴趣点。
2、描述子
上面讨论的兴趣点(关键点)位置描述子给出了兴趣点的位置和尺度信息。为了实现旋转不变性,基于每个点周围图像梯度的方向和大小,SIFT 描述子又引入了参考方向。SIFT 描述子使用主方向描述参考方向。主方向使用方向直方图(以大小为权重)来度量。
下面我们基于位置、尺度和方向信息来计算描述子。为了对图像亮度具有稳健性,SIFT 描述子使用图像梯度。下图所示为描述子的构造过程。
SIFT描述子会以每个像素点附近选取一个网格(标准为4*4),在每个子区域当中计算梯度方向直方图,每个子区域拼接起来组成描述子向量,而每个子区域的直方图拼接起来组成描述子向量,每个子区域使用 8 个小区间的方向直方图,会产生共128 个小区间的直方图(4×4×8=128)。
图解:
(a) 一个围绕兴趣点的网格结构,其中该网格已经按照梯度主方向进行旋转
(b) 在网格的一个子区域内构造梯度方向的8-bin直方图
(c) 在网格的每个子区域内提取直方图
(d) 拼接直方图,得到一个长的特征向量
SIFT算法实现
1.实例化sift
sift = cv2.xfeatures2d.SIFT_create()
2.利用sift.detectAndCompute()检测关键点并计算
kq, dst = sift.detectAndCompute(gray, None)
参数:
- gray:进行关键点检测的图像,注意要是灰度图像
返回:
- kp:关键点信息,包括位置,尺度,方向信息
- des:关键点描述符,每个关键点对应128个梯度信息的特征向量
3.将关键点检测结果绘制在图像上
cv2.drawKeypoints(pic2, kq, pic2, (0, 0, 255),
参数:
image:原始图像
keypoints:关键点信息,将其绘制在图像上
outputimage:输出图片,可以是原始图像
color:颜色设置,通过修改(b,g,r)的值,更改画笔的颜色,b=蓝色,g=绿色,r=红色。
flags:绘图功能的标识设置
- cv2.DRAW_MATCHES_FLAGS_DEFAULT:创建输出图像矩阵,使用现存的输出图像匹配对和特征点,对每一个关键点,对每一个关键点只绘制中间点.
- cv2.DRAW_MATCHES_FLAGS_DRAW_OVER_OUTIMG:不创建输出图像矩阵,而是在输出图像上绘制匹配对。
- cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS:对每一个特征点绘制带大小和方向的关键点图形。
- cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS:单点的特征点不被绘制。
Opencv实现
-
import cv2
-
import matplotlib.pyplot
as plt
-
-
# 1.读取灰度图像
-
pic1 = cv2.imread(
"Elon test.png")
-
gray = cv2.cvtColor(pic1, cv2.COLOR_BGR2GRAY)
-
# 2.SIFT实例化
-
sift = cv2.xfeatures2d.SIFT_create()
-
# 3.检测关键点
-
kq, dst = sift.detectAndCompute(gray,
None)
-
# 4.绘制关键点
-
pic2 = pic1.copy()
-
cv2.drawKeypoints(pic2, kq, pic2, (
0,
0,
255),
-
cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
# flags=4可以替换cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS
-
# 绘制图像
-
fig, axes = plt.subplots(nrows=
2, ncols=
2, figsize=(
10,
10))
-
axes[
0,
0].set_title(
"original")
-
axes[
0,
0].imshow(pic1[:, :, ::-
1])
-
axes[
0,
1].set_title(
"gary_scale")
-
axes[
0,
1].imshow(gray, plt.cm.gray)
-
axes[
1,
1].set_title(
"SIFT_feature_detect")
-
axes[
1,
1].imshow(pic2[:, :, ::-
1])
-
plt.show()
-
cv2.waitKey(
0)
注:代码来源于黑马教程以及ζั͡ ั͡雾 ั͡狼 ั͡✾的博客(26条消息) [图像识别]10.OpenCV的特征点检测 SIFT和SURF算法_ζั͡ ั͡雾 ั͡狼 ั͡✾的博客-CSDN博客_opencv sift目标检测
这里还有保姆级的,大家感兴趣的可以去学习,我只是作为了解。
(1条消息) Python实现SIFT算法,附详细公式推导和代码_Derle3er的博客-CSDN博客_python sift
总结
SIFT在图像的不变特征提取拥有无与伦比的优势,但并不完美,仍然存在实时性不高,有时特征点较少,对边缘光滑的目标无法准确提取特征点等缺陷。
转载:https://blog.csdn.net/m0_62919535/article/details/127452171