python opencv之SURF算法示例


Posted in Python onFebruary 24, 2018

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

目标:

  1. SURF算法基础
  2. opencv总SURF算法的使用

原理:

上节课使用了SIFT算法,当时这种算法效率不高,需要更快速的算法。在06年有人提出了SURF算法“加速稳定特征”,从名字上来看,他是SIFT算法的加速版本。

(原文)
在SIFT算法当中使用高斯差分方程(Difference of Gaussian)对高斯拉普拉斯方程( Laplacian of Gaussian)进行近似。然而,SURF使用盒子滤波器进行近似,下面的图片显示了这种近似的方法。在进行卷积计算的时候可以利用积分图像,这是使用盒子形滤波器的一个优点,即计算某个窗口中的像素和的时候,计算量大小,也就是时间复杂度不受到窗口大小的影响。而且,这种运算可以在不用的尺度空间当中实现。

SURF算法计算关键点的尺度和位置信息使用Hessian矩阵实现。

(解释)
文中的高斯拉普拉斯方程(算子)是检测图像中斑点的一种十分常用的方法。以一维高斯函数来检测一维信号中的斑点为例。有一维信号f,高斯函数的一阶导数ddxg" role="presentation">,信号与高斯函数的一阶导数卷积后,会在边缘处出现极值。如图:

python opencv之SURF算法示例 

上面图片是在一维情况下,使用高斯函数的一阶导数的情况,另一种方法是使用高斯函数的二阶导数与信号进行卷积,高斯函数的二阶导数也叫做拉普拉斯变换。

但是,在一维信号斑点检测的实际情况当中,一个斑点可以考虑成是两个相邻的跳突组成,如下图。

python opencv之SURF算法示例 

类似于在图像当中,一个轮胎可以当成一个斑点,一个苍蝇也可以当成一个斑点。但是在使用高斯函数的二阶导数来检测斑点的时候,使用不同的高斯核(就是方差)运算不同大小的斑点时,计算出来的极值,即响应值会出现衰减。

此时,需要将高斯函数的二阶导数进行正规化,去除方差值不同导致响应值出现的衰减。

以上,是一维高斯函数检测一维信号的原理。二维的图像信号,使用二维高斯函数来检测斑点原理基本相同,此处的二维高斯函数的二阶导数,就叫做高斯拉普拉斯算子也就是LOG,通过改变不同的方差值,可以检测不同尺寸的二维斑点,如图。

python opencv之SURF算法示例

文中的高斯差分方程是SIFT算法当中,发明者想要利用两个相邻高斯尺度空间的图像相减来得到一个LOG的近似,因为这样做可以节省时间,而且可以控制精度变化,类似于高等数学当中泰勒公式那玩意-_- 。关于SIFT原理可以看上一篇博客

文中提到的积分图像实际上原理非常简单,类似递推方程。积分图像的目的是想建立一个函数,能够快速得到一个矩形图像区域当中所有像素值的和是多少。那么,设p(i,j)" role="presentation">表示从(0,0)" role="presentation">点到(i,j)" role="presentation">点的所有像素的和是多少,存储在p(i,j)" role="presentation">这个数组里面,如果想要获得W区域的像素和是多少,如图,只要计算p(i4,j4)p(i2,j2)p(i3,j3)+p(i1,j1)" role="presentation">即可。

python opencv之SURF算法示例 

如何求得p(i,j)" role="presentation">? 递推公式为,p(i,j)=p(i1,j)+p(i,j1)+I(i,j)p(i1,j1)" role="presentation">,这里面I(i,j)" role="presentation">表示像素点(i,j)" role="presentation">处的像素值。

文中提到的Hessian矩阵,学过数学分析、最优化、机器学习之类的人肯定对这玩意非常熟悉,实际上黑塞矩阵就是一个多元函数的二阶偏导数构成的方阵,它的行列式值(Determinant of Hessian )可以反映的局部结构信息,简称DOH。与LOG类似,DOH可以使用不同方差生成高斯函数对各个元的二阶偏导模板,以此来对图像进行卷积运算。 同样,DOH也会在卷积后的函数中,得到对图像信号斑点极值的响应。如图

python opencv之SURF算法示例

在SURF算法当中,黑塞矩阵中的L,即为二维高斯函数与图像的卷积,求得黑塞矩阵后,会得到如图。

python opencv之SURF算法示例

将上面得到的模板与图像的卷积转换为盒子滤波器,这里使用原文中的图像,如图。

python opencv之SURF算法示例

得到三个不同的盒子滤波器以后,对其进行近似和简化操作,并用其表示图像中某点的斑点响应值,遍历图像当中的所有像素,就得到了在某一尺度下斑点检测的响应图像。然后,利用不同的模板尺寸,获取多尺度斑点响应金字塔,在金字塔中搜索极值点,下面的操作就和SIFT算法类似了。

