OpenCV-Python(32):SIFT算法

这篇具有很好参考价值的文章主要介绍了OpenCV-Python(32):SIFT算法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目标

  • 学习SIFT 算法的概念
  • 学习在图像中查找SIFT关键点和描述符

原理及介绍

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

OpenCV-Python(32):SIFT算法,opencv,算法,SIFT,尺度不变特征变换,图像匹配


        所以在2004 年,D.Lowe 提出了一个新的算法,尺度不变特征变换(SIFT),这个算法可以帮助我们提取图像中的关键点并计算它们的描述符。

步骤

        SIFT 算法主要由以下几步构成。接下来我们来分步来进行学习。 

尺度空间极值检测

        从上图我们可以很明显的看出来在不同的尺度空间不能使用相同的窗口检测极值点。对小的角点要用小的窗口,对大的角角点只能使用大的窗口。为了达到这个目的我们要使用尺度空间滤波器。(尺度空间滤波器可以使用一系列具有不同方差σ 的高斯卷积核构成)。使用具有不同方差值σ 的高斯拉普拉斯算子(LoG)对图像进行卷积,LoG 由于具有不同的方差值σ 所以可以用来检测不
同大小的斑点(当LoG 的方差σ 与斑点直径相等时能够使斑点完全平滑)。简单来说,方差σ 就是一个尺度变换因子。例如,上图中使用一个小方差σ 的高斯卷积核是可以很好的检测出小的角点,而使用大方差σ 的高斯卷积核时可以很好的检测到大的角点。所以我们可以在尺度空间和二维平面中检测到局部最大值。如(x,y,σ), 这表示在σ 尺度中(x,y)点可能是一个关键点。(高斯方差的大小与窗口的大小存在一个倍数关系:窗口大小等于6 倍方差加1,所以方差的大小也决定了窗口大小)

        但是这个LoG 的计算量非常大,所以SIFT 算法使用高斯差分算子(DoG)来对LoG 做近似。这里需要再介绍一下图像金字塔,我们可以通过减少采样(如只取奇数行或奇数列)来构成一组图像尺寸(1,0.5,0.25 等)不同的金字塔,然后对这一组图像中的每一张图像使用具有不同方差σ 的高斯卷积核构建出具有不同分辨率的图像金字塔(不同的尺度空间)。DoG 就是这组具有不同分辨率的图像金字塔中相邻的两层之间的差值。如下图所示:

OpenCV-Python(32):SIFT算法,opencv,算法,SIFT,尺度不变特征变换,图像匹配

        在DoG 搞定之后,就可以在不同的尺度空间和2D 平面中搜索局部最大值了。对于图像中的一个像素点而言,它需要与自己周围的8 邻域以及尺度空间中上下两层中的相邻的18(2x9)个点相比。如果是局部最大值,它就可能是一个关键点。基本上来说,关键点是图像在相应尺度空间中的最好代表。如下图所示:

OpenCV-Python(32):SIFT算法,opencv,算法,SIFT,尺度不变特征变换,图像匹配

        该算法的作者在文章中给出了SIFT 参数的经验值:octaves=4(通过降低采样从而减小图像尺寸,构成尺寸减小的图像金字塔4 层)尺度空间为5,也就是每个尺寸使用5 个不同方差的高斯核卷积,初始方差是1.6,k 等于√2 等。 

关键点(极值点)定位

        一旦找到关键点,我们就需要对它们进行修正从而得到更准确的结果。作者使用尺度空间的泰勒级数展开来获得极值的准确位置。如果极值点的灰度值小于阈值(0.03)就会被忽略掉。在OpenCV 中这种阈值被称为contrastThreshold
        DoG 算法对边界非常敏感,所以我们必须把边界去掉。前面我们讲的Harris 算法除了可以用于角点检测之外还可以用于检测边界。作者就是使用了同样的思想。作者使用2x2 的Hessian 矩计算算主曲率。从Harris 角点检测的算法中,我们知道当一个特征值远远大于另外一个特征值时检测到的是边界。所以他们使用了一个简单的函数,如果比例高于阈值(OpenCV 中称为边界阈值)这个关键点就会被忽略。文章中给出的边界阈值为10。所以低对比度的关键点和边界关键点都会被去掉,剩下的就是我们感兴趣的关键点了。

为关键点(极值点)指定方向参数

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

