基于python+opencv的SIFT演算法分析
當對影像進行平移、旋轉、縮放等操作后,其特性保持不變,此演算法即SIFT演算法,影像在平移、旋轉比例和光照條件發生變化時的匹配,對視角變換和仿射變換,SIFT演算法具有較穩定的特征匹配性能,SIFT 演算法實作具體程序如下:
(1)特征點檢測
a.建立尺度空間
尺度空間理論于1983年被提出,后被推廣到二維影像,二維影像尺度空間,可由影像與高斯核進行卷積得到:
公式 (4- 1)
式中:I(x,y)代表二維影像,G(x,y,σ)是高斯核,L(x,y,σ)表示尺度空間,σ大小與影像的平滑程度有關,σ值越大則尺度越粗糙,
b.DOG空間關鍵點檢測
Lowe教授提出,可以用差分高斯DoG極值作為判斷,對歸一化LoG算子進行近似,可以得到DoG算子,
公式 (4- 2)
其中,K為相鄰兩個尺度因子的比值.
先把高斯影像金字塔分成若干階,每階又分成3~5層,相鄰層之間的σ相差一個k,為了得到保持影像的連續性,下一階影像的底層是通過第一階影像得到的,最后一階影像的尺度因子為2σ進行2降采樣,為了搜索尺度空間的極值點,如下圖所示,中間的藍色像素要比同層的8個像素,以及上下層的18個像素,只有當其值最大或最小,才將該點作為極值點并存盤起來供后續計算使用,
c.關鍵點的位置與尺度的確定
由關鍵點周圍的每個像素梯度計算其位置及尺度,擬合計算采用三維二次函式,尺度空間函式D(x,y,σ)在極值點(x0,y0,σ)處的Taylor展開式如下:
公式 (4- 3)
對上式求導,當等于零時,比較準確的位置如下:
公式 (4- 4)
可得極值點的方程:
公式 (4- 5)
當 ,表示其不易受噪聲影響,可保留,反之要去除,
邊緣回應的去除,需要通過一個2×2的Hessian矩陣來計算主曲率,
公式 (4- 6)
其中,主曲率用D表示,特征值用H表示,特征值用α、β表示,則:
公式 (4- 7)
Det(H)代表矩陣H的行列式,Tr(H)代表矩陣H對角線元素之和,令𝛼=𝑟𝛽,可以得到下式
公式 (4- 8)
(r+1) 2r的比值與r成正比,在去除邊緣影響時,需要按照下式進行檢測,
公式 (4- 9)
當上式成立時保留,反之去除,
d.計算關鍵點的方向
利用關鍵點鄰域像素其梯度方向特性,為每個關鍵點指定方向引數,采用下式計算關鍵點的梯度和方向,
公式 (4- 10)
式中,L為檢測的關鍵點所在的尺度,
(2)生成特征向量
首先,將坐標軸旋轉為關鍵點的方向,取8×8的視窗,如圖4-3所示,(a)的中心點為關鍵點,對其進行加權運算,每4×4的小塊上,計算8個方向的梯度方向直方圖,形成一個種子點,如圖4-3(b)所示,一個關鍵點由4個種子點組成,每個種子點有8個方向資訊,每個關鍵點使用16個種子點來描述,一個關鍵點就形成128維的SIFT特征向量,
(3)特征匹配
如何確定其適用性是SIFT匹配演算法的最后一個關鍵步驟,這里選擇關鍵點特征向量的歐氏距離作為相似性的判斷,判斷步驟如下,首先在第一幅影像中提取一個特征點,再提取另一幅影像的特征點,并記錄兩個歐氏距離最近的點,其次,比較最后一步的歐幾里得距離,如果分割第二最小距離的最小距離的值小于閾值,則這兩個點匹配成功,反之不接受,
(4)演算法特點
SIFT算子對影像的亮度變化、尺度縮放、旋轉、噪聲有很好的魯棒性,演算法較穩定,但是,存在匹配精度差、匹配準確率低、實時性差等問題,仍需和其它演算法相結合,
(5)適用場景
目標的旋轉、縮放、平移;影像仿射/投影變換;光照影響;目標遮擋;雜物場景;噪聲,
代碼段如下:
#coding=utf-8
import cv2
import time
sift = cv2.xfeatures2d.SIFT_create(nfeatures=1000)
img1 = cv2.imread("E:/left3.2.bmp")
img2 = cv2.imread("E:/right3.2.bmp")
img3=img2
#img3=cv2.flip(img2,-1)
#求中心點,對影像進行旋轉
#(h,w)=img2.shape[:2]
#center=(w//2,h//2)
#M=cv2.getRotationMatrix2D(center,30,1.0)
#img3=cv2.warpAffine(img2,M,(w,h))
#灰度化
img1_gray = cv2.cvtColor(img1, cv2.COLOR_RGB2GRAY)
img3_gray = cv2.cvtColor(img3, cv2.COLOR_RGB2GRAY)
kp1, des1 = sift.detectAndCompute(img1_gray, None)
kp2, des2 = sift.detectAndCompute(img3_gray, None)
#繪制特征點圖
img1t=cv2.drawKeypoints(img1_gray,kp1,img1)
img3t=cv2.drawKeypoints(img3_gray,kp2,img3)
#進行KNN特征匹配,K設定為2
start=time.time()
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1, des2, k=2)
good=[]
print(len(matches))
matchesMask = [[0, 0] for i in range(len(matches))]
for i, (m1, m2) in enumerate(matches):
if m1.distance < 0.7* m2.distance: # 兩個特征向量之間的歐氏距離,越小表明匹配度越高,
good.append(m1)
matchesMask[i]=[1,0]
pt1 = kp1[m1.queryIdx].pt # queryIdx 是匹配之后所對應關鍵點的序號,第一個載入圖片的匹配關鍵點序號
pt2 = kp2[m1.trainIdx].pt # trainIdx 是匹配之后所對應關鍵點的序號,第二個載入圖片的匹配關鍵點序號
#print(kpts1)
print(i, pt1, pt2) #列印匹配點個數,并標出兩圖中的坐標位置
#畫特征點及其周圍的圓圈
cv2.circle(img1, (int(pt1[0]), int(pt1[1])), 5, (0, 255, 0), -1)
num = "{}".format(i)
cv2.putText(img1, num, (int(pt1[0]), int(pt1[1])),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
cv2.circle(img3, (int(pt2[0]), int(pt2[1])), 5, (0, 255, 0), -1)
cv2.putText(img3, num, (int(pt2[0]), int(pt2[1])),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
end=time.time()
print("good match num:{} good match points:".format(len(good)))
print("number of feature points:", len(kp1), len(kp2))
#匹配連線
draw_params = dict(matchColor=(255, 0, 0),
singlePointColor=(0, 0, 255),
matchesMask=matchesMask,
flags=0)
res = cv2.drawMatchesKnn(img1, kp1, img3, kp2, matches, None,**draw_params)
print("運行時間:%.2f秒"%(end-start))
cv2.imshow("img1_gray",img1_gray)
cv2.imshow("img3_gray",img3_gray)
cv2.imshow("Result", res)
cv2.imshow("img1", img1)
cv2.imshow("img3", img3)
cv2.imwrite("SIFTimg1_gray.jpg",img1_gray)
cv2.imwrite("SIFTimg3_gray.jpg",img3_gray)
cv2.imwrite("SIFTimg1.jpg",img1)
cv2.imwrite("SIFTimg3.jpg",img3)
cv2.imwrite("SIFTimg1t.jpg",img1t)
cv2.imwrite("SIFTimg3t.jpg",img3t)
cv2.imwrite("SIFTResult.jpg",res)
#cv2.waitKey(0)
#cv2.destroyAllWindows()
可以分別對所要匹配影像進行原圖匹配、進行尺度變換后匹配、旋轉后匹配、以及對影像進行遮擋后進行匹配;進而來對匹配結果進行分析是否符合SIFT演算法的特點,
尺度變換時輸出結果:

左右圖各取特征點1000,匹配對數195,匹配時間為0.36s
逆時針旋轉30度輸出結果:

左圖特征點835右圖特征點714,匹配對數499,匹配時間0.54s
遮擋情況下的輸出匹配結果:

左圖特征點835,右圖特征點807,匹配對數631,匹配時間0.27s
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/277838.html
標籤:python
上一篇:第十一屆藍橋杯大賽軟體類省賽第二場python大學組題解(原始碼+注釋)
下一篇:新手求助關于CPLEX的問題
