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 相关文章推荐
Mac OS X10.9安装的Python2.7升级Python3.3步骤详解
Dec 04 Python
使用py2exe在Windows下将Python程序转为exe文件
Mar 04 Python
python的paramiko模块实现远程控制和传输示例
Oct 13 Python
Python输出各行命令详解
Feb 01 Python
python3使用flask编写注册post接口的方法
Dec 28 Python
谈一谈基于python的面向对象编程基础
May 21 Python
Python多版本开发环境管理工具介绍
Jul 03 Python
在python中画正态分布图像的实例
Jul 08 Python
Pytorch Tensor 输出为txt和mat格式方式
Jan 03 Python
python无序链表删除重复项的方法
Jan 17 Python
Python替换NumPy数组中大于某个值的所有元素实例
Jun 08 Python
python引入其他文件夹下的py文件具体方法
May 23 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分页函数示例代码分享
2014/02/24 PHP
解读PHP中上传文件的处理问题
2016/05/29 PHP
PHP5.6读写excel表格文件操作示例
2019/02/26 PHP
Js切换功能的简单方法
2010/11/23 Javascript
DIV外区域Click后关闭DIV的实现代码
2011/12/21 Javascript
jquery 判断滚动条到达了底部和顶端的方法
2014/04/02 Javascript
javascript解析json数据的3种方式
2014/05/08 Javascript
js加密解密字符串可自定义密码因子
2014/05/13 Javascript
js Object2String方便查看js对象内容
2014/11/24 Javascript
javascript最基本的函数汇总
2015/06/25 Javascript
jQuery实现的网页右下角tab样式在线客服效果代码
2015/10/23 Javascript
JS如何判断是否为ie浏览器的方法(包括IE10、IE11在内)
2015/12/13 Javascript
javascript日期验证之输入日期大于等于当前日期
2015/12/13 Javascript
Vue.js表单控件实践
2016/10/27 Javascript
jQuery的ajax中使用FormData实现页面无刷新上传功能
2017/01/16 Javascript
关于React动态加载路由处理的相关问题
2019/01/07 Javascript
深入理解es6块级作用域的使用
2019/03/28 Javascript
Vue中Table组件行内右键菜单实现方法(基于 vue + AntDesign)
2019/11/21 Javascript
js实现有趣的倒计时效果
2021/01/19 Javascript
[02:23]完美世界全国高校联赛街访DOTA2第一期
2019/11/28 DOTA
Python实现字典去除重复的方法示例
2017/07/31 Python
Python hashlib模块用法实例分析
2018/06/12 Python
Python实现端口检测的方法
2018/07/24 Python
Python实现堡垒机模式下远程命令执行操作示例
2019/05/09 Python
Python爬虫实现“盗取”微信好友信息的方法分析
2019/09/16 Python
Win下PyInstaller 安装和使用教程
2019/12/25 Python
python3光学字符识别模块tesserocr与pytesseract的使用详解
2020/02/26 Python
详解Python中的Lock和Rlock
2021/01/26 Python
欧舒丹加拿大官网:L’Occitane加拿大
2017/10/29 全球购物
工厂会计员职责
2014/02/06 职场文书
旅游管理专业大学生职业规划书
2014/02/27 职场文书
交警个人先进事迹材料
2014/05/11 职场文书
医生个人年度总结
2015/02/28 职场文书
Python 内置函数速查表一览
2021/06/02 Python
SpringBoot 拦截器妙用你真的了解吗
2021/07/01 Java/Android
CSS 实现磨砂玻璃(毛玻璃)效果样式
2023/05/21 HTML / CSS