关键点描述符

        新的关键点描述符被创建了。选取与关键点周围一个16x16 的邻域,把它分成16 个4x4 的小方块,为每个小方块创建一个具有8 个bin 的方向直方图。总共加加来有128 个bin。由此组成长度为128 的向量就构成了关键点描述符。除此之外,还要进行几个测量以达到对光照变化、旋转等的稳定性。

关键地匹配

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

OpenCV中的SIFT算法

        现在让我们来看看OpenCV 中关于SIFT 的函数吧。让我们从关键点检测和绘制开始吧。首先我们先创建对象。我们可以使用不同的参数,这并不是必须的,关于参数的解释可以查看文档。

import cv2
import numpy as np
img = cv2.imread('home.jpg')
gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
sift = cv2.SIFT()
kp = sift.detect(gray,None)
img=cv2.drawKeypoints(gray,kp)
cv2.imwrite('sift_keypoints.jpg',img)

         函数sift.detect() 可以在图像中找到关键点。如果你只想在图像中的一个区域搜索的话也可以创建一个掩模图像作为参数使用。返回的关键点是一个带有很多不同属性的特殊结构体,这些属性中包含它的坐标(x,y),有意义的邻域大小、确定其方向的角度等。

        OpenCV 也提供了绘制关键点的函数cv2.drawKeyPoints(),它可以在关键点的部位绘制一个小圆圈。如果你设置参数为cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS,就会绘制代表关键点大小的圆圈甚至可以绘制制关键点的方向。

img=cv2.drawKeypoints(gray,kp,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv2.imwrite('sift_keypoints.jpg',img)

结果如下:

OpenCV-Python(32):SIFT算法,opencv,算法,SIFT,尺度不变特征变换,图像匹配

现在来计算关键点描述符,OpenCV 提供了两种方法:

  1. 由于我们已经找到了关键点,我们可以使用函数sift.compute() 来计算这些关键点的描述符。例如:kp, des = sift.compute(gray, kp)。
  2. 如果还没有找到关键点,还可以使用函数sift.detectAndCompute()一步到位直接找到关键点并计算出其描述符。

这里我们来看看第二个方法:
        这里 kp 是一个关键点列表。des 是一个Numpy 数组,其大小是关键点数目乘以128。
所以我们得到了关键点和描述符等。现在我们想看看如何在不同图像之间进行关键点匹配,这就是我们在接下来的章节将要学习的内容。文章来源地址https://www.toymoban.com/news/detail-783487.html

图像匹配示例

import cv2
import numpy as np
#from psd_tools import PSDImage

# 1) psd to png
'''psd1 = PSDImage.load('200x800.ai.psd')
psd1.as_PIL().save('psd_image_to_detect1.png')

psd2 = PSDImage.load('800x200.ai.psd')
psd2.as_PIL().save('psd_image_to_detect2.png')'''


# 2) 以灰度图的形式读入图片

psd_img_1 = cv2.imread('./images/1.png', cv2.IMREAD_GRAYSCALE)
psd_img_2 = cv2.imread('./images/2.png', cv2.IMREAD_GRAYSCALE)

# 3) SIFT特征计算
sift = cv2.xfeatures2d.SIFT_create()

psd_kp1, psd_des1 = sift.detectAndCompute(psd_img_1, None)
psd_kp2, psd_des2 = sift.detectAndCompute(psd_img_2, None)

# 4) Flann特征匹配
FLANN_INDEX_KDTREE = 1
index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)
search_params = dict(checks=50)

flann = cv2.FlannBasedMatcher(index_params, search_params)
matches = flann.knnMatch(psd_des1, psd_des2, k=2)
goodMatch = []
for m, n in matches:
	# goodMatch是经过筛选的优质配对,如果2个配对中第一匹配的距离小于第二匹配的距离的1/2,基本可以说明这个第一配对是两幅图像中独特的,不重复的特征点,可以保留。
    if m.distance < 0.75*n.distance:
        goodMatch.append(m)
# 增加一个维度
goodMatch = np.expand_dims(goodMatch, 1)
print(goodMatch[:50])

img_out = cv2.drawMatchesKnn(psd_img_1, psd_kp1, psd_img_2, psd_kp2, goodMatch[:15], None, flags=2)

cv2.imshow('image', img_out)#展示图片
cv2.waitKey(0)#等待按键按下
cv2.destroyAllWindows()#清除所有窗口

