应用OpenCV和Python进行SIFT算法的实现详解


Posted in Python onAugust 21, 2019

应用OpenCV和Python进行SIFT算法的实现

如下图为进行测试的gakki101和gakki102,分别验证基于BFmatcher、FlannBasedMatcher等的SIFT算法,对比其优劣。为体现出匹配效果对于旋转特性的优势,将图gakki101做成具有旋转特性的效果。

应用OpenCV和Python进行SIFT算法的实现详解

基于BFmatcher的SIFT实现

BFmatcher(Brute-Force Matching)暴力匹配,应用BFMatcher.knnMatch( )函数来进行核心的匹配,knnMatch(k-nearest neighbor classification)k近邻分类算法。

kNN算法则是从训练集中找到和新数据最接近的k条记录,然后根据他们的主要分类来决定新数据的类别。该算法涉及3个主要因素:训练集、距离或相似的衡量、k的大小。kNN算法的核心思想是如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性。该方法在确定分类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。

kNN方法在类别决策时,只与极少量的相邻样本有关。由于kNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,kNN方法较其他方法更为适合。
经检验 BFmatcher在做匹配时会耗费大量的时间。

代码段如下:

import numpy as np
import cv2
from matplotlib import pyplot as plt

imgname1 = 'E:/other/gakki101.jpg'
imgname2 = 'E:/other/gakki102.jpg'

sift = cv2.xfeatures2d.SIFT_create()

img1 = cv2.imread(imgname1)
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) #灰度处理图像
kp1, des1 = sift.detectAndCompute(img1,None)  #des是描述子

img2 = cv2.imread(imgname2)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)#灰度处理图像
kp2, des2 = sift.detectAndCompute(img2,None) #des是描述子

hmerge = np.hstack((gray1, gray2)) #水平拼接
cv2.imshow("gray", hmerge) #拼接显示为gray
cv2.waitKey(0)

img3 = cv2.drawKeypoints(img1,kp1,img1,color=(255,0,255)) #画出特征点,并显示为红色圆圈
img4 = cv2.drawKeypoints(img2,kp2,img2,color=(255,0,255)) #画出特征点,并显示为红色圆圈
hmerge = np.hstack((img3, img4)) #水平拼接
cv2.imshow("point", hmerge) #拼接显示为gray
cv2.waitKey(0)
# BFMatcher解决匹配
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1,des2, k=2)
# 调整ratio
good = []
for m,n in matches:
  if m.distance < 0.75*n.distance:
    good.append([m])

img5 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,matches,None,flags=2)
cv2.imshow("BFmatch", img5)
cv2.waitKey(0)
cv2.destroyAllWindows()

首先是针对图像的灰度化显示:

应用OpenCV和Python进行SIFT算法的实现详解

之后完成特征点的标注,用红色圆圈表示:

应用OpenCV和Python进行SIFT算法的实现详解

在cv2.drawMatchesKnn(img1,kp1,img2,kp2,matches,None,flags=2)下的匹配效果,比较杂乱,且会出错。

应用OpenCV和Python进行SIFT算法的实现详解

如果更换为cv2.drawMatchesKnn(img1,kp1,img2,kp2,good,None,flags=2),明显优于上面的匹配,并且为预想的匹配区域,其效果为:

应用OpenCV和Python进行SIFT算法的实现详解

基于FlannBasedMatcher的SIFT实现

FLANN(Fast_Library_for_Approximate_Nearest_Neighbors)快速最近邻搜索包,它是一个对大数据集和高维特征进行最近邻搜索的算法的集合,而且这些算法都已经被优化过了。在面对大数据集时它的效果要好于 BFMatcher。
经验证,FLANN比其他的最近邻搜索软件快10倍。使用 FLANN 匹配,我们需要传入两个字典作为参数。这两个用来确定要使用的算法和其他相关参数等。

第一个是 IndexParams
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
这里使用的是KTreeIndex配置索引,指定待处理核密度树的数量(理想的数量在1-16)。

第二个字典是SearchParams
search_params = dict(checks=100)用它来指定递归遍历的次数。值越高结果越准确,但是消耗的时间也越多。实际上,匹配效果很大程度上取决于输入。

5kd-trees50checks总能取得合理精度,而且短时间完成。在之下的代码中,丢弃任何距离大于0.7的值,则可以避免几乎90%的错误匹配,但是好的匹配结果也会很少。

