【OpenCV】SIFT(尺度不变特征变换)算法?

news/2024/9/18 15:03:15/ 标签: opencv, 算法, 人工智能

在这里插入图片描述
关键词:SIFT Algorithm

文章目录

  • 一、介绍
  • 二、什么是 SIFT 算法
  • 三、人类与机器识别
    • 3.1 SIFT 在计算机视觉中的应用
    • 3.2 SIFT 关键点的优势
    • 3.3 示例演示
  • 四、关键点定位
    • 关键点选择
  • 五、实验任务指导
    • 5.1 计算大小和方向
    • 5.2 创建震级和方向的直方图
    • 5.2 创建震级和方向的直方图
    • 5.3 关键点描述符
    • 5.4 关键点描述符
  • 六、特征匹配
    • 特征匹配代码
  • 七、结论
    • 7.1 关键要点

一、介绍

   您是否想过,即使从模糊的照片或不同的角度,您也能立即识别朋友的脸?这是因为您的大脑擅长识别关键特征并建立联系。尺度不变特征变换 (SIFT) 算法是计算机视觉领域的一种强大工具,它模仿了这种能力。

   与人类不同,机器很难识别图像中具有不同比例或视角的物体。SIFT 弥补了这一差距。通过从图像中提取独特的特征,SIFT 允许机器将这些特征与同一物体的新图像进行匹配。这为图像识别、物体检测等领域的激动人心的应用铺平了道路。在本文中,我们将深入研究 SIFT 算法,并探索它如何赋予机器类似人类的图像识别能力。

   学习目标

   向初学者介绍强大的 SIFT(尺度不变特征变换)技术。
了解如何使用尺度不变特征变换算法执行特征匹配。
尝试使用 Python 编写 SIFT(尺度不变特征变换)算法

二、什么是 SIFT 算法

2.1 SIFT 算法描述

   SIFT(尺度不变特征变换)算法是一种用于特征检测和描述的计算机视觉技术。它可以检测图像中对尺度、旋转和仿射变换变化具有鲁棒性的独特关键点或特征。SIFT(尺度不变特征变换)的工作原理是根据关键点的局部强度极值来识别关键点,并计算描述符来捕获这些关键点周围的局部图像信息。然后,这些描述符可用于图像匹配、对象识别和图像检索等任务。

2.2 SIFT 算法示例

   看看下面的图片集,想想它们之间的共同元素:
在这里插入图片描述

SIFT 算法示例
   当然是辉煌的埃菲尔铁塔!眼尖的你们还会注意到,每张图片都有不同的背景,是从不同的角度拍摄的,而且前景中也有不同的物体(在某些情况下)。

三、人类与机器识别

   我敢肯定,你只需要花一小会儿的时间就能搞清楚这一切。图像以奇怪的角度旋转或放大到只显示一半的铁塔都没关系。这主要是因为你已经多次看过埃菲尔铁塔的图像,你的记忆很容易回忆起它的特征。我们自然而然地明白,图像的比例或角度可能会发生变化,但物体保持不变。

   但机器在处理同样的事情时却遇到了巨大的困难。如果我们改变某些东西(如角度或比例),它们识别图像中的物体将是一项挑战。好消息是,机器非常灵活,我们可以教它们以几乎人类的水平识别图像。

3.1 SIFT 在计算机视觉中的应用

   这是计算机视觉工作中最令人兴奋的方面之一!

   SIFT 计算机视觉,即尺度不变特征变换,是计算机视觉中的一种特征检测算法

   SIFT 算法有助于定位图像中的局部特征,通常称为图像的“关键点”。这些关键点是比例和旋转不变量,可用于各种计算机视觉应用,如图像匹配、对象检测、场景检测等。

3.2 SIFT 关键点的优势

   我们还可以在模型训练期间使用 SIFT 生成的关键点作为图像的特征。SIFT 特征、边缘特征或 HOG 特征的主要优点是它们不受图像大小或方向的影响。

   示例演示
   例如,这是另一张埃菲尔铁塔的图片及其较小版本。第一张图像中物体的关键点与第二张图像中找到的关键点相匹配。当另一张图像中的物体略微旋转时,两张图像也会出现同样的情况。很神奇,对吧?