到了这里,关于OpenCV-Python(32):SIFT算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • OpenCV-Python(35):BRIEF算法

            BRIEF( Binary Robust Independent Elementary Features )是一种用于计算机视觉中特征点描述子的算法。它是一种 二进制描述子 ,通过比较图像上不同位置的像素值来生成特征点的描述子。         BRIEF算法的基本思想是选取一组固定的像素对,并比较这些像素对之间的

    2024年01月23日
    浏览(35)
  • python数字图像处理基础(八)——harris角点检测、图像尺度空间、SIFT算法

    原理 Harris 角点检测是一种用于在图像中检测角点的算法。角点是图像中局部区域的交叉点或者突出的特征点。Harris 角点检测算法旨在寻找图像中对于平移、旋转和尺度变化具有不变性的角点。 该算法通过计算图像中每个像素点的灰度值的变化,来识别角点。具体来说,Ha

    2024年01月19日
    浏览(43)
  • OpenCV-Python中的图像处理-GrabCut算法交互式前景提取

    cv2.grabCut(img: Mat, mask: typing.Optional[Mat], rect, bgdModel, fgdModel, iterCount, mode=…) img:输入图像 mask:掩模图像,用来确定那些区域是背景,前景,可能是前景/背景等。 可以设置为: cv2.GC_BGD,cv2.GC_FGD,cv2.GC_PR_BGD,cv2.GC_PR_FGD,或者直接输入 0,1,2,3 也行。 rect :包含前景的矩形,格式为

    2024年02月12日
    浏览(43)
  • Python与OpenCV环境中,借助SIFT、单应性、KNN以及Ransac技术进行实现的图像拼接算法详细解析及应用

    一、引言 在当今数字化时代,图像处理技术的重要性不言而喻。它在无人驾驶、计算机视觉、人脸识别等领域发挥着关键作用。作为图像处理的一个重要部分,图像拼接算法是实现广阔视野图像的重要手段。今天我们将会讲解在Python和OpenCV环境下,如何使用SIFT、单应性、K

    2024年02月15日
    浏览(40)
  • 【OpenCV-Python】——机器学习kNN算法&SVM算法&k均值聚类算法&深度学习图像识别&对象检测

    目录 前言: 1、机器学习 1.1 kNN算法 1.2 SVM算法(支持向量机)  1.3 k均值聚类算

    2024年02月05日
    浏览(45)
  • 学习笔记:Opencv实现图像特征提取算法SIFT

    2023.8.19 为了在暑假内实现深度学习的进阶学习,特意学习一下传统算法,分享学习心得,记录学习日常 SIFT的百科: SIFT = Scale Invariant Feature Transform, 尺度不变特征转换 全网最详细SIFT算法原理实现_ssift算法_Tc.小浩的博客-CSDN博客 在环境配置中要配置opencv: pip install opencv-c

    2024年02月12日
    浏览(44)
  • 【OpenCV-Python】——单/多模板匹配&分水岭算法图像分割&图像金字塔&交互式前景提取

    目录 前言: 1、模板匹配 1.1 单目标匹配 1.2 多目标匹配 2、图像分割

    2024年02月07日
    浏览(49)
  • OpenCV使用SURF和SIFT算法报错解决记录

    OpenCV使用SURF和SIFT算法报错解决记录 1.报错代码,使用以下两种写法都会报错 第一种报错 AttributeError: module ‘cv2’ has no attribute ‘xfeatures2d’ 第二种报错 AttributeError: module ‘cv2’ has no attribute ‘SURF_create’ 2.查找网络上的解决办法,大部分分为两种 SIFT和SURF算法申请了专利,

    2024年02月07日
    浏览(37)
  • Opencv-Python入门———配置opencv-python环境

    1.1配置python环境及编译器(Pycharm)下载 进入Pycharm官网下载Pycharm   PyCharm: the Python IDE for Professional Developers by JetBrains https://www.jetbrains.com/pycharm/ 进入Python官网下载最新版本Python Download Python | Python.org https://www.python.org/downloads/ 安装细则可参照博客 (36条消息) python,pycharm的安装

    2024年02月11日
    浏览(37)
  • opencv的SIFT样例(CPP/python)

    结论说明: 两种代码在同一个环境上的,相同的图片大小和数量(19张图片),运行耗时如下: python c++ 差距不会很明显,但是如果文件很多,并且使用多线程/多进程,会有一个比较明显的差距。

    2024年01月19日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包