OPENCV学习笔记 - SIFT 尺度不变特征变换 Python

  • 为什么我们需要SIFT尺度不变特征变换?
  • 第一,建立高斯差分金字塔
  • 第二,极值点的精确定位
  • 第三,确定关键点的主方向
  • 第四,构建关键点的描述符
  • 代码
  • 结果

树袋熊的前言
这个算法设计步骤之多,细节之复杂,让我整个人都想拿脑袋撞墙。刚开始在youtube上找了国外教授的CV课来理解,英语让我想撞完墙去跳河。然后在bilibili上找到了一个比较清晰的教程,感谢up主:会飞的吴克 https://www.bilibili.com/video/av47799675?p=2 有条件看视频的同学请移步,(教程部分图片不适合公共场合观看…emmmm…)然后其中遇到不懂的地方又查询了博主https://blog.csdn.net/dcrmg/article/details/52561656的博文!

虽然说对算法大概的思想和步骤有了理解,但很多细节仍有许许多多不清楚,远远没到可以看懂/写出源码的程度!要继续加油鸭~

为什么我们需要SIFT尺度不变特征变换?


OPENCV TUTORIAL 的解释(图三)
在前面两节我们学习了一些角点检测技术,比如 Harris 等。它们具有旋转不变特性,即使图片发生了旋转,我们也能找到同样的角点。很明显即使图像发生旋转之后角点还是角点。那如果我们对图像进行缩放呢?角点可能就不再是角点了。以下图为例,在一副小图中使用一个小的窗口可以检测到一个角点,但是如果图像被放大,再使用同样的窗口就检测不到角点了。

更进一步的理解(图一/二)
我们用摄像机拍摄的照片,往往遵循近大远小,近处清晰,远处模糊的定理。也就是说,除非是从图一的45°视角拍摄的图片(图一)可以用单一大小的窗口实现检测,其他具有透视的照片(图二)我们都需要对不同的角点使用不同的窗口,以实现更加精确的加测,这就是SIFT要实现的目标
.
.
.
.
.

第一,建立高斯差分金字塔

补充:我们使用高斯金字塔主要是为了模拟摄像机中近大远小,近处清晰远处模糊的成像原理。且有数学证明,仅高斯模糊可以达到这个效果,任何其他的模糊算子都不能模拟摄像机的成像。

高斯金字塔构建过程:

  1. 先将原图像扩大一倍之后作为高斯金字塔的第1组第1层,将第1组第1层图像经高斯卷积(其实就是高斯平滑或称高斯滤波)之后作为第1组金字塔的第2层,高斯卷积函数为:

  2. 对于参数σ,在Sift算子中取的是固定值1.6。

  3. 将σ乘以一个比例系数k,等到一个新的平滑因子σ=k*σ,用它来平滑第1组第2层图像,结果图像作为第3层。

  4. 如此这般重复,最后得到L层图像,在同一组中,每一层图像的尺寸都是一样的,只是平滑系数不一样。它们对应的平滑系数分别为:0,σ,kσ,k2σ,k3σ……k^(L-2)σ。

  5. 将第1组倒数第三层图像作比例因子为2的降采样,得到的图像作为第2组的第1层,然后对第2组的第1层图像做平滑因子为σ的高斯平滑,得到第2组的第2层,就像步骤2中一样,如此得到第2组的L层图像,同组内它们的尺寸是一样的,对应的平滑系数分别为:0,σ,kσ,k2σ,k3σ……k^(L-2)σ。但是在尺寸方面第2组是第1组图像的一半。

这样反复执行,就可以得到一共O组,每组L层,共计O*L个图像,这些图像一起就构成了高斯金字塔,结构如下:

高斯差分金字塔的构建过程:
然后我们把同一层相邻两层相减就得到了高斯金字塔
这些长得黑乎乎的图像就是差分金字塔的实际显示效果,只在第1组第1层差分图像上模糊可以看到一个轮廓。但其实这里边包含了大量特征点信息,只是我们人眼已经分辨不出来了。

下边对这些DOG图像进行归一化,可有很明显的看到差分图像所蕴含的特征,并且有一些特征是在不同模糊程度、不同尺度下都存在的,这些特征正是Sift所要提取的“稳定”特征:

第二,极值点的精确定位

1. 阈值化(去除那些噪声极致点)

如果 abs(val)>0.5*T/n,那么,就认为这些点是噪声而不是极值点
其中T=0.04(经验值)
其中n=每一组的高斯差分金字塔中要取特征的图片层数(即高斯金字塔一组层数-3)

2. 在高斯差分金字塔中寻找极致点

去除噪声点后,我们就可以在查分金字塔的三层中寻找极值点了。对于图像中的一个像素点而言,它需要与自己周围的 8 邻域,以及尺度空间中上下两层中的相邻的 18(2x9)个点相比。如果是局部最大值,它就可能是一个关键点。基本上来说关键点是图像在相应尺度空间中的最好代表。