在这里插入图片描述

3.3 示例演示

  • SIFT 流程
       让我们了解一下这些关键点是如何识别的,以及用于确保尺度和旋转不变性的技术是什么。从广义上讲,整个过程可以分为 4 个部分:

   构建尺度空间:确保特征与尺度无关
   关键点定位:识别合适的特征或关键点
   方向分配:确保关键点旋转不变
   关键点描述符:为每个关键点分配一个唯一的指纹
   最后,我们可以使用这些关键点进行特征匹配!

  •    构建尺度空间
    我们需要在忽略任何噪声的情况下识别给定输入图像中最独特的特征。此外,我们需要确保特征不依赖于尺度。这些都是关键概念,让我们逐一讨论它们。

  •    高斯模糊
    我们使用高斯模糊技术来减少图像中的噪音。

   对于图像中的每个像素,高斯模糊都会根据其具有特定 sigma 值的相邻像素计算一个值。下面是应用高斯模糊之前和之后的图像示例。如您所见,纹理和细节已从图像中删除,只保留了相关信息(如形状和边缘):
在这里插入图片描述

  •    高斯模糊
    高斯模糊有助于图像处理,并成功去除了图像中的噪声,并且我们突出了图像的重要特征。现在,我们需要确保这些特征与尺度相关。这意味着我们将通过创建“尺度空间”在多个尺度上搜索这些特征。

   尺度空间是从单幅图像生成的具有不同尺度的图像集合。

   因此,这些模糊图像是针对多个比例创建的。要创建一组不同比例的新图像,我们将获取原始图像并将比例缩小一半。对于每个新图像,我们将创建模糊版本,如上所示。

   下面是一个可以更好地理解它的例子。我们有大小为 (275, 183) 的原始图像和尺寸为 (138, 92) 的缩放图像。对于这两幅图像,都会创建两个模糊图像:
在这里插入图片描述

高斯模糊 | SIFT(尺度不变特征变换)算法
   你可能会想——我们需要缩放图像多少次,每张缩放后的图像需要创建多少张模糊图像?理想的八度数应该是四个,每个八度的模糊图像数量应该是五个。
在这里插入图片描述

高斯模糊 | SIFT(尺度不变特征变换)算法

  • 高斯差分
       到目前为止,我们已经创建了多个尺度的图像(通常用 σ 表示),并对每个尺度的图像使用高斯模糊来降低图像中的噪声。接下来,我们将尝试使用一种称为高斯差分或 DoG 的技术来增强特征。

   高斯差分是一种特征增强算法,它涉及从原始图像的另一个较不模糊的版本中减去一个模糊版本。

   DoG 会通过以相同的比例从前一个图像中减去每个图像,为每个八度创建另一组图像。以下是 DoG 实现方式的直观说明:
在这里插入图片描述

高斯差分

   注:该图片取自原论文。为了更清晰的视图,现在以垂直形式表示八度音阶。

   让我们在比例空间中为图像创建 DoG。请看下图。左侧有 5 张图像,全部来自第一个八度(因此具有相同的比例)。每个后续图像都是通过对前一个图像应用高斯模糊创建的。

   右边是四幅通过减去连续高斯函数生成的图像。结果令人瞠目结舌!
在这里插入图片描述

  • 连续高斯
       我们增强了每幅图像的功能。请注意,这里我仅针对第一个八度音阶实施了该功能,但所有八度音阶都会发生相同的过程。

   现在我们有了一组新的图像,我们将用它来找到重要的关键点。

