我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Python-opencv3 SIFT算

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Python-opencv3 SIFT算

最近接触一个项目:根据设计师定出的psd格式文件(photoshop),生成不同尺寸的海报。这里面牵扯到了尺度不变而对特征做变换的问题。这里简单介绍一下SIFT的概念,并知晓如何找到SIFT中的Keypoints和Descriptors,最后展示一个Demo。

一点推荐

作为CSDN的忠实用户,最近发现CSDN学院上了一些对新手比较友好的课程。以我的切身体会来看,对于想要了解机器学习算法或者python编程语言的同学,非常有帮助。还记得我最开始学习python的时候,看的是一本写给小孩子的书《趣学Python——教孩子学编程》。

虽然这本书不错,但是确实有些过于简单了,而CSDN提供的课程有两门对现在的我来讲还是有相当大的帮助,老师讲课水平高,配合丰富的例子,容易让人掌握知识点,下面推荐两门课程:

人工智能在网络领域的应用与实践:
https://edu.csdn.net/course/play/10319?utm_source=sooner

ps: 如果想要系统学习python的朋友,下面这门课是涵盖了python基础语法、web开发、数据挖掘以及机器学习,是CSDN强力推荐的课程,有需要的朋友可以看看哈:

Python全栈工程师:
https://edu.csdn.net/topic/python115?utm_source=sooner


简介

SIFT(Scale-invariant feature transform),也叫尺度不变特征变换算法,是David Lowe于1999年提出的局部特征描述子(Descriptor),并于2004年进行了更深入的发展和完善。Sift特征匹配算法可以处理两幅图像之间发生平移、旋转、仿射变换情况下的匹配问题,具有很强的匹配能力。在Mikolajczyk对包括Sift算子在内的十种局部描述子所做的不变性对比实验中,Sift及其扩展算法已被证实在同类描述子中具有最强的健壮性。

其应用范围包含物体辨识、机器人地图感知与导航、影像缝合、3D模型建立、手势辨识、影像追踪和动作比对。局部影像特征的描述与侦测可以帮助辨识物体,SIFT 特征是基于物体上的一些局部外观的兴趣点而与影像的大小和旋转无关。对于光线、噪声、些微视角改变的容忍度也相当高。基于这些特性,它们是高度显著而且相对容易撷取,在母数庞大的特征数据库中,很容易辨识物体而且鲜有误认。

SIFT算法特点与步骤

  • Sift特征是图像的局部特征 对平移、旋转、尺度缩放、亮度变化、遮挡和噪声等具有良好的不变性,对视觉变化、仿射变换也保持一定程度的稳定性。

  • 独特性好 信息量丰富,适用于在海量特征数据库中进行快速、准确的匹配。

  • 多量性 即使少数的几个物体也可以产生大量Sift特征向量。

  • 速度相对较快 经优化的Sift匹配算法甚至可以达到实时的要求。

  • 可扩展性强 可以很方便的与其他形式的特征向量进行联合。

SIFT算法的实质是:“不同的尺度空间上查找关键点(特征点),并计算出关键点的方向” ,SIFT所查找到的关键点是一些十分突出,不会因光照,仿射变换和噪音等因素而变化的点,如角点、边缘点、暗区的亮点及亮区的暗点等。

