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

  • 时间:
  • 浏览:58

利用OpenCV战Python停止SIFT算法的真现

以下图为停止测试的gakki101战gakki102,别离考证基于BFmatcher、FlannBasedMatcher等的SIFT算法,对照其好坏。为表现出婚配结果对扭转特征的劣势,将图gakki101做成具有扭转特征的结果。

基于BFmatcher的SIFT真现

BFmatcher(Brute-Force Matching)暴力婚配,利用BFMatcher.knnMatch( )函数去停止中心的婚配,knnMatch(k-nearest neighbor classification)k远邻分类算法。

kNN算法例是从锻炼集合找到战新数据最靠近的k笔记录,然后按照他们的次要分类去决议新数据的种别。该算法触及3个次要果素:锻炼散、间隔或类似的权衡、k的巨细。kNN算法的中心思惟是若是1个样本正在特点空间中的k个最相邻的样本中的年夜大都属于某1个种别,则该样本也属于那个种别,并具有那个种别上样本的特征。该办法正在肯定分类决议计划上只根据最临近的1个或几个样本的种别去决议待分样本所属的种别。

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()

起首是针对图象的灰度化显现:

以后完成特点面的标注,用白色圆圈暗示:

正在cv2.drawMatchesKnn(img1,kp1,img2,kp2,matches,None,flags=2)下的婚配结果,比力混乱,且会堕落。

若是改换为cv2.drawMatchesKnn(img1,kp1,img2,kp2,good,None,flags=2),较着劣于下面的婚配,而且为料想的婚配地区,其结果为:

基于FlannBasedMatcher的SIFT真现

FLANN(Fast_Library_for_Approximate_Nearest_Neighbors)疾速比来邻搜刮包,它是1个对年夜数据散战下维特点停止比来邻搜刮的算法的汇合,并且那些算法皆已被劣化过了。正在面临年夜数据散时它的结果要好过 BFMatcher。
经历证,FLANN比其他的比来邻搜刮硬件快10倍。利用 FLANN 婚配,我们需求传进两个字典做为参数。那两个用去肯定要利用的算法战其他相干参数等。

第1个是 IndexParams
index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
那里利用的是KTreeIndex设置装备摆设索引,指定待处置核稀度树的数目(抱负的数目正在1⑴6)。

第2个字典是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()

起首是针对图象的灰度化显现:

以后完成特点面的标注,用白色圆圈暗示:

正在cv2.drawMatchesKnn(img1,kp1,img2,kp2,matches,None,flags=2)下的婚配结果,比力混乱,且会堕落。

若是改换为cv2.drawMatchesKnn(img1,kp1,img2,kp2,good,None,flags=2),较着劣于下面的婚配,而且为料想的婚配地区,其结果为:

修正if m.distance < 0.7*n.distance:为 if m.distance < 1*n.distance:,显现结果为:

可睹,固然值越年夜,婚配的线条越稀散,但毛病婚配面也会增加,正在lowe论文中,Lowe保举ratio的阈值为0.8,但做者对年夜量肆意存正在标准、扭转战明度变革的两幅图片停止婚配,成果表白ratio与值正在0. 4~0. 6 之间最好,小于0. 4的很少有婚配面,年夜于0. 6的则存正在年夜量毛病婚配面,以是倡议ratio的与值本则以下:

ratio=0. 4:对精确度请求下的婚配;
ratio=0. 6:对婚配面数量请求比力多的婚配;
ratio=0. 5:1般状况下。

基于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)下的婚配结果,比力混乱,且会堕落。

若是改换为cv2.drawMatchesKnn(img1,kp1,img2,kp2,good,None,flags=2),较着劣于下面的婚配,而且为料想的婚配地区,其结果为:

但便其毛病面数目战婚配结果而行,并出有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算法正在特点面标识表记标帜时数目较少,如图:

正在cv2.drawMatchesKnn(img1,kp1,img2,kp2,matches,None,flags=2)下的婚配结果,比力混乱,且会堕落。

若是改换为cv2.drawMatchesKnn(img1,kp1,img2,kp2,good,None,flags=2),较着劣于下面的婚配,而且为料想的婚配地区,其结果为:

但一样会呈现正在一样的婚配体例上,结果没有如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特点提与的图象显现:

以上便是本文的全数内容,期望对各人的进修有所帮忙,也期望各人多多撑持剧本之家。