四、关键点定位

   创建图像后,下一步是从图像中找到可用于特征匹配的重要关键点。这个想法是找到图像的局部最大值和最小值。这部分分为两个步骤:

  • 找到局部最大值和最小值
       删除低对比度关键点(关键点选择)
    局部最大值和局部最小值
    为了找到局部最大值和最小值,我们遍历图像中的每个像素并将其与相邻像素进行比较。

   当我说“邻近”时,这不仅包括该图像的周围像素(像素所在的位置),还包括八度音阶中前一个和下一个图像的九个像素。

   这意味着每个像素值都会与其他 26 个像素值进行比较,以确定它是否是局部最大值/最小值(称为极值)。例如,在下图中,我们有来自第一个八度的三幅图像。标记为x的像素与相邻像素(绿色)进行比较,如果它是相邻像素中最高或最低的,则被选为关键点或兴趣点:
在这里插入图片描述

   我们现在有了代表图像且尺度不变的潜在关键点。我们将对选定的关键点进行最后的检查,以确保这些是代表图像的最准确的关键点。

关键点选择

   太棒了!到目前为止,我们已经成功生成了尺度不变的关键点。但其中一些关键点可能对噪声不够稳健。这就是为什么我们需要进行最后检查,以确保我们拥有最准确的关键点来表示图像特征。

   因此,我们将消除对比度低或非常靠近边缘的关键点。

   为了处理低对比度的关键点,我们会对每个关键点进行二阶泰勒展开式计算。如果结果值小于 0.03(幅度),我们会拒绝该关键点。

   那么我们该如何处理剩余的关键点呢?好吧,我们进行检查以识别位置不佳的关键点。这些关键点靠近边缘,具有较高的边缘响应,但可能对少量噪声不够稳健。二阶 Hessian 矩阵用于识别此类关键点。您可以在此处了解背后的数学原理。

   现在我们已经执行了对比度测试和边缘测试来拒绝不稳定的关键点,我们现在将为每个关键点分配一个方向值以使旋转不变。

五、实验任务指导

   在此阶段,我们有一组稳定的图像关键点。现在我们将为每个关键点分配一个方向,以便它们不受旋转影响。我们可以再次将此步骤分为两个较小的步骤:

5.1 计算大小和方向

   创建震级和方向的直方图
计算震级和方向
请考虑下面显示的示例图像:
在这里插入图片描述

计算震级和方向
   假设我们想找到红色像素值的幅度和方向。为此,我们将通过取 55 与 46 和 56 与 42 之间的差来计算 x 和 y 方向上的梯度。结果分别为 Gx = 9 和 Gy = 14。

   一旦我们有了梯度,我们就可以使用以下公式找到幅度和方向:

  • 幅度 = √[(G x ) 2 +(G y ) 2 ] = 16.64
  • Φ = atan(Gy / Gx) = atan(1.55) = 57.17
  • 幅度表示像素的强度,方向表示像素的方向。
  • 有了这些像素的幅度和方向值,我们现在就可以创建直方图。

5.2 创建震级和方向的直方图

   在 x 轴上,我们将为角度值设置区间,例如 0-9、10-19、20-29 和最高 360。由于我们的角度值为 57,因此它将位于第 6 个区间。第 6 个区间值将与像素的大小成比例,即 16.64。我们将对关键点周围的所有像素执行此操作。

   这就是我们得到下面直方图的方法:
在这里插入图片描述

5.2 创建震级和方向的直方图

   您可以参考本文,了解有关计算梯度、幅度、方向和绘制直方图的更详细解释 -方向梯度直方图的宝贵介绍。

   此直方图将在某个点达到峰值。我们看到峰值所在的箱体将是关键点的方向。此外,如果存在另一个显著峰值(在 80% 到 100% 之间),则会生成另一个关键点,其幅度和尺度与用于生成直方图的关键点相同。角度或方向将等于具有峰值的新箱体。

   实际上,此时我们可以说关键点的数量可能会略有增加。

5.3 关键点描述符

   这是 SIFT(尺度不变特征变换)计算机视觉的最后一步。到目前为止,我们已经有了尺度不变和旋转不变的稳定关键点。在本节中,我们将使用相邻像素、它们的方向和它们的大小来为该关键点生成一个唯一的指纹,称为“描述符”。

   此外,由于我们使用周围的像素,描述符将部分地不受图像的照明或亮度的影响。

   我们首先在关键点周围取一个 16×16 的邻域。这个 16×16 块进一步划分为 4×4 子块,对于每个子块,我们使用幅度和方向生成直方图。