Lowe将SIFT算法分解为如下四步:

  • ① 尺度空间极值检测:搜索所有尺度上的图像位置。通过高斯微分函数来识别潜在的对于尺度和旋转不变的兴趣点。

    为了在不同的尺度空间检测关键点。这里,尺度空间的获取需要使用尺度空间滤波(scale-space filtering)来实现,Lindeberg等人已证明高斯卷积核是实现尺度变换的唯一变换核,并且是唯一的线性核。尺度规范化的LoG(Laplacion of Gaussian)算子具有真正的尺度不变性,但是由于LoG算法复杂度较高。因此,Lowe使用更为高效的高斯差分算子(Difference of Gaussians)近似LoG算子来进行极值检测,如下:
    D(x,y,σ)=(G(x,y,kσ)G(x,y,σ))I(x,y)=L(x,y,kσ)L(x,y,σ)D(x,y,\sigma) = (G(x,y,k\sigma) - G(x,y,\sigma) ) * I(x,y) = L(x,y,k\sigma) - L(x,y,\sigma)D(x,y,σ)=(G(x,y,kσ)−G(x,y,σ))∗I(x,y)=L(x,y,kσ)−L(x,y,σ)

    由上式可以看出,高斯差分算子(Difference of Gaussians)是使用两个不同的σ\sigmaσ,kσk\sigmakσ来做高斯模糊差异而得到的。这里,*∗表示卷积操作,G(x,y,σ)G(x,y,\sigma)G(x,y,σ)为一个变化尺度的高斯(Gaussian )函数,I(x,y)I(x,y)I(x,y)表示原图像。

    在实际计算时,使用高斯金字塔(Gaussian Pyramid)每组中相邻上下两层图像相减,得到高斯差分图像,如下图所示(关于高斯金字塔中的构建在内容延伸中会介绍):
    这里写图片描述

    G(x,y,σ)=12πσ2e(xm/2)2+(yn/2)22σ2G(x,y,\sigma) = \frac{1}{2\pi\sigma^2}e^-\frac{(x - m/2)^2 + (y - n/2)^2}{2\sigma^2}G(x,y,σ)=2πσ21​e−2σ2(x−m/2)2+(y−n/2)2​
    m,nm,nm,n表示高斯模板的维度(由(6σ+1)(6σ+1)(6\sigma +1)(6\sigma + 1)(6σ+1)(6σ+1)确定。x,yx, yx,y代表图像的像素位置。σ\sigmaσ是尺度空间因子,值越小表示图像被平滑的越少,相应的尺度也就越小。大尺度对应于图像的结构,小尺度对应于图像的细节纹理特征。

下面3张图转自博客:https://blog.csdn.net/zddblog/article/details/7521424

这里写图片描述

这里写图片描述

这里写图片描述

当我们得到DoG(Difference of Gaussian)之后,图像在尺度空间中搜寻局部极值(local extrema)。以下图为例,在图像中的某个像素点不但与其附近的8个像素点比较,而且与其前一层(previous scale)的9个像素点和下一层(next scale)的9个像素点进行比较(需为同一Octave)。如果该像素点是局部极值点,那么我们就认为它是一个潜在的KeyPoint(关键点)——最能代表这个scale的点

这里写图片描述

论文中给出了一些经验的值:octave(组)为4,scale layer(层)为5,σ=1.6\sigma=1.6σ=1.6,k=2k=\sqrt 2k=2​。

  • ② 关键点定位:在每个候选的位置上,通过一个拟合精细的模型来确定位置和尺度。关键点的选择依据于它们的稳定程度。
    由第①步检测得到的极值点是离散空间的极值点。下面,通过拟合三维二次函数来精确确定关键点的位置和尺度,同时去除低对比度的关键点不稳定的边缘响应点(因为DoG算子会产生较强的边缘响应),以增强匹配稳定性、提高抗噪声能力。
    他们使用泰勒级数展开式空间来获得更精确的极值位置,如果这个极值点的强度小于阈值,它就会被拒绝。这个阈值在Opencv中为contrastThreshold

因为DoG算子会产生较强的边缘响应,所以要去除这些不稳定的边缘响应点。与Harris角点检测的思路相似,获取特征点处的Hessian矩阵,主曲率(principal curvature)通过一个2x2 的Hessian矩阵HHH求出:
这里写图片描述
HHH的特征值ααα和βββ分别代表x和y方向的梯度,
这里写图片描述
这里,Tr(H)Tr(H)Tr(H)为主对角线元素之和,Det(H)Det(H)Det(H)表示矩阵H的行列式。假设是ααα较大的特征值,而βββ为较小的特征值,令α=rβα=rβα=rβ,则
这里写图片描述

DDD的主曲率和HHH的特征值成正比,跟上面一样,让ααα为最大特征值,βββ为最小特征值,则公式(r+1)2r\frac{(r+1)^2}{r}r(r+1)2​的值在两个特征值相等时最小,随着rrr的增大而增大。rrr值越大,说明两个特征值的比值越大,即在某一个方向的梯度值越大,而在另一个方向的梯度值越小,边缘恰恰就是一个方向梯度大,一个方向梯度小的情况。所以为了剔除边缘响应点,需要让该比值小于一定的阈值(论文给的rrr值为10):
这里写图片描述
将满足条件的关键点保留,否则则扔掉。因此,低对比度和边缘的关键点在本步骤中被去除,只保留最感兴趣的那些点。

下图左为边缘消除前的关键点分布图,右是消除后的,这里可以看出一些边缘角点被去除掉了。
这里写图片描述

  • ③ 方向确定:基于图像局部的梯度方向,分配给每个关键点位置一个或多个方向。所有后面的对图像数据的操作都相对于关键点的方向、尺度和位置进行变换,从而提供对于这些变换的不变性。

为了使描述符(Descriptors)具有旋转不变性,需要利用图像的局部特征为给每一个关键点分配一个基准方向。使用图像梯度的方法求取局部结构的稳定方向。对于在DoG中检测出的关键点,采集其所在高斯金字塔图像3σ3σ邻域窗口内像素的梯度和方向分布特征。梯度的模值和方向如下:
这里写图片描述
L为关键点所在的尺度空间值,按Lowe的建议,梯度的模值m(x,y)按的σ=1.5σoct\sigma = 1.5\sigma_{oct}σ=1.5σoct​高斯分布,按尺度采样的3σ3σ原则,邻域窗口半径为3×1.5σoct3\times1.5\sigma_{oct}3×1.5σoct​。
在完成关键点的梯度计算后,使用直方图统计邻域内像素的梯度和方向。梯度直方图将0~360度的方向范围分为36个柱(bins),其中每柱10度。如下图所示,直方图的峰值方向代表了关键点的主方向,(为简化,图中只画了八个方向的直方图)。

这里写图片描述
方向直方图的峰值则代表了该特征点处邻域梯度的方向,以直方图中最大值作为该关键(KeyPoint)的主方向。为了增强匹配的鲁棒性,只保留峰值大于主方向峰值80%的方向作为该关键点的辅方向。因此,对于同一梯度值的多个峰值的关键点位置,在相同位置和尺度将会有多个关键点被创建但方向不同。仅有15%的关键点被赋予多个方向,但可以明显的提高关键点匹配的稳定性。

实际编程实现中,就是把该关键点复制成多份关键点,并将方向值分别赋给这些复制后的关键点,并且,离散的梯度方向直方图要进行插值拟合处理,来求得更精确的方向角度值,检测结果如图所示。
这里写图片描述

至此,将检测出的含有位置、尺度和方向的关键点即是该图像的SIFT特征点。

  • ④ 关键点描述:在每个关键点周围的邻域内,在选定的尺度上测量图像局部的梯度。这些梯度被变换成一种表示,这种表示允许比较大的局部形状的变形和光照变化。

Demo

  • 基于python3.x + opencv3.x

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('psd_image_to_detect1.png', cv2.IMREAD_GRAYSCALE)
psd_img_2 = cv2.imread('psd_image_to_detect2.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.50*n.distance:
        goodMatch.append(m)
# 增加一个维度
goodMatch = np.expand_dims(goodMatch, 1)
print(goodMatch[:20])

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

这里写图片描述

如果把img_out中的参数goodMatch[:15]改为goodMatch,即展示所有匹配的特征,图为:

这里写图片描述

内容延伸

1 高斯金字塔的构建

SIFT算法特点与步骤的第一部分中,尺度空间在实现时使用高斯金字塔(Gaussian Pyramid)表示,这里介绍一下高斯金字塔的构造过程。高斯金字塔的构建分为两部分:

  • 对图像做不同尺度(不同σ\sigmaσ)的高斯模糊;
  • 对图像做降采样(隔点采样)。

这里写图片描述

图像的金字塔模型是指:“将原始图像不断降采样(Downsampling),得到一系列大小不一的图像,由大到小,从下到上构成的塔状模型。” ,原图像为金子塔的最底层(Octave 1),每次降采样所得到的新图像为金字塔的一层。金字塔的层数根据图像的原始大小和塔顶图像的大小共同决定,其计算公式如下:

这里写图片描述

其中M,NM,NM,N为原图像的大小,ttt为塔顶图像的最小维数的对数值。如,对于大小为512512的图像,金字塔上各层图像的大小如下表所示,当塔顶图像为44时,n=7,当塔顶图像为2*2时,n=8。
这里写图片描述

octave–组,Layer–层,scale–尺度。为了让尺度体现其连续性,高斯金字塔在简单降采样的基础上加上了高斯滤波。如上图所示,将图像金字塔每层的一张图像使用不同尺度(scale)做高斯模糊,使得金字塔的每层含有多张高斯模糊图像,将金字塔每层的多张图像合称为一组(Octave),金字塔每层只有一组图像,组数和金字塔层数相等。

注意:为了在每组中检测S个尺度的极值点,则DoG金字塔每组需S+2层图像,而DoG金字塔由高斯金字塔同组的相邻两层相减得到,则高斯金字塔每组需S+3层图像,实际计算时S在3到5之间。lowe推荐S取3。


  1. Introduction to SIFT (Scale-Invariant Feature Transform)
  2. Distinctive Image Features from Scale-Invariant Keypoints——David G. Lowe
  3. SIFT算法详解——zddhub

Python-opencv3 SIFT算

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Python-opencv3 SIFT算

最近接触一个项目:根据设计师定出的psd格式文件(photoshop),生成不同尺寸的海报。这里面牵扯到了尺度不变而对特征做变换的问题。这里简单介绍一下SIFT的概念,并知晓如何找到SIFT中的Keypoints和Descriptors,最
2023-01-31

Python opencv3安装

目录方法一:使用pip命令安装方法二:在pycharm安装Python opencv3安装及配置安装环境:win10 64;python3.6 64;pycharm2017;opencv3.4.3在运行(win+R打开)使用cmd命令进入d
2023-01-31

python opencv3机器学习之EM算法怎么使用

今天小编给大家分享一下python opencv3机器学习之EM算法怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。引
2023-07-02

Python中利用Scipy包的SIFT方法进行图片识别的实例教程

scipy scipy包包含致力于科学计算中常见问题的各个工具箱。它的不同子模块相应于不同的应用。像插值,积分,优化,图像处理,,特殊函数等等。 scipy可以与其它标准科学计算程序库进行比较,比如GSL(GNU C或C++科学计算库),或
2022-06-04

python 算法

算法的复杂度算法的时间复杂度是指算法需要消耗的时间资源时间复杂度用“O(数量级)”来表示常见的时间复杂度有:O(1)常数阶; 问题规模越大效率越高,时间不变, a = [1,2,3] a[0]=1,a增加无影响O(log2n)对数阶:
2023-01-31

Python 运算符

和大多数语言一样,Python也有很多运算符,并且运算符跟其他语言的运算符大同小异接下来一一介绍:算术运算符:运算符描述实例+加 - 两个对象相加a+b的输出结果是30-减 - 得到复数或者一个数减去另外一个数a-b的输出结果是10*乘 -
2023-01-31

[python]运算符 >>

都是移位操作,三个符号和两个符号的区别是:“>> 右移,高位补符号位” 这里右移一位表示除2“>>> 无符号右移,高位补0”; 与>>类似“<< 左移” 左移一位表示乘2,二位就表示4,就是2的n次方
2023-01-31

Python-运算符

笔记:运算中常见的几个函数:max():求最大值;min():求最小值;pow():幂函数;abs():计算绝对值;divmod(5,2) :表示5除以2,返回的元组中包含商和余数>>> divmod(5,2)(2, 1)round():四
2023-01-30

python的运算

三元运算result = 值1 if 条件 else 值2a=9b=5c = 8 if a < b else 99print(c)99a=8b=5c = 8 if a < b else 99print(c)8比较两个数输出最大的数a=
2023-01-31

【Python】python之π的计算

用IPO模式分析问题如下:1.输入:抛点的数量。2.处理:对于每个抛洒点,计算点到圆心的距 离,通过距离盘点该点在 圆内或圆外,统计在圆内点的数量。3.输出:π值代码如下from random import randomfrom m
2023-01-31

运算符Python

Python语言支持以下类型的运算符
运算符Python
2024-04-23

Python运算符

运算符:算法运算符:+-*/** %//加减乘除幂取余(返回除的余数)取整(返回商的整数部分) 比较运算费符:==><=><= !=等于大于小于大于等于小于等于不等于布尔值:True  真            False    假  (注
2023-01-30

python计算器

功能说明:使用python编写一个计算器,实现简单的加减乘除功能。程序的逻辑很简单,取出括号,计算里面的乘除加减,结果替换原括号内容,再循环直到最终结果。难点在于正则匹配字符和计算细节上,怎么很好协调配合并正确获得结果。逻辑图:程序目录:m
2023-01-31

Python中的/和//算术运算符

通常C/C++中,"/ " 算术运算符的计算结果是根据参与运算的两边的数据决定的,比如:  6 / 3 = 2 ; 6,3都是整数,那么结果也就是整数2;  6.0 / 3.0 = 2.0 ; 6.0,3.0是浮点数,那么结果也是浮点数2.
2023-01-31

python位运算符如何运算

Python中的位运算符包括:与运算(&)、或运算(|)、异或运算(^)、取反运算(~)、左移运算(>)。下面是每个位运算符的运算规则:1. 与运算(&):只有当两个对应的二进制位都为1时,结果才为1,否则为0。示例:5 & 3 = 15的
2023-10-11

Python学习-算术运算符,赋值运算符

算术运算符  常见的算术运算符有 :   +     加法运算符 print(1 + 2); // 3print('1' + '2'); //12  不仅可以进行2个数字的相加,还可以连接2个字符串 -     减法运算符print(4
2023-01-30

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录