3. 在高斯差分金字塔中寻找极致点

但是,因为图像信息本来就是离散的,而层数之间的σ也是离散的,所以我们找的并不是真正的极值点,而只是真正极值点周围的一个点。为了找到准确的极值点,我们对极值点进行三元二阶的泰勒展开如下
(哭了,并不知道这里为什么要用泰勒展开式来求得精确的极值点,哪位大神能告诉我!)


然后我们进行求导,来确定这个展开式的极值点

注:其中的计算遵循有限差分求导


4. 舍去低对比度的点
如果 abs(f(x))<T/n,则舍去
其中 T=0.04
其中n=每一组的高斯差分金字塔中要取特征的图片层数(即高斯金字塔一组层数-3)

5.边缘效应的去除

  • 这一步我们希望去除那些是edge而不是corner的点,(同harris corner中的概念),也就是说我们希望曲线的两个曲率相差不大。

  • 在数学中,Hessian matrix 的特征值与曲线的曲率成正比,所以我们希望Hessian matrix(如下)的特征值相差不大。

    Dxx(x,y)代表x的二阶偏导, Dxy(x,y)代表x,y的混合偏导

  • 但是一般我们是不会作死去算特征值的,我们还是通过trace和det转换这个问题

  • 设大的特征值为α,小的特征值为β,Γ = α/β
    Tr(H) = Dxx + Dyy = α + β
    Det(H) = DxxDyy-(Dxy)^2 = αβ

    希望把 “α和β相差不大” 的问题转化成 “trace,det的不等式”

  • 若Det(H)<0,即α和β异号,直接抛弃(相差太多)

  • 若Det(H)>0

    我们希望 “α和β相差不大”,就是希望 "Γ尽量接近于1”(这里建议取Γ=10)
    因为α>β,所以Γ>1,而上式在[1, +∞]上单调递增
    所以转换, "Γ尽量接近于1” 为以下等式

第三,确定关键点的主方向

现在我们要为每一个关键点赋予一个反向参数,这样它才会具有旋转不变性。获取关键点(所在尺度空间)的邻域,然后计算这个区域的梯度级和方向。根据计算得到的结果创建一个含有 36 个 bins(每 10 度一个 bin)的方向直方图。(使用当前尺度空间 σ 值的 1.5 倍为方差的圆形高斯窗口和梯度级做权重)。直方图中的峰值为主方向参数,如果其他的任何柱子的高度高于峰值的80% 被认为是辅方向。这就会在相同的尺度空间相同的位置构建除具有不同方向的关键点。这对于匹配的稳定性会有所帮助。

第四,构建关键点的描述符


新的关键点描述符被创建了。选取与关键点周围一个 16x16 的邻域(这个领域不是直接在高斯金字塔中选取的,而是在讲其转到主方向后再选取的,为了保证旋转不变性)。把邻域 16 个 4x4 的小方块,为每个小方块创建一个具有 8 个 bin 的方向直方图(描述这个小方块的梯度方向的分布)。总共加起来有 128 个 bin。由此组成长为 128 的向量就构成了关键点描述符。

下一步就可以采用关键点特征向量的欧式距离来作为两幅图像中关键点的相似性判定度量。取第一个图的某个关键点,通过遍历找到第二幅图像中的距离最近的那个关键点。但有些情况下,第二个距离最近的关键点与第一个距离最近的关键点靠的太近。这可能是由于噪声等引起的。此时要计算最近距离与第二近距离的比值。如果比值大于 0.8,就忽略掉。这会去除 90% 的错误匹配,同时只去除 5% 的正确匹配。如文章所说。
这就是 SIFT 算法的摘要。非常推荐你阅读原始文献,这会加深你对算法的理解。请记住这个算法是受专利保护的。所以这个算法包含在 OpenCV 中的收费模块中。

代码

这里我用的摄像头哈

import cv2
import numpy as npcap = cv2.VideoCapture(0)while True:_, frame = cap.read()gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)sift = cv2.xfeatures2d.SIFT_create()kp = sift.detect(gray, None)frame = cv2.drawKeypoints(gray, kp, frame,     flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)cv2.imshow('frame', frame)if cv2.waitKey(5) & 0xff == 27:breakcv2.destroyAllWindows()
cap.release()

结果

那个小轴轴就是梯度方向!!神!奇!然后可以看到前景(我的头发等)中景(桌上的杂物)和远景(墙上的灯)都识别的很好。