在这里插入图片描述

5.4 关键点描述符

   在此阶段,箱体大小会增加,我们只取 8 个箱体(而不是 36 个)。每个箭头代表 8 个箱体,箭头的长度定义量级。因此,每个关键点总共会有 128 个箱体值。

   下面是在 matplotlib 中使用 pyplot 的示例:

import cv2 
import matplotlib.pyplot as plt
%matplotlib inline#reading image
img1 = cv2.imread('eiffel_2.jpeg')  
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)#keypoints
sift = cv2.xfeatures2d.SIFT_create()
keypoints_1, descriptors_1 = sift.detectAndCompute(img1,None)img_1 = cv2.drawKeypoints(gray1,keypoints_1,img1)
plt.imshow(img_1)

matplotlib 中的 pyplot
在这里插入图片描述

六、特征匹配

   我们现在将使用 SIFT 计算机视觉特征进行特征匹配。为此,我下载了两张从不同位置拍摄的埃菲尔铁塔图像。你可以用任意两张你想要的图像来尝试。

   以下是我使用的两张图片:

在这里插入图片描述

import cv2 
import matplotlib.pyplot as plt
%matplotlib inline# read images
img1 = cv2.imread('eiffel_2.jpeg')  
img2 = cv2.imread('eiffel_1.jpg') img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)figure, ax = plt.subplots(1, 2, figsize=(16, 8))ax[0].imshow(img1, cmap='gray')
ax[1].imshow(img2, cmap='gray')

特征匹配代码

   现在,对于这两幅图像,我们将生成 SIFT 特征。首先,我们必须构建一个 SIFT 对象。我们首先使用 sift_create 创建一个 SIFT 计算机视觉对象,然后使用函数detectAndCompute获取关键点。它将返回两个值 - 关键点和 sift 计算机视觉描述符。

   让我们确定关键点并打印在每个图像中找到的关键点总数:

import cv2 
import matplotlib.pyplot as plt
%matplotlib inline# read images
img1 = cv2.imread('eiffel_2.jpeg')  
img2 = cv2.imread('eiffel_1.jpg') img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)#sift
sift = cv2.xfeatures2d.SIFT_create()keypoints_1, descriptors_1 = sift.detectAndCompute(img1,None)
keypoints_2, descriptors_2 = sift.detectAndCompute(img2,None)len(keypoints_1), len(keypoints_2)
283, 540

   接下来,让我们尝试将图像 1 中的特征与图像 2 中的特征进行匹配。我们将使用BFmatcher (强力匹配)模块中的match()函数。此外,我们将在匹配两幅图像的特征之间画线。这可以使用OpenCV python 中的drawMatches函数来完成。

import cv2 
import matplotlib.pyplot as plt
%matplotlib inline# read images
img1 = cv2.imread('eiffel_2.jpeg')  
img2 = cv2.imread('eiffel_1.jpg') img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)#sift
sift = cv2.xfeatures2d.SIFT_create()keypoints_1, descriptors_1 = sift.detectAndCompute(img1,None)
keypoints_2, descriptors_2 = sift.detectAndCompute(img2,None)#feature matching
bf = cv2.BFMatcher(cv2.NORM_L1, crossCheck=True)matches = bf.match(descriptors_1,descriptors_2)
matches = sorted(matches, key = lambda x:x.distance)img3 = cv2.drawMatches(img1, keypoints_1, img2, keypoints_2, matches[:50], img2, flags=2)
plt.imshow(img3),plt.show()

在这里插入图片描述

OpenCV python 中的 drawMatches 函数
   为了清晰起见,我在这里只绘制了 50 个匹配项。您可以根据自己的喜好增加匹配项的数量。要找出匹配的关键点数,我们可以打印变量matches的长度。在本例中,答案是 190。

