SIFT特征

SIFT:尺度不变特征变换

你好! 这是我对于 SIFT原理 的学习理解,记录的是关键结论,有理解错误的地方麻烦指出。如果你想SIFT的原理推导, 可以学习下面这个视频。

学习参考自:鲁鹏计算机视觉bilibil视频

提出原因

  • 目标:能在不同尺度下检测出同一个特征点,且不受亮度、对比度、旋转、仿射变换影响
  • 起初LoG 高斯拉普拉斯算子,可以检测边缘且具有尺度不变性。简单理解是:用高斯的二阶导的卷积核,卷积之后在某个大小的方差 σ \sigma σ会取得极值 ,检测区域半径r= 2 σ \sqrt[]{2}\sigma 2 σ
  • 由于LoG计算量比较大,提出用DoG高斯差分算子来近似替代;
  • D o G ( σ ) = G ( x , y , k σ ) − G ( x , y , σ ) DoG(\sigma )=G(x,y,k\sigma )-G(x,y,\sigma ) DoG(σ)=G(x,y,)G(x,y,σ)

1. 尺度空间极值检测Scale-space Extrema Detection

为了用尽量少的计算得到连续尺度的卷积结果,建立高斯差分金字塔。
在这里插入图片描述
s:每组输出的层数
k:尺度因子 k = 2 1 s 2^{\frac{1}{s} } 2s1 (这样设置是为了最后输出的尺度连续)

高斯金字塔组内:

  1. 每组内有s+3层
  2. 每组得到高斯差分s+2层,因为对空间上相邻27个点非极大值抑制,得到s个尺度(每3层的中间层中取最大点)
  3. σ \sigma σ层求 k σ k\sigma :
    • 由于大高斯核可以由小高斯核叠加实现,且能减少计算量
    • 符合勾股定理:例如方差5的高斯卷积 = 方差3 * 方差 4。
    • k 2 − 1 σ \sqrt{k^2-1}\sigma k21 σ的卷积核,在原本 σ \sigma σ上卷积可以得到 k σ k\sigma

高斯金字塔组间:

  1. 第二组的第一层,从第一组的上往下数第3层下采样得到,依此类推。(因为该层 k n = 2 s 1 s = 2 ) k^{n } = 2^{s\frac{1}{s}} = 2) kn=2ss1=2)
  2. 因为更大的 σ \sigma σ,意味着更大的卷积核,更多的计算量。我们可以通过下采样缩小图片减少计算量,同时使用 σ \sigma σ的卷积,来近似 2 σ 2\sigma 2σ的效果。

2. 关键点定位Keypoint Localization

目的:剔除弱变化点、边缘点

  1. 极值点的强度小于阈值(论文中为0.03),则拒绝该极值点。
  2. 对改变量E进行泰勒展开(Harris角度的内容), E ( u , v ) = ( u v ) M ( u v ) E(u,v)=\begin{pmatrix}u & v \end{pmatrix} M \binom{u}{v} E(u,v)=(uv)M(vu), 再对M进行对角化,比较两个特征值大小,如果一个远大于另一个则为边缘,两个都大则为角点。这里比值大于10的点被筛去。

3. 定向分配Orientation Assignment

目的:方向归一化

  1. 对关键点周围正方形窗口(例如16x16)的每个像素点求梯度方向。
  2. 每10度为1个方向,共36个方向,建立梯度直方图(还要进行特征点尺度 σ \sigma σ的1.5倍的高斯加权),最高峰为主方向。
  3. 高于最高峰80%的作为辅方向
    在这里插入图片描述

4. 关键点描述符Keypoint Descriptor

  1. 关键点周围有一个16x16的邻域。它被分成16个4x4大小的子块。对于每个子块,计算每个像素的梯度,统计成8维的(每个45度)直方图。因此,表示成一个4 x 4 x 8 = 128维向量。

5. 关键点匹配Keypoint Matching

  1. 比较时,用两个点对应的8维向量逐个计算欧式距离。

通过识别两幅图像之间的最近邻居来匹配关键点。但在某些情况下,第二个最接近的匹配可能非常接近第一个。它可能是由于噪音或其他原因发生的。在这种情况下,计算最近距离与次最近距离的比率。如果大于0.8,则拒绝。根据论文,它消除了大约90%的错误匹配,而只丢弃了5%的正确匹配。1

6. opencv实现sift特征提取

import cv2
import os
import numpy as np
##sift特征点提取

#图片所在目录
direct_images = r"C:\Users\huangq\Desktop\images"
#获取目录下所有文件
files = os.listdir(direct_images)
#过滤出所有jpg文件
jpg_files = [f for f in files if f.endswith('.JPG')]
#读取并处理每个jpg
# SIFT特征点检测器
sift = cv2.SIFT_create()
# SIFT处理代码  
keypoints_and_descriptors = {}
for file in jpg_files:
    #地址合并
    file_path = os.path.join(direct_images, file)
    image = cv2.imread(file_path)
    #图上检测SIFT特征点
    keypoints, descriptors = sift.detectAndCompute(image, None)
    #存储
    keypoints_and_descriptors[file] = {'keypoints': keypoints, 'descriptors': descriptors}
    
    # #绘制
    image_with_keypoints = np.copy(image)
    cv2.drawKeypoints(image, keypoints, image_with_keypoints, flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
    # #显示图像
    width = 1080 #image.shape[1]
    height = int(image.shape[0] * (width / image.shape[1]))
    resized_image = cv2.resize(image_with_keypoints, (width, height))
    
    cv2.imshow("SIFT KeyPoints", resized_image)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

输出效果:
在这里插入图片描述

7. opencv实现sift特征匹配

##sift特征点匹配
bf = cv2.BFMatcher()
a = keypoints_and_descriptors[jpg_files[0]]['descriptors']
b = keypoints_and_descriptors[jpg_files[1]]['descriptors']
matches = bf.knnMatch(a,b,k=2)

good = []
for m,n in matches:
    if m.distance < 0.75*n.distance:
        good.append([m])
kp1 = keypoints_and_descriptors[jpg_files[0]]['keypoints']
kp2 = keypoints_and_descriptors[jpg_files[1]]['keypoints']
img1 = keypoints_and_descriptors[jpg_files[0]]['image']
img2 = keypoints_and_descriptors[jpg_files[1]]['image']
img3 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,good,None,flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
# plt.imshow(img3),plt.show()
# cv2.imshow("SIFT KeyPoints", img3)
# cv2.waitKey(0)

cv2.namedWindow('image', cv2.WINDOW_NORMAL)  # 创建可调整大小的窗口  
cv2.imshow('image', img3)  # 显示图像  
cv2.waitKey(0)  
cv2.destroyAllWindows()

输出效果:
在这里插入图片描述


  1. https://docs.opencv.org/4.5.4/da/df5/tutorial_py_sift_intro.html ↩︎

  • 24
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值