OpenCV-Python(32):SIFT算法

news2024/11/17 15:45:03

目标

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

原理及介绍

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


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

步骤

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

尺度空间极值检测

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

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

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

        该算法的作者在文章中给出了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 提供了两种方法:

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

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

图像匹配示例

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()#清除所有窗口

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1377369.html

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

相关文章

基于SkyEye仿真6678处理器:实现国产操作系统ReWorks仿真运行

信号处理的数据量以及实时性的要求随着嵌入式技术的发展不断提高&#xff0c;众多厂商和研究所选择多核DSP处理器芯片去替代原有的单核DSP&#xff0c;并运行嵌入式操作系统来保证信号处理的实时性以及精确性。然而受到硬件资源或者项目实施周期限制&#xff0c;软件工程师调试…

JS实现网页轮播图

轮播图也称为焦点图&#xff0c;是网页中比较常见的网页特效。 1、页面基本结构&#xff1a; 大盒子focus&#xff0c;里面包含 左右按钮ul 包含很多个li &#xff08;每个li里面包含了图片&#xff09;下面有很多个小圆圈 因为我们想要点击按钮&#xff0c;轮播图左右播放&a…

“消费新纪元:从传统消费到消费增值的跨越!“

你是否已经厌倦了传统消费模式&#xff0c;感觉每一次购物只是让钱从左手流到右手&#xff1f;现在&#xff0c;一个新的消费模式正在兴起&#xff0c;它让你的消费变得更有价值&#xff01; 消费增值是一种创新的消费理念&#xff0c;它让你在享受优质商品和服务的同时&#x…

学生公寓里如何进行安全用电管理

安科瑞武陈燕acrelcy 学校肩负着教育、科研和社会服务的重任&#xff0c;是构成社会的重要社区&#xff0c;也是资源能源消费的大户&#xff0c;其中学生公寓电能的消耗占到了学校整体能源消耗的很大部分&#xff0c;根据国家建设节约型校园的要求&#xff0c;各高校对电能的管…

2023年全国职业院校技能大赛软件测试赛题—单元测试卷①

单元测试 一、任务要求 题目1&#xff1a;根据下列流程图编写程序实现相应分析处理并显示结果。返回文字“xa*a*b的值&#xff1a;”和x的值&#xff1b;返回文字“xa-b的值&#xff1a;”和x的值&#xff1b;返回文字“xab的值&#xff1a;”和x的值。其中变量a、b均须为整型…

Oracle 19c OCP 1z0 082考场真题解析第32题

考试科目&#xff1a;1Z0-083 考试题量&#xff1a;85 通过分数&#xff1a;57% 考试时间&#xff1a;150min本文为云贝教育郭一军&#xff08;微信&#xff1a;guoyJoe&#xff09;原创&#xff0c;请尊重知识产权&#xff0c;转发请注明出处&#xff0c;不接受任何抄袭、演绎…

在 Nvidia Docker 容器编译构建显存优化加速组件 xFormers

本篇文章&#xff0c;聊聊如何在新版本 PyTorch 和 CUDA 容器环境中完成 xFormers 的编译构建。 让你的模型应用能够跑的更快。 写在前面 xFormers 是 FaceBook Research &#xff08;Meta&#xff09;开源的使用率非常高的 Transformers 加速选型&#xff0c;当我们使用大模…

可以打印试卷的软件有哪些?推荐这几款

可以打印试卷的软件有哪些&#xff1f;随着科技的飞速发展&#xff0c;越来越多的学习工具如雨后春笋般涌现&#xff0c;其中&#xff0c;能够打印试卷的软件尤其受到广大学生和家长的青睐。这些软件不仅方便快捷&#xff0c;而且内容丰富&#xff0c;可以满足不同学科、不同年…

从零学Java Set集合

Java Set集合 文章目录 Java Set集合1 Set 集合2 Set实现类2.1 HashSet【重点】2.2 LinkedHashSet2.3 TreeSet 3 Comparator 自定义比较器 1 Set 集合 特点&#xff1a;无序无下标、元素不可重复。 方法&#xff1a;全部继承自Collection中的方法。 常用方法&#xff1a; publ…

windos exe 以服务的形式运行(开机运行)