七、结论

   在本文中,我们详细讨论了 SIFT 特征匹配算法。该网站为 SIFT 的每个步骤提供了出色的可视化效果。您可以添加自己的图像,它也会为该图像创建关键点。另一种流行的特征匹配算法是 SURF(加速稳健特征),它是 SIFT 的更快版本。我鼓励您也探索它。

   如果你是计算机视觉和图像数据领域的新手,我建议你查看以下课程:使用深度学习 2.0 的计算机视觉

7.1 关键要点

   SIFT(尺度不变特征变换)是一种强大的图像匹配技术,可以识别和匹配对缩放、旋转和仿射畸变不变的特征。
它在计算机视觉应用中得到广泛应用,包括图像匹配、对象识别和 3D 重建。
SIFT 技术生成具有不同尺度的图像的尺度空间,然后使用高斯差分 (DoG) 方法识别关键点。
   它还计算每个关键点的描述符,可用于特征匹配和对象识别。
您可以使用 Python 和 OpenCV 库实现 SIFT,该库提供了检测关键点、计算描述符和匹配特征的函数。


http://www.ppmy.cn/news/1516793.html

相关文章

博弈论详解 2(SG函数 和 SG定理)

传送门:博弈论详解 1(基本理论定义 和 Nim 游戏) 什么是 SG 函数 接着上次的讲解,我们来了解一个更通用的模型。我们把每一个状态变成一个点(在 Nim 游戏里就代表 a a a 数组),如果可以从一种…

安装Win10操作系统时找不到任何驱动器的解决方法

安装Win10操作系统时找不到任何驱动器的解决方法 有时候在一台新电脑上使用U盘安装系统时提示:我们找不到任何驱动器。 如下图所示: 解决方法: 一、按F12(不同电脑进入Bios的按键可能不同)将电脑进入Bios画面&#xf…

DataX(Doris同步数据到SelectDB)

背景 由于之前的doris数仓在本地的服务器,当数据量越来越大,服务器的性能达不到要求,查询数据经常超时,故需要把本地的doris数仓部署到云上,本文以阿里云为例,迁移工具使用的阿里开源的datax。 datax官方文…

client网络模块的开发和client与server端的部分联动调试

客户端网络模块的开发 我们需要先了解socket通信的流程 socket通信 server端的流程 client端的流程 对于closesocket()函数来说 closesocket()是用来关闭套接字的,将套接字的描述符从内存清除,并不是删除了那个套接字,只是切断了联系,所以我们如果重复调用,不closesocket()…

20240828 每日AI必读资讯

8岁女孩玩转AI编程,45分钟打造聊天机器人,Karpathy都看呆了 - 新晋顶流AI代码编辑器——Cursor,已经进化到了“0手工代码”阶段。 - 提供了多个AI模型,包括GPT-4、GPT-4o和Claude 3.5 Sonnet等,可以通过跟大模型聊天…

微服务——远程调用

为什么需要远程调用? 在微服务架构中,每个服务都是独立部署和运行的,它们之间需要相互协作以完成复杂的业务逻辑。因此,远程调用成为微服务之间通信的主要方式。通过远程调用,一个服务可以请求另一个服务执行某些操作或…

【Python机器学习】NLP概述——词序和语法

词的顺序很重要,那些在词序列(如句子)中控制词序的规则被称为语言的语法(也被称为文法)。这是之前的词袋或词向量例子中所丢弃的信息。在大多数简短的短语甚至许多完整的句子中,上述词向量近似方法都可以奏…

设计模式 7 桥接模式

设计模式 7 创建型模式(5):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式结构型模式(7):适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式、代理模式行为型模式&#xff0…

整合sentinel遇到的小问题

1.运行jar包 ,端口为默认8080 正确命令 java -Dserver.port8090 -Dcsp.sentinel.dashboard.server127.0.0.1:8090 -Dproject.namesentinel-dashboard -jar sentinel-dashboard-1.8.6.jar -D这些指令要在 -jar前面 在宝塔部署时,直接复制到运行命令后…