import numpy as np
import cv2
from matplotlib import pyplot as plt

imgname1 = 'E:/other/gakki101.jpg'
imgname2 = 'E:/other/gakki102.jpg'

sift = cv2.xfeatures2d.SIFT_create()

# FLANN 参数设计
FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params,search_params)

img1 = cv2.imread(imgname1)
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) #灰度处理图像
kp1, des1 = sift.detectAndCompute(img1,None)#des是描述子

img2 = cv2.imread(imgname2)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
kp2, des2 = sift.detectAndCompute(img2,None)

hmerge = np.hstack((gray1, gray2)) #水平拼接
cv2.imshow("gray", hmerge) #拼接显示为gray
cv2.waitKey(0)

img3 = cv2.drawKeypoints(img1,kp1,img1,color=(255,0,255))
img4 = cv2.drawKeypoints(img2,kp2,img2,color=(255,0,255))

hmerge = np.hstack((img3, img4)) #水平拼接
cv2.imshow("point", hmerge) #拼接显示为gray
cv2.waitKey(0)
matches = flann.knnMatch(des1,des2,k=2)
matchesMask = [[0,0] for i in range(len(matches))]

good = []
for m,n in matches:
  if m.distance < 0.7*n.distance:
    good.append([m])

img5 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,matches,None,flags=2)
cv2.imshow("FLANN", img5)
cv2.waitKey(0)
cv2.destroyAllWindows()

首先是针对图像的灰度化显示:

应用OpenCV和Python进行SIFT算法的实现详解

之后完成特征点的标注,用红色圆圈表示:

应用OpenCV和Python进行SIFT算法的实现详解

在cv2.drawMatchesKnn(img1,kp1,img2,kp2,matches,None,flags=2)下的匹配效果,比较杂乱,且会出错。

应用OpenCV和Python进行SIFT算法的实现详解

如果更换为cv2.drawMatchesKnn(img1,kp1,img2,kp2,good,None,flags=2),明显优于上面的匹配,并且为预想的匹配区域,其效果为:

应用OpenCV和Python进行SIFT算法的实现详解

修改if m.distance < 0.7*n.distance:为 if m.distance < 1*n.distance:,显示效果为:

应用OpenCV和Python进行SIFT算法的实现详解

可见,虽然值越大,匹配的线条越密集,但错误匹配点也会增多,在lowe论文中,Lowe推荐ratio的阈值为0.8,但作者对大量任意存在尺度、旋转和亮度变化的两幅图片进行匹配,结果表明ratio取值在0. 4~0. 6 之间最佳,小于0. 4的很少有匹配点,大于0. 6的则存在大量错误匹配点,所以建议ratio的取值原则如下:

ratio=0. 4:对于准确度要求高的匹配;
ratio=0. 6:对于匹配点数目要求比较多的匹配;
ratio=0. 5:一般情况下。

基于FlannBasedMatcher的SURF实现

SURF全称为“加速稳健特征”(Speeded Up Robust Feature),不仅是尺度不变特征,而且是具有较高计算效率的特征。可被认为SURF是尺度不变特征变换算法(SIFT算法)的加速版。SURF最大的特征在于采用了haar特征以及积分图像的概念,SIFT采用的是DoG图像,而SURF采用的是Hessian矩阵(SURF算法核心)行列式近似值图像。SURF借鉴了SIFT算法中简化近似的思想,实验证明,SURF算法较SIFT算法在运算速度上要快3倍,综合性优于SIFT算法。

import numpy as np
import cv2
from matplotlib import pyplot as plt

imgname1 = 'E:/other/gakki101.jpg'
imgname2 = 'E:/other/gakki102.jpg'

surf = cv2.xfeatures2d.SURF_create()

FLANN_INDEX_KDTREE = 0
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
search_params = dict(checks=50)
flann = cv2.FlannBasedMatcher(index_params,search_params)

img1 = cv2.imread(imgname1)
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) #灰度处理图像
kp1, des1 = surf.detectAndCompute(img1,None)#des是描述子

img2 = cv2.imread(imgname2)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
kp2, des2 = surf.detectAndCompute(img2,None)

hmerge = np.hstack((gray1, gray2)) #水平拼接
cv2.imshow("gray", hmerge) #拼接显示为gray
cv2.waitKey(0)

