python opencv之SIFT算法示例


Posted in Python onFebruary 24, 2018

本文介绍了python opencv之SIFT算法示例,分享给大家,具体如下:

目标:

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

原理:

(原理部分自己找了不少文章,内容中有不少自己理解和整理的东西,为了方便快速理解内容和能够快速理解原理,本文尽量不使用数学公式,仅仅使用文字来描述。本文中有很多引用别人文章的内容,仅供个人记录使用,若有错误,请指正出来,万分感谢)

之前的harris算法和Shi-Tomasi 算法,由于算法原理所致,具有旋转不变性,在目标图片发生旋转时依然能够获得相同的角点。但是如果对图像进行缩放以后,再使用之前的算法就会检测不出来,原理用一张图表示(图1):

python opencv之SIFT算法示例

(harris算法和shi-tomasi算法都是基于窗口中像素分布和变化的原理,在图像放大且窗口大小不发生变化的时,窗口中的像素信息则会有很大的不同,造成无法检测的结果)

SIFT特性:

  1. 独特性,也就是特征点可分辨性高,类似指纹,适合在海量数据中匹配。
  2. 多量性,提供的特征多。
  3. 高速性,就是速度快。
  4. 可扩展,能与其他特征向量联合使用。

SIFT特点:

  1. 旋转、缩放、平移不变性
  2. 解决图像仿射变换,投影变换的关键的匹配
  3. 光照影响小
  4. 目标遮挡影响小
  5. 噪声景物影响小

SIFT算法步骤:

  1. 尺度空间极值检测
  2. 关键点定位
  3. 关键点方向参数
  4. 关键点描述符
  5. 关键点匹配

尺度空间极值检测:

尺度空间的个人理解:
你找一张分辨率1024×1024图片,在电脑上观看,十分清晰,但是图片太大。现在把这图片反正photoshop上,将分辨率改成512×512,图片看着依然很清晰,但是不可能像1024×1024的画面那么精细,只不过是因为人眼构造的原因,512×512图片依然能让你分辨出这是个什么东西。

粗俗点说,尺度空间,就相当于一个图片需要获得多少分辨率的量级。如果把一个图片从原始分辨率到,不停的对其分辨率进行减少,然后将这些图片摞在一起,可以看成一个四棱锥的样式,这个东西就叫做图像金字塔(如下图,图2)。

python opencv之SIFT算法示例

再回到尺度空间,在摄像头中,计算机无法分辨一个景物的尺度信息。而人眼不同,除了人大脑里已经对物体有了基本的概念(例如正常人在十几米外看到苹果,和在近距离看到苹果,都能认出是苹果)以外,人眼在距离物体近时,能够获得物体足够多的特性,在距离物体远时,能够或略细节,例如,近距离看一个人脸能看到毛孔,距离远了看不到毛孔等等。

在图片信息当中,分辨率都是固定的,要想得到类似人眼的效果,就要把图片弄成不同的分辨率,制作成图像金字塔来模拟人眼的功能,从而在其他图片中进行特征识别时,能够像人眼睛一样,即使要识别的物体尺寸变大或者变小,也能够识别出来!

从图1可以看出,如果如果图像变大,窗口大小还是以前的大小,则无法正确检测出角点。那么很自然的就能想到,如果图片变大,咱们把窗口也放大不就行了? 这就需要上面提到的尺度空间发挥作用。

在SIFT当中,利用了一个叫做高斯核的方程来构建尺度空间,原因是高斯核函数是唯一多尺度空间的核。听起来比较晦涩,个人理解为:

高斯核函数在之前的高斯滤波当中使用过,其原理就是利用高斯分布的特性,在以某一个点为中心要进行以某一个窗口大小进行模糊的操作。那么,根据滤波的原理,距离中心像素点位置的距离越远的像素点,需要“模糊化效果”的值就应该越少。那么这个距离值的分配方法,就是利用满足高斯核函数的分配方法,由中心,到四周,符合高斯核函数的“钟型”曲线(从二维上看)。

那么尺度空间中的高斯核也可以这么理解,高斯核函数的参数有三个G(x,y,σ) ,在滤波当中,第三个参数σ在运算中是固定的一个值。而在尺度空间的构造当中,所谓的“尺度”,就是这个σ值变化,而x和y表示像素坐标。σ的值越小,图像被平滑(被模糊)的越少,尺度也越小。所以,大尺度图片可以对应成一个图像离远处观看,是个大致轮廓,小尺度图片可以对应成离近处观看,有更多细节。

构建尺度空间的目的是为了检测出在不同的尺度下都存在的特征点,如此可以获得缩放不变性

其中利用图像I(x,y)G(x,y,σ) 进行卷积运算,得到尺度空间L(x,y,σ),可以理解,所谓的“尺度空间”在这里就是这个函数L(x,y,σ)

如果求取特征点,可以使用一个叫做拉普拉斯算子进行运算