vue事件监听

我们可以使用 v-on 指令 (简写为 ) 来监听 DOM 事件,并在事件触发时执行对应的 1.回车事件(点击回车触发) confirm 适用uni-app keyup.enter 适用vue3 运用场景:通常在文本框输入的时候使用 2.点击事件(鼠标左键…

Cubase操作:如何修改每个音频块的名字 写歌习惯

如何修改每个音频块的名字 我对命名比较注重,之前用Cubase12,导入我手机中编辑过的Cubasis的工程时,发现中文部分有乱码…… 而且好像改名改得很费劲…… 后面通过多方咨询和探索思考,终于找到方法了! 可以先把信息…

【C#】【EXCEL】BumblebeeComponentsAnalysisGH_Ex_Ana_CondTopCount

这段代码定义了一个名为 GH_Ex_Ana_CondTopCount 的 Grasshopper 组件。它的主要功能是为 Excel 中的一个范围添加条件格式,具体是根据数值的大小高亮显示前N个(或后N个)数值。以下是该组件的详细介绍: 功能概述: 组件…

灵办AI搜索引擎和文档总结工具

前言—— 在信息爆炸的时代,如何高效地获取和处理知识成为了每个人面临的挑战。随着人工智能技术的迅猛发展,本文将深入探讨这一创新工具的功能与优势,以及如何在日常生活和工作中充分利用它,开启智能化的信息获取新篇章。 点击…

Part3-DOM学习笔记-操作元素

5.操作多个元素 5.1 排他思想 前面所述均为操作一个元素,给一个元素注册事件,如果是一组元素,就需要用循环的方式给元素注册事件。 我们想要给当前的元素实现某种样式,而其他的元素没有这个样式,这就需要用到排他思…

P2709 小B的询问

*原题链接* 非常简单的莫队板子题,让我们求出区间[l,r]中每个数出现次数的平方和,设枚举到,原来答案是res,如果加上后,则原来的变为,即res相比原来加上,删除同理。知道如何维护一个数的添加和删除后&#…

WIFI 配网

配网:指的是外部向WiFi模块提供SSID和密码,以便Wi-Fi模块可以连接指定的热点 常见的配网方式有:-键配网smart config、SoftAP配网、蓝牙配网、屏幕配网。 1.0 一键配网 2.0 蓝牙配网 一键配网的模式对应的厂加模式 3.0 状态机WIFI模组物联网 4.0 创建枚举结构体 ty…

Vue3.0项目实战(二)——大事件管理系统登录注册功能实现

目录 1. 登录注册页面 [element-plus 表单 & 表单校验] 1.1 注册登录 静态结构 & 基本切换 2. 注册功能 2.1 实现注册校验 2.2 注册前的预校验 2.3 封装 api 实现注册功能 3. 登录功能 3.1 实现登录校验 3.2 登录前的预校验 & 登录成功 1. 登录注册页面 […

Go反射四讲---第三讲:如何使用反射操作函数,获取函数的相关信息?

反射-函数 这是我们反射四讲的第三讲,本次给大家讲解如何使用反射处理函数相关的操作。 在这一部分,向大家展示如何输出方法的信息并执行调用。 输出信息,包含方法名,方法参数,返回值。 最后,如何使用反…

【小趴菜前端实习日记4】

el-table数据更新视图不更新的问题、el-dialog居中展示、el-form表单验证之对象属性验证、vue2过滤器 一、el-table数据更新视图不更新的问题二、el-dialog居中展示三、el-form表单验证之对象属性验证四、vue2过滤器 一、el-table数据更新视图不更新的问题 手动触发元素更新&a…

Linux:Socket网络编程

目录 1. 理解源 IP 地址和目的 IP 地址 2:认识端口号 3:端口号范围划分 4:理解源端口号和目的端口号 5:理解Socket(套接字) 6:两个传输协议 (TCP/UDP) 6.1:User Datagram Prot…