(原文)
为了给找到的特征点赋予方向,以特征点为中心,6s为半径获取水平和垂直小波响应运算结果,这里s是特征点尺度,同时使用高斯加权的方法。然后,他们会被绘制在如下图当中。其中,特征点的主方向估计运算是有一个弧度为60的扇形窗口,在滑动的过程中不断计算其中的响应值之和。有趣的是,小波响应值在任意尺度下使用积分图像很容易被获取。但是在多数情况下,旋转不变性不是必须的,可以代码当中将这一步取消,这样还能够提高算法计算速度,而且在+-15度的情况也保持稳定,此时该方法称作 U-SURF。用户可以设置upright参数,当参数为0计算方向,参数为1不计算方向。

python opencv之SURF算法示例

对于特征点描述的建立,SURF再一次使用Haar小波响应,同时使用积分图像使操作变得简单。在一个矩形区域当中,以特征点为中心,划取周围20s×20s区域的大小,以特征点为原点,主方向为横轴,分成四个子区域,每个子区域使用2s的Haar小波响应,对于每个子区域,获取一个向量,记录垂直、水平方向上的小波响应值,如图。

python opencv之SURF算法示例 

这个特征描述符的长度使64,降低维度可以加速计算,又可以区分特征。为了更好的区分特征点,SURF还使用了长度为128特征描述符。当dy小于0或者大于0时,计算dx或|dx|的和。同样,根据dx的符号计算不同的dy和。因此能够获得双倍的特征。计算复杂度也不会增加。opencv当中的extended参数为0或1时分别对应64和128的特征。

另外一个重要的改善是对潜在的兴趣点使用了拉普拉斯算子符号(黑塞矩阵的迹)。由于之前的计算已经完成对黑塞矩阵的构造,所以这步不会增加复杂度。

拉普拉斯符号在不同明暗背景下区分不同亮度的斑点,在匹配阶段,我们只需要比较拥有相同对比度的特征是否匹配即可,这样加快了计算速度,如图。

python opencv之SURF算法示例 

SURF算法的速度是SIFT速度的3倍,善于处理模糊和旋转的图像,但是不善于处理视角变化和关照变化。

(解释)
文中的小波响应运算,全称是haar小波运算。这里使用haar小波目的是为了获取图像梯度,使用之前计算好的图像积分结果,这样能够提高计算速度。与SIFT算法类似,在对每个特征点获取主方向时,使用原文中提到的一个π/3大小的扇形窗口,同时以0.2弧度为步长旋转滑动此窗口,在每个窗口当中对的haar响应值的水平方向,垂直方向进行累加。由于时使用一个圆形区域,转换成类似极坐标矢量的方式来表示,每个窗口中的结果(mw,θw)" role="presentation">,如图。

python opencv之SURF算法示例

主方向最大Haar响应值累加对应的方向。其中,如果除了主方向,还有其它方向的响应累加值较大,算法当中还会额外添加一个特征点,并赋予另外一个次大方向。

文中建立的特征描述符顾名思义,就是描述一个特征点的一组向量,里面唯一确定了一个特征。SURF获取主方向后,需要获取特征点描述子。以特征点为原点,主方向为横轴建立一个二维坐标系,区域大小是20s×20s,分成是个之块,每个子块利用2s的haar模板进行响应计算。然后统计ΣdxΣ|dx|ΣdyΣ|dy|" role="presentation">,每个20s的窗口分成4×4的子窗口,每个子窗口中又5s×5s个像元。如图

python opencv之SURF算法示例 

又4×4个子块,每个子块里面记录四个值,所以描述子一共又4×4×4=64个特征。

最后将沿着主方向的小波响应值扭转过来,原理就是简单的旋转矩阵。

代码部分

opencv里面提供的SURF算法和SIFT差不多,这两个玩意都是受到版权保护的,如果你是用pip 一条命令安装的opencv,那么恭喜你用不了SURF和SIFT算法,印象中只有2.4.9版本的opencv库才可以使用。

不过,办法还是有的,再控制台当中输入pip install opencv-contrib-python 就可以用了。

如果还是无法安装,可以直接网站早opencv-contrib-python的轮子,然后放到对应的文件下安装就行了。

我的版本是opencv 3.2,和教程文档中的使用方法不同。

详细参数可以自己去查一查,一查一个准的

https://docs.opencv.org/master/d5/df7/classcv_1_1xfeatures2d_1_1SURF.html

import cv2 
import numpy as np 

img = cv2.imread('feng.jpg')

#参数为hessian矩阵的阈值
surf = cv2.xfeatures2d.SURF_create(400)
#找到关键点和描述符
key_query,desc_query = surf.detectAndCompute(img,None)
#把特征点标记到图片上
img=cv2.drawKeypoints(img,key_query,img)

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