但是,由于拉普拉斯算子的效率太低,再SIFT算法当中使用差分来代替。

高斯金字塔:

在建立尺度空间后,需要找到关键点,此时需要实现高斯金字塔的构造来实现关键点的求取。在高斯金字塔当中,“塔”的每一层都是图像,“塔”的高度就是上面提到的尺度σ。“塔”的每一层对应一个σ值,同时将高斯金字塔中的图像分成组,每组当中图像的尺寸相同,但是尺度σ不同。具体尺度之间的计算关系,先忽略,如下图所示:

python opencv之SIFT算法示例

高斯差分金字塔DOG:

每一组相邻当中相邻两层的图像做差,得到的图像再“叠”成一个金字塔就是高斯差分金字塔DOG。

DOG局部特征点检测:

有了差分金字塔,现在便可以计算关键点(特征点)。由于金字塔的模型不是二维模型,而是一个三维模型,这里计算极值的方法也不再是二维求取极值的方法。

计算一个某一个点是否是局部最大值,在离散的三维空间当中,以该点为中心,检测它周围的点。类似魔方的中心位置一样,如下图中的“叉”就是待计算是否是局部极值点。

python opencv之SIFT算法示例

这里说明,局部极值点都是在同一个组当中进行的,所以肯定有这样的问题,某一组当中的第一个图和最后一个图层没有前一张图和下一张图,那该怎么计算? 解决办法是,在用高斯模糊,在高斯金字塔多“模糊”出三张来凑数,所以在DOG中多出两张。

关键点定位:

上面找到的关键点要进行处理,去除一些不好的特征点,保存下来的特征点能够满足稳定性等条件。

主要是去掉DOG局部曲率非常不对称的像素。

因为低对比度的特征点和边界点对光照和噪声变化非常敏感,所以要去掉。利用阈值的方法来限制,在opencv中为contrastThreshold。

去除低对比度的特征点:

使用泰勒公式对DOG函数空间进行拟合,去掉小于修正阈值的关键点。

去除不稳定的边界点:

利用Hessian矩阵(就是求导数的矩阵),利用边缘梯度的方向上主曲率值比较大,而沿着边缘方向则主曲率值较小的原理,将主曲率限制为某个值。满足该值条件的点留下,反之去除。

关键点设定方向参数:

每个关键点设置方向以后可以获得旋转不变性。

获取关键点所在尺度空间的邻域,然后计算该区域的梯度和方向,根据计算得到的结果创建方向直方图,直方图的峰值为主方向的参数,其他高于主方向百分之80的方向被判定为辅助方向,这样设定对稳定性有很大帮助。如图

python opencv之SIFT算法示例

关键点描述符:

经过上面的步骤计算,每个关键点有三个信息,位置、尺度、方向。所以具备平移、缩放、和旋转不变性。

接下来对每个关键点用一组向量将这个关键点描述出来,使其不随着光照、视角等等影响而改变。该描述符不但涉及关键点,而且还涉及到关键点周围的像素,使其有更强的不变特性。

基本原理是选取关键点周围16×16的像素区域,分成4个小块,每个小块创建8个bin的直方图,这总共的128个信息的向量就是关键点描述符的主要内容。此外还要测量,以达到光照、旋转的稳定性。如图

python opencv之SIFT算法示例

关键点匹配:

分别对模板图和实时图建立关键点描述符集合,通过对比关键点描述符来判断两个关键点是否相同。128个信息的向量使用欧氏距离来实现。

在关键点的匹配当中,使用的搜索算法为区域搜索算法当中最常用的k-d树实现。

比较之后,需要在进行消除错配点才算完成。

OpenCV 中的 SIFT:

关于opencv版本与SIFT算法不能调用的问题:

SIFT算法是一个有专利的算法,在商业用途上是收费的。对于穷B学生,算法的发明者还比较仁慈,可以使用。
不过,在python当中使用SIFT算法和版本之间有不少关系,源文档当中使用opencv版本是2.4.9版本,此版本可以随意使用SIFT算法。

但是,在opencv3当中就没那么幸运了,opencv中的很多特征点提取算法都和cv2中的库分离开,必须要添加opencv-contrib才可以使用,本人使用的opencv版本是3.3.0,几乎是最新的版本。

网上有一大堆教程关于如何在opencv当中如何添加opencv-contrib的教程,使用cmake,使用vs,啥的非常麻烦。

本人狗急跳墙,寻思在pip上面有没有啥第三方的库可以直接就将opencv-contrib这个库。

结果,还真找到了 哈哈。

这下方便了,只要在你的控制台当中输入
pip install opencv-contrib-python即可

如果pip安装不上去

直接上官方上面下个轮子,然后pip安装就能用了

网站在此!!!

import cv2
import numpy as np


img = cv2.imread('1.jpg')
gray= cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
sift = cv2.xfeatures2d.SIFT_create()


kp = sift.detect(gray,None)#找到关键点