img3 = cv2.drawKeypoints(img1,kp1,img1,color=(255,0,255))
img4 = cv2.drawKeypoints(img2,kp2,img2,color=(255,0,255))

hmerge = np.hstack((img3, img4)) #水平拼接
cv2.imshow("point", hmerge) #拼接显示为gray
cv2.waitKey(0)

matches = flann.knnMatch(des1,des2,k=2)

good = []
for m,n in matches:
  if m.distance < 0.7*n.distance:
    good.append([m])
img5 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,good,None,flags=2)
cv2.imshow("SURF", img5)
cv2.waitKey(0)
cv2.destroyAllWindows()

在cv2.drawMatchesKnn(img1,kp1,img2,kp2,matches,None,flags=2)下的匹配效果,比较杂乱,且会出错。

应用OpenCV和Python进行SIFT算法的实现详解

如果更换为cv2.drawMatchesKnn(img1,kp1,img2,kp2,good,None,flags=2),明显优于上面的匹配,并且为预想的匹配区域,其效果为:

应用OpenCV和Python进行SIFT算法的实现详解

但就其错误点数量和匹配效果而言,并没有SIFT来的理想。

基于BFMatcher的ORB实现

ORB(Oriented Fast and Rotated BRIEF),结合Fast与Brief算法,并给Fast特征点增加了方向性,使得特征点具有旋转不变性,并提出了构造金字塔方法,解决尺度不变性,但文章中没有具体详述。特征提取是由FAST(Features from Accelerated Segment Test)算法发展来的,特征点描述是根据BRIEF(Binary Robust Independent Elementary Features)特征描述算法改进的。ORB特征是将FAST特征点的检测方法与BRIEF特征描述子结合起来,并在它们原来的基础上做了改进与优化。ORB主要解决BRIEF描述子不具备旋转不变性的问题。实验证明,ORB远优于之前的SIFT与SURF算法,ORB算法的速度是sift的100倍,是surf的10倍。

import numpy as np
import cv2
from matplotlib import pyplot as plt

imgname1 = 'E:/other/gakki101.jpg'
imgname2 = 'E:/other/gakki102.jpg'

orb = cv2.ORB_create()

img1 = cv2.imread(imgname1)
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) #灰度处理图像
kp1, des1 = orb.detectAndCompute(img1,None)#des是描述子

img2 = cv2.imread(imgname2)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
kp2, des2 = orb.detectAndCompute(img2,None)

hmerge = np.hstack((gray1, gray2)) #水平拼接
cv2.imshow("gray", hmerge) #拼接显示为gray
cv2.waitKey(0)

img3 = cv2.drawKeypoints(img1,kp1,img1,color=(255,0,255))
img4 = cv2.drawKeypoints(img2,kp2,img2,color=(255,0,255))

hmerge = np.hstack((img3, img4)) #水平拼接
cv2.imshow("point", hmerge) #拼接显示为gray
cv2.waitKey(0)

# BFMatcher解决匹配
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1,des2, k=2)
# 调整ratio
good = []
for m,n in matches:
  if m.distance < 0.75*n.distance:
    good.append([m])

img5 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,good,None,flags=2)
cv2.imshow("ORB", img5)
cv2.waitKey(0)
cv2.destroyAllWindows()

经显示观察到,ORB算法在特征点标记时数量较少,如图:

应用OpenCV和Python进行SIFT算法的实现详解

在cv2.drawMatchesKnn(img1,kp1,img2,kp2,matches,None,flags=2)下的匹配效果,比较杂乱,且会出错。

应用OpenCV和Python进行SIFT算法的实现详解

如果更换为cv2.drawMatchesKnn(img1,kp1,img2,kp2,good,None,flags=2),明显优于上面的匹配,并且为预想的匹配区域,其效果为:

应用OpenCV和Python进行SIFT算法的实现详解

但同样会出现在同样的匹配方式上,效果不如SIFT的现象。
如下为使用FAST作为特征描述的关键代码和提取图像显示:

import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('E:/other/gakki102.',0)

fast=cv2.FastFeatureDetector_create()#获取FAST角点探测器
kp=fast.detect(img,None)#描述符
img = cv2.drawKeypoints(img,kp,img,color=(255,255,0))#画到img上面
print ("Threshold: ", fast.getThreshold())#输出阈值
print ("nonmaxSuppression: ", fast.getNonmaxSuppression())#是否使用非极大值抑制
print ("Total Keypoints with nonmaxSuppression: ", len(kp))#特征点个数
cv2.imshow('fast',img)
cv2.waitKey(0)

