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的pandas框架操作Excel文件中的数据教程
Mar 31 Python
利用python模拟实现POST请求提交图片的方法
Jul 25 Python
详解pandas数据合并与重塑(pd.concat篇)
Jul 09 Python
flask框架单元测试原理与用法实例分析
Jul 23 Python
python使用celery实现异步任务执行的例子
Aug 28 Python
python对Excel的读取的示例代码
Feb 14 Python
python模拟点击网页按钮实现方法
Feb 25 Python
Django添加bootstrap框架时无法加载静态文件的解决方式
Mar 27 Python
keras 两种训练模型方式详解fit和fit_generator(节省内存)
Jul 03 Python
详解Python3.8+PyQt5+pyqt5-tools+Pycharm配置详细教程
Nov 02 Python
python批量合成bilibili的m4s缓存文件为MP4格式 ver2.5
Dec 01 Python
python疲劳驾驶困倦低头检测功能的实现
Apr 04 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环境套包 dedeampz 伪静态设置示例
2014/03/26 PHP
php中switch语句用法详解
2015/08/17 PHP
php如何执行非缓冲查询API
2016/07/22 PHP
JavaScript中void(0)的具体含义解释
2007/02/27 Javascript
javascript 选择文件夹对话框(web)
2009/07/07 Javascript
jquery 得到当前页面高度和宽度的两个函数
2010/02/21 Javascript
JQuery Ajax通过Handler访问外部XML数据的代码
2010/06/01 Javascript
分享20多个很棒的jQuery 文件上传插件或教程
2011/09/04 Javascript
JS事件在IE与FF中的区别详细解析
2013/11/20 Javascript
jQuery操作表单常用控件方法小结
2015/03/23 Javascript
javascript cookie基础应用之记录用户名的方法
2016/09/20 Javascript
JavaScript中全选、全不选、反选、无刷新删除、批量删除、即点即改入库(在yii框架中操作)的代码分享
2016/11/01 Javascript
bootstrap weebox 支持ajax的模态弹出框
2017/02/23 Javascript
基于React实现表单数据的添加和删除详解
2017/03/14 Javascript
JavaScript数据结构之二叉树的删除算法示例
2017/04/13 Javascript
微信小程序实现给循环列表添加点击样式实例
2017/04/26 Javascript
JS实现DOM节点插入操作之子节点与兄弟节点插入操作示例
2018/07/30 Javascript
Vue.js 使用v-cloak后仍显示变量的解决方法
2018/11/19 Javascript
elementUI 动态生成几行几列的方法示例
2019/07/11 Javascript
vuex根据不同的用户权限展示不同的路由列表功能
2019/09/20 Javascript
javaScript代码飘红报错看不懂?读完这篇文章再试试
2020/08/19 Javascript
python使用Berkeley DB数据库实例
2014/09/26 Python
Python基于回溯法子集树模板实现图的遍历功能示例
2017/09/05 Python
django之跨表查询及添加记录的示例代码
2018/10/16 Python
Python 运行.py文件和交互式运行代码的区别详解
2019/07/02 Python
Python+Selenium+phantomjs实现网页模拟登录和截图功能(windows环境)
2019/12/11 Python
Pytorch Tensor的统计属性实例讲解
2019/12/30 Python
python re的findall和finditer的区别详解
2020/11/15 Python
Python实现Appium端口检测与释放的实现
2020/12/31 Python
利用CSS3的checked伪类实现OL的隐藏显示的方法
2010/12/18 HTML / CSS
大一军训感言
2014/01/09 职场文书
党员创先争优心得体会
2014/09/11 职场文书
长江三峡导游词
2015/01/31 职场文书
上班迟到检讨书范文
2015/05/06 职场文书
考教师资格证不要错过的4个最佳时机
2019/07/17 职场文书
vue+springboot实现登录验证码
2021/05/27 Vue.js