OPENCV学习笔记 - SIFT 尺度不变特征变换 Python相关推荐

  1. OpenCV系列之SIFT尺度不变特征变换 | 三十九

    目标 在这一章当中, 我们将学习SIFT算法的概念 我们将学习找到SIFT关键点和描述算符. 理论 在前两章中,我们看到了一些像Harris这样的拐角检测器.它们是旋转不变的,这意味着即使图像旋转了, ...

  2. [转载]SIFT(尺度不变特征变换)算法小结

    原文地址:SIFT(尺度不变特征变换)算法小结[转]作者:慕容天峰 最近一直在看SIFT算法.Sift是David Lowe于1999年提出的局部特征描述子,并于2004年进行了更深入的发展和完善.S ...

  3. OpenCV(22)SIFT尺度不变特征变换(纯理论)

    SIFT算法(纯理论) 1.引言 前面介绍了Harris和Shi-Tomasi角点检测算法,这两种算法具有旋转不变性,但不具有尺度不变性.以下图为例,在左侧小图中可以检测到角点,但是图像被放大后,在使 ...

  4. python-opencv图像处理之SIFT尺度不变特征变换

    在这一章当中,我们将学习SIFT算法的概念,找到SIFT关键点和描述算符. 一.概念 在前面,我们看到了一些像Harris这样的拐角检测器.它们是旋转不变的,这意味着即使图像旋转了,我们也可以找到相同 ...

  5. Opencv学习笔记 透视变换/单应性变换

    1.透视变换概述 透视变换(Perspective Transformation),又称Homography Transformation. 在计算机视觉领域,空间中同一平面的任意两幅图像通过单应性关 ...

  6. OpenCV中的尺度不变特征变换(SIFT Scale-Invariant Feature Transform)

    OpenCV中的尺度不变特征变换(SIFT Scale-Invariant Feature Transform) 1. 效果图 2. 原理 2.1 步骤 2.2 opencv实现方法 2.3 SIFT ...

  7. 数字图像处理学习笔记(二):SIFT(尺度不变特征变换)算法

    数字图像处理学习笔记(二):SIFT(尺度不变特征变换)算法 一.概述: 提到特征点算法,首先就是大名鼎鼎的SIFT算法了.SIFT的全称是Scale Invariant Feature Transf ...

  8. 数字图像处理学习笔记(三):ORB算法(尺度不变特征变换)Oriented FAST and Rotated BRIEF

    数字图像处理学习笔记(三):ORB算法(尺度不变特征变换)Oriented FAST and Rotated BRIEF 一.概述 参考:特征点匹配+特征检测方法汇总 ORB的全称是Oriented ...

  9. Python+OpenCV:尺度不变特征变换(SIFT)的加速健壮特性(SURF)

    Python+OpenCV:尺度不变特征变换(SIFT)的加速健壮特性(SURF) 理论 In SIFT, Low approximated Laplacian of Gaussian with Di ...

最新文章

  1. OpenGL入门学习(十二) 【转】
  2. java获取当前系统时间毫秒_java 获取当前系统时间简写 | 学步园
  3. Spring Cloud原理
  4. 【洛谷2986】【USACO10MAR】伟大的奶牛聚集
  5. 对比Oracle和Mysql在锁机制上的类似和差异点
  6. 听说年底这些公司在裁员?是不是真的......
  7. linux实验报告makefile,linux实验二交叉编译和Makefile实验报告.doc
  8. ASP.NET文件上传大小的限制解决方案
  9. gc java 单核_JAVA应用性能监控之JVM层GC调优
  10. len函数实例python_Python通过len函数返回对象长度
  11. 推荐两个适合代码的字体
  12. flexPaper制作在线文库阅读器思路
  13. unity 实现PPT动画效果切换图片
  14. JS 案例 改变网页背景颜色
  15. 解决宏碁5750g ubuntu无法调整和保存屏幕亮度的问题
  16. 数据库的研究内容主要有哪些方面?
  17. 安庆集团-冲刺日志(第八天)
  18. 大数据挖掘机器学习人工智能的维恩图战争
  19. html垂直线性渐变,再说CSS3渐变——线性渐变
  20. 印度软件和中国软件工程师_如何成为印度的软件工程师?

热门文章

  1. win10系统下配置maven环境
  2. headless=脑残?
  3. 安装jdk并配置环境变量
  4. Unity: How to build and debug external DLLs
  5. 关于用Java程序实现8421码权限管理 -第三部分
  6. Linux 3.进程间通信(IPC)(pipe 无名管道、mkfifo 有名管道、ftok、msgget、msgrcv、msgsnd、msgctl 消息队列)
  7. 网络安全与网站安全及计算机安全:如何使用Kali Linux进行Windows计算机操作系统安全演练
  8. Docker 入门笔记 8 - Namespace 简介(中)
  9. C++四个数排序(从小到大)
  10. 零基础能不能学计算机专业,零基础新手可不可以学会计算机电脑