如图为FAST特征提取的图像显示:

应用OpenCV和Python进行SIFT算法的实现详解

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

Python 相关文章推荐
Python中3种内建数据结构:列表、元组和字典
Nov 30 Python
Python中实现从目录中过滤出指定文件类型的文件
Feb 02 Python
Python中几种操作字符串的方法的介绍
Apr 09 Python
关于Django外键赋值问题详解
Aug 13 Python
Python中表示字符串的三种方法
Sep 06 Python
详解Python Matplotlib解决绘图X轴值不按数组排序问题
Aug 05 Python
导入tensorflow:ImportError: libcublas.so.9.0 报错
Jan 06 Python
Python计算指定日期是今年的第几天(三种方法)
Mar 26 Python
python matplotlib模块基本图形绘制方法小结【直线,曲线,直方图,饼图等】
Apr 26 Python
如何解决python多种版本冲突问题
Oct 13 Python
pytorch finetuning 自己的图片进行训练操作
Jun 05 Python
自动在Windows中运行Python脚本并定时触发功能实现
Sep 04 Python
Python Django 添加首页尾页上一页下一页代码实例
Aug 21 #Python
Python Django 简单分页的实现代码解析
Aug 21 #Python
Django项目之Elasticsearch搜索引擎的实例
Aug 21 #Python
python爬虫豆瓣网的模拟登录实现
Aug 21 #Python
Python Django 页面上展示固定的页码数实现代码
Aug 21 #Python
详解Python利用random生成一个列表内的随机数
Aug 21 #Python
Python Django 封装分页成通用的模块详解
Aug 21 #Python
You might like
PHP在XP下IIS和Apache2服务器上的安装
2006/09/05 PHP
一个数据采集类
2007/02/14 PHP
你可能不知道PHP get_meta_tags()函数
2014/05/12 PHP
PHP设计模式之装饰者模式代码实例
2015/05/11 PHP
jQuery UI 应用不同Theme的办法
2010/09/12 Javascript
学习面向对象之面向对象的术语
2010/11/30 Javascript
我的javascript 函数链之演变
2011/04/07 Javascript
javascript学习笔记(九)javascript中的原型(prototype)及原型链的继承方式
2011/04/12 Javascript
node.js中的querystring.stringify方法使用说明
2014/12/10 Javascript
全面理解JavaScript中的闭包
2016/05/12 Javascript
深入理解jQuery事件绑定
2016/06/02 Javascript
详解js中的apply与call的用法
2016/07/30 Javascript
js实现数组和对象的深浅拷贝
2017/09/30 Javascript
jQuery基于Ajax实现读取XML数据功能示例
2018/05/31 jQuery
JS实现图片拖拽交换效果
2018/11/30 Javascript
jquery.tagsinput.js实现记录checkbox勾选的顺序
2019/09/21 jQuery
JavaScript工具库MyTools详解
2020/01/01 Javascript
解决vue与node模版引擎的渲染标记{{}}(双花括号)冲突问题
2020/09/11 Javascript
vue实现简易的双向数据绑定
2020/12/29 Vue.js
Python多层嵌套list的递归处理方法(推荐)
2016/06/08 Python
Python selenium 三种等待方式解读
2016/09/15 Python
python分割一个文本为多个文本的方法
2019/07/22 Python
Python字典生成式、集合生成式、生成器用法实例分析
2020/01/07 Python
如何基于Python + requests实现发送HTTP请求
2020/01/13 Python
python统计函数库scipy.stats的用法解析
2020/02/25 Python
Python venv虚拟环境配置过程解析
2020/07/08 Python
利用 Canvas实现绘画一个未闭合的带进度条的圆环
2019/07/26 HTML / CSS
DC Shoes荷兰官方网站:美国极限运动品牌
2019/10/22 全球购物
畜牧兽医本科生个人的自我评价
2013/10/11 职场文书
网站设计师的岗位职责
2013/11/21 职场文书
大学毕业后的十年规划
2014/01/07 职场文书
《蒙娜丽莎之约》教学反思
2014/02/27 职场文书
销售口号大全
2014/06/11 职场文书
2014年销售助理工作总结
2014/12/01 职场文书
天鹅湖观后感
2015/06/09 职场文书
师德师风培训感言
2015/08/03 职场文书