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

news2024/10/1 1:22:01

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

文章目录

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

一、介绍

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

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

学习目标

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

二、什么是 SIFT 算法?

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

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

幅度表示像素的强度,方向表示像素的方向。

有了这些像素的幅度和方向值,我们现在就可以创建直方图。

创建震级和方向的直方图
在 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.coloradmin.cn/o/2066022.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【LLM大模型论文日更】| QAEA-DR:一个用于密集检索的统一文本增强框架

论文:https://arxiv.org/pdf/2407.20207代码:未开源机构:鹏城实验室领域:稠密检索发表:arXiv 研究背景 研究问题:这篇文章要解决的问题是密集检索(Dense Retrieval)中,将…

Windows:Node.js下载与安装教程

1、进入nodejs官网:https://nodejs.org/en 2、配置系统参数 3、运行cmd,输入 node -v 出现安装版本即安装成功

Keil C51 插件 检测所有if语句

此插件解决的问题 Keil 插件 -- Python 代码 import chardet, sys, glob, re from pathlib import Pathfrom collections import deque# 变量名字典 key--数据名 value--数据s类型 variable_dic {}# 初始化一个空的二维数组 matrix [] # 列表的头数据 header_list [] # 列表…

Tina5 Linux开发

准备开发环境 首先准备一台 Ubuntu 20.04 / Ubuntu 18.04 / Ubuntu 16.04 / Ubuntu 14.04 的虚拟机或实体机,其他系统没有测试过出 BUG 不管。 更新系统,安装基础软件包 sudo apt-get update sudo apt-get upgrade -y sudo apt-get install build-ess…

保护网站安全,了解常见的几种网络攻击

随着互联网技术的迅猛发展,网站作为信息展示和交互的重要平台,面临着日益复杂的网络攻击威胁。从简单的口令入侵到复杂的分布式拒绝服务(DDoS)攻击,网络攻击手段层出不穷,给网站所有者带来了巨大的挑战。今…

sqlilabs less21-25关手工注入

第21关 一.登录页面 二 .Burp Suite 抓包,进入重放器 三.查询数据库 先进行编码 )and updatexml(1,concat(1,database()),1)# 四.查表,先进行编码 )and updatexml(1,concat(1,(select group_concat(table_name) from information_schema.tables where…

王老师 linux c++ 通信架构 笔记(五)编译后生成的 nginx 可执行程序的启动与 nginx 选项

(22) 启动 nginx : 上网测试一下: 端口号 介绍: (23) 因为 nginx 监听知名端口号 80 ,http 服务。也可以知名端口号,格式如下: 生产环境下可以设置 ngi…

扬中网站建设创建网站

扬中网站建设:打造企业更强大的数字名片 随着互联网的发展,网站已经成为企业不可或缺的一部分。对于扬中市的企业而言,建设一个专业的网站不仅能提升品牌形象,更能拓展市场,提高竞争力。本文将为您介绍扬中网站建设的重…

【jetson交叉编译(1)】nvidia jetson 系列开发板交叉编译方法,CUDA依赖程序

资源 Toolchain Information jetson-linux jetpack 文章目录 资源1 方案1 qemu-aarch64-static和docker 容器编译jetson2 方案2 模拟器交叉编译器2.1 应对库缺失的情况,进行环境准备2.1.1 模拟器(方案1)2.1.2 在jetson上面进行安装(方案2) 2…

yolov8行人车辆检测与计数系统

yolov8行人车辆检测与计数系统(PythonYOLOv8deepsort车辆追踪深度学习模型清新界面) (1)YOL v8算法实现,模型一键切换更新; (2)检测图片、视频等图像中的各目标数目; &am…

2024数学建模国赛水奖攻略(也可适用其他比赛)

很多同学私信我,问学校要求参加数模比赛,但对建模和编程不太擅长,又不想浪费时间,该怎么办。今天我想和大家分享一些关于数学建模比赛的经验,特别是如何水奖的攻略。 一、选题技巧 有句话说得好,选择比努力…

彻底解决win7系统文件夹选项高级设置是空白

需求背景 win7系统的文件夹选项-高级设置里面是空白的,效果图如下。 解决方法 1、新建txt文本文档 2、文档内容 复制下面的内容到txt文件中,然后保存。 Windows Registry Editor Version 5.00[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Ad…

第七届强网杯-PWN-【WTOA】

文章目录 参考WebAssemblyWasmtime调试逆向源码exp 参考 WebAssembly实践指南——C和Rust通过wasmtime实现相互调用实例 WebAssembly WebAssembly是一种可移植的二进制指令集格式,其本身与平台无关,类似于Java的class文件字节码。 WebAssembly本来的…

Springsecurity中的Eureka报错:Cannot execute request on any known server

完整报错信息: com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server 报错体现: 访问eureka控制面板: 访问测试地址: 控制台报错: 可能的报错原因&#xff…

Python之列表解析和用matplotlib模块绘制图形

列表解析用matplotlib模块绘制成图形导入模块numpy阵列将列表转为阵列arrange函数创建阵列广播 使用matplotilib将阵列绘制成图 列表解析 列表解析式用紧凑的方式来构造列表。 语法: [表达式 for循环 条件] 例如:要得到0-20的偶数列表。需要在0-20中循环…

CyberScraper-2077+simple-one-api:使用大模型爬虫

大模型相关目录 大模型,包括部署微调prompt/Agent应用开发、知识库增强、数据库增强、知识图谱增强、自然语言处理、多模态等大模型应用开发内容 从0起步,扬帆起航。 swift与Internvl下的多模态大模型分布式微调指南(附代码和数据&#xff…

IT6113: 高速MIPI DSI 4通道转8通道转接芯片资料

1、产品概述: 芯片将 SOC输出的4通道高速 Mipi DSI 视频转换为8通道半速 DSI 显示器,用于平板电脑、智能手机、笔记本电脑、 VR、智能手表等应用,分割器模式也可用。 2、产品说明 : IT6113 MIPI DSI 视频桥是一个4通道进、8通道出…

2024安卓iOS免签封装源码/解决APP误报毒/可打包和上传APP/自动实现5分钟随机更换签名

源码简介: 2024全新安卓iOS免签封装源码,它可处理apk报毒,解决APP误报毒。不仅可打包APP,也可上传APK。自动实现5分钟随机更换包名和签名系统源码。 解决app误报毒,可打包APP可上传APK,并且自动实现5分钟…

ShardingSphere导致的NPE

1. 项目背景 工程内使用shardingsphere支持分库分表,上层使用的MybatisPlus,有一张表的操作总是报NullPointException。 2. 异常堆栈 ### SQL: INSERT INTO t_tg_message ( update_id, from_id, from_user_name, chat_id, type, data, text, create_…

领夹麦克风哪个品牌音质最好?一文揭秘国内最好的麦克风品牌

在数字化直播与Vlog盛行的今天,无线领夹麦克风凭借其便捷性与高音质,成为了内容创作者们的必备好物。但随着市场的迅速扩张,无线领夹麦克风领域也悄然滋生了一系列乱象。品牌众多,质量却良莠不齐,消费者稍有不慎便可能…