windos 品台编写的 小工具 exe 或者 批处理 .bat 经常需要开机自启动&#xff0c;可以直接把它 加在开启启动项&#xff0c;或者做成 windos服务&#xff0c;这样既可以开机自动启动而且还可以 防止误触关闭掉&#xff1b; windos 以服务启动 exe/bat 的通用方式&#xff1…

js逆向第18例:猿人学第15题备周则意怠-常见则不疑

文章目录 一、前言二、定位关键参数三、代码实现四、参考文献一、前言 任务十五:抓取这5页的数字,计算加和并提交结果 二、定位关键参数 先找到数据接口 可以看到接口的url地址中存在变量m如下 进入堆栈,定位m值 如下图逻辑很清晰,可以看到window.

ChatGPT到底能做什么呢?

1、熟练掌握ChatGPT提示词技巧及各种应用方法&#xff0c;并成为工作中的助手。 2、通过案例掌握ChatGPT撰写、修改论文及工作报告&#xff0c;提供写作能力及优化工作 3、熟练掌握ChatGPT融合相关插件的应用&#xff0c;完成数据分析、编程以及深度学习等相关科研项目。 4、…

【AI视野·今日Sound 声学论文速览 第四十三期】Mon, 8 Jan 2024

AI视野今日CS.Sound 声学论文速览 Mon, 8 Jan 2024 Totally 6 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Sound Papers MusicAOG: an Energy-Based Model for Learning and Sampling a Hierarchical Representation of Symbolic Music Authors Yikai Qian, Tia…

实现秒杀功能设计

页面 登录页面 登录成功后&#xff0c;跳转商品列表 商品列表页 加载商品信息 商品详情页 根据商品id查出商品信息返回VO&#xff08;包括rmiaoshaStatus、emainSeconds&#xff09;前端根据数据展示秒杀按钮&#xff0c;点击开始秒杀 订单详情页 秒杀页面设置 后端返回秒杀…

在线陪玩软件开发系统(APP小程序H5、平台、搭建)游戏陪玩系统APP开发 源码搭建,源码交付,支持二开!

一、游戏陪玩系统APP的核心功能 1. 匹配系统&#xff1a;通过智能匹配算法&#xff0c;将寻找陪玩的玩家与愿意提供陪玩服务的玩家进行匹配&#xff0c;确保双方的需求能够得到满足。 2. 实时通讯&#xff1a;提供实时语音和文字聊天功能&#xff0c;让玩家和陪玩者可以在游戏…

Js - 函数(四)

1.函数简单介绍 什么是函数&#xff1f; 函数&#xff08;function&#xff09;是执行特定任务的一段代码块 为什么需要函数&#xff1f; 可以实现代码复用&#xff0c;提高开发效率 2.函数使用 函数的声明语法 函数名命名规范 函数的调用语法 函数体 函数体是函数的构…

【Scala】——流程控制

1 if-else 分支控制 让程序有选择的的执行&#xff0c;分支控制有三种&#xff1a;单分支、双分支、多分支 1.1单分支 if (条件表达式) {执行代码块 }1.2 双分支 if (条件表达式) {执行代码块 1 } else {执行代码块 2 }1.3 多分支 if (条件表达式1) {执行代码块 1 } else …

选中图层为什么不能建立3D模型---模大狮模型网

在Photoshop CC 2021(也就是PS6)中&#xff0c;要将选中的图层转换为3D模型&#xff0c;需要满足以下几个条件&#xff1a; 图层类型支持&#xff1a;只有特定类型的图层可以被转换为3D模型。通常&#xff0c;普通的像素图层、矢量图层和形状图层都可以进行转换。但是&#xff…

仲晶同志简历

女&#xff0c;汉族。1972年出生&#xff0c;国防大学科技与装备教研室教官。1992年&#xff0c;仲晶毕业于军事气象学院&#xff0c;1996年成为国防大学国防科技发展战略学硕士研究生&#xff0c;毕业后留校任教。曾出版过9部军事专著&#xff0c;先后发表学术论文100多万字。…

VUE element-ui实现表格动态展示、动态删减列、动态排序、动态搜索条件配置、表单组件化。

1、实现效果 1.1、文件目录 1.2、说明 1、本组件支持列表的表头自定义配置&#xff0c;checkbox实现 2、本组件支持列表列排序&#xff0c;vuedraggable是拖拽插件&#xff0c;上图中字段管理里的拖拽效果 &#xff0c;需要的话请自行npm install 3、本组件支持查询条件动态…