img=cv2.drawKeypoints(gray,kp,img)#绘制关键点

cv2.imshow('sp',img)
cv2.waitKey(0)

返回的关键点是一个带有很多不用属性的特殊结构体,属性当中有坐标,方向、角度等等。

计算关键点描述符:

使用sift.compute()函数来进行计算关键点描述符

kp,des = sift.compute(gray,kp)

如果未找到关键点,可使用函数sift.detectAndCompute()直接找到关键点并计算。

在第二个函数中,kp为关键点列表,des为numpy的数组,为关键点数目×128

sift = cv2.xfeatures2d.SIFT_create()

kp, des = sift.detectAndCompute(gray,None)

结果如图

python opencv之SIFT算法示例

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python 检查数组元素是否存在类似PHP isset()方法
Oct 14 Python
Python实现压缩与解压gzip大文件的方法
Sep 18 Python
python编程之requests在网络请求中添加cookies参数方法详解
Oct 25 Python
用python生成(动态彩色)二维码的方法(使用myqr库实现)
Jun 24 Python
使用django实现一个代码发布系统
Jul 18 Python
使用Pyinstaller转换.py文件为.exe可执行程序过程详解
Aug 06 Python
python 计算积分图和haar特征的实例代码
Nov 20 Python
pygame库实现移动底座弹球小游戏
Apr 14 Python
Python爬虫爬取煎蛋网图片代码实例
Dec 16 Python
Django日志及中间件模块应用案例
Sep 10 Python
python全栈开发语法总结
Nov 22 Python
端午节将至,用Python爬取粽子数据并可视化,看看网友喜欢哪种粽子吧!
Jun 11 Python
python3 破解 geetest(极验)的滑块验证码功能
Feb 24 #Python
python opencv之SURF算法示例
Feb 24 #Python
几种实用的pythonic语法实例代码
Feb 24 #Python
使用Python爬取最好大学网大学排名
Feb 24 #Python
python opencv 直方图反向投影的方法
Feb 24 #Python
python爬虫爬取淘宝商品信息
Feb 23 #Python
python爬取淘宝商品详情页数据
Feb 23 #Python
You might like
PHP防止跨域提交表单
2013/11/01 PHP
PHP Curl出现403错误的解决办法
2014/05/29 PHP
PHP后端银联支付及退款实例代码
2017/06/23 PHP
php之header的不同用法总结(实例讲解)
2017/11/28 PHP
laravel 5.4 + vue + vux + element的环境搭配过程介绍
2018/04/26 PHP
php5对象复制、clone、浅复制与深复制实例详解
2019/08/14 PHP
JQuery 拾色器插件发布-jquery.icolor.js
2010/10/20 Javascript
jquery ajax 同步异步的执行 return值不能取得的解决方案
2012/01/08 Javascript
jquery数据验证插件(自制,简单,练手)实例代码
2013/10/24 Javascript
jQuery获得内容和属性示例代码
2014/01/16 Javascript
Javascript的&&和||的另类用法
2014/07/23 Javascript
js实现图片上传并正常显示
2015/12/19 Javascript
vue.js事件处理器是什么
2017/03/20 Javascript
JS排序之选择排序详解
2017/04/08 Javascript
深入理解与使用keep-alive(配合router-view缓存整个路由页面)
2018/09/25 Javascript
关于Vue Router中路由守卫的应用及在全局导航守卫中检查元字段的方法
2018/12/09 Javascript
基于Vue 实现一个中规中矩loading组件
2019/04/03 Javascript
基于jquery实现的tab选项卡功能示例【附源码下载】
2019/06/10 jQuery
[59:48]LGD vs IG 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
python中mechanize库的简单使用示例
2014/01/10 Python
利用Python+阿里云实现DDNS动态域名解析的方法
2019/04/01 Python
python tkinter组件摆放方式详解
2019/09/16 Python
用python实现英文字母和相应序数转换的方法
2019/09/18 Python
tensorflow通过模型文件,使用tensorboard查看其模型图Graph方式
2020/01/23 Python
利用 Python ElementTree 生成 xml的实例
2020/03/06 Python
jupyter 添加不同内核的操作
2021/02/06 Python
基于canvas使用贝塞尔曲线平滑拟合折线段的方法
2018/01/10 HTML / CSS
香港唯港荟酒店预订:Hotel ICON
2018/03/27 全球购物
C++的几个面试题附答案
2016/08/03 面试题
教师求职推荐信范文
2013/11/20 职场文书
美术教师个人总结
2015/02/06 职场文书
学校三八妇女节活动总结
2015/02/06 职场文书
教师党员个人总结
2015/02/10 职场文书
nginx 多个location转发任意请求或访问静态资源文件的实现
2021/03/31 Servers
使用PostGIS完成两点间的河流轨迹及流经长度的计算(推荐)
2022/01/18 PostgreSQL
Nginx的基本概念和原理
2022/03/21 Servers