python opencv之SURF算法示例

凤的嘴上特征点占了这么多,辨识度还是蛮高的~ -_-|||

下面是设置方向,和输出一些值的方法

import cv2 
import numpy as np 

img = cv2.imread('feng.jpg')

#参数为hessian矩阵的阈值
surf = cv2.xfeatures2d.SURF_create(4000)

#设置是否要检测方向
surf.setUpright(True)

#输出设置值
print(surf.getUpright())

#找到关键点和描述符
key_query,desc_query = surf.detectAndCompute(img,None)

img=cv2.drawKeypoints(img,key_query,img)

#输出描述符的个数
print(surf.descriptorSize())


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

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

Python 相关文章推荐
Python sqlite3事务处理方法实例分析
Jun 19 Python
Django中针对基于类的视图添加csrf_exempt实例代码
Feb 11 Python
python实现关键词提取的示例讲解
Apr 28 Python
numpy中的delete删除数组整行和整列的实例
May 09 Python
PyCharm代码提示忽略大小写设置方法
Oct 28 Python
python 实现数字字符串左侧补零的方法
Dec 04 Python
Python Pexpect库的简单使用方法
Jan 29 Python
python获取微信企业号打卡数据并生成windows计划任务
Apr 30 Python
实例详解Python模块decimal
Jun 26 Python
django自带serializers序列化返回指定字段的方法
Aug 21 Python
浅析Python 字符编码与文件处理
Sep 24 Python
Python类的继承super相关原理解析
Oct 22 Python
几种实用的pythonic语法实例代码
Feb 24 #Python
使用Python爬取最好大学网大学排名
Feb 24 #Python
python opencv 直方图反向投影的方法
Feb 24 #Python
python爬虫爬取淘宝商品信息
Feb 23 #Python
python爬取淘宝商品详情页数据
Feb 23 #Python
Python如何抓取天猫商品详细信息及交易记录
Feb 23 #Python
python列表生成式与列表生成器的使用
Feb 23 #Python
You might like
php中判断一个字符串包含另一个字符串的方法
2007/03/19 PHP
PHP自带函数给数字或字符串自动补齐位数
2014/07/29 PHP
PHP开发注意事项总结
2015/02/04 PHP
PHP中如何使用Redis接管文件存储Session详解
2018/11/28 PHP
用javascript获取当页面上鼠标光标位置和触发事件的对象的代码
2009/12/09 Javascript
jQuery News Ticker 基于jQuery的即时新闻行情展示插件
2011/11/05 Javascript
js opener的使用详解
2014/01/11 Javascript
jquery动态更换设置背景图的方法
2014/03/25 Javascript
从零学JSON之JSON数据结构
2014/05/19 Javascript
js实现jquery的offset()方法实例
2015/01/10 Javascript
JS判断客服QQ号在线还是离线状态的方法
2015/01/13 Javascript
JavaScript函数的一些注意要点小结及js匿名函数
2015/11/10 Javascript
js实现模拟银行卡账号输入显示效果
2015/11/18 Javascript
jQuery实现右下角可缩放大小的层完整实例
2016/06/20 Javascript
Bootstrap编写一个兼容主流浏览器的受众门户式风格页面
2016/07/01 Javascript
ES6中Proxy与Reflect实现重载(overload)的方法
2017/03/30 Javascript
Angular5中状态管理的实现
2018/09/03 Javascript
vue删除html内容的标签样式实例
2018/09/13 Javascript
vue基于两个计算属性实现选中和全选功能示例
2019/02/08 Javascript
Vue.set 全局操作简单示例
2019/09/19 Javascript
vue轮播组件实现$children和$parent 附带好用的gif录制工具
2019/09/26 Javascript
[57:12]完美世界DOTA2联赛循环赛 Inki vs Matador BO2第一场 10.31
2020/11/02 DOTA
python爬虫实现教程转换成 PDF 电子书
2017/02/19 Python
Python使用pickle模块存储数据报错解决示例代码
2018/01/26 Python
Selenium chrome配置代理Python版的方法
2018/11/29 Python
pandas实现DataFrame显示最大行列,不省略显示实例
2019/12/26 Python
TensorFlow tf.nn.conv2d_transpose是怎样实现反卷积的
2020/04/20 Python
俄罗斯电动工具和设备购物网站:Vseinstrumenti.ru
2020/11/12 全球购物
RealTek面试题
2016/06/28 面试题
小学生秋游活动方案
2014/02/23 职场文书
民主生活会对照检查材料
2014/09/22 职场文书
十八大标语口号
2014/10/09 职场文书
公司离职证明标准格式
2014/11/18 职场文书
2015年健康教育工作总结
2015/04/10 职场文书
表扬信格式模板
2015/05/05 职场文书
Java实现添加条码或二维码到Word文档
2022/06/01 Java/Android