在OpenCV裡使用特徵匹配和單對映變換的程式碼詳解
前面已經學習特徵查詢和對應匹配,接著下來在特徵匹配之後,再使用findHomography函式來找出對應影象的投影矩陣。首先使用一個查詢圖片,然後在另外一張圖片裡找到目標物件,其實就是想在圖片裡查詢所需要目標的一部分割槽域。為了實現這樣的功能,需要使用calib3d庫裡的一個函式cv.findHomography()
,把從兩張圖片裡找到的特徵點當作引數,傳送給這個函式,然後這個函式返回一個投影變換矩陣,我們就可以使用 cv.perspectiveTransform()
函式來對查詢的目標進行投影,這樣就可以在複雜圖片裡標記出相應的目標位置。
我們已經看到,在匹配時可能會有一些錯誤,這可能會影響結果。為了解決這個問題,需要使用RANSAC 或 LEAST_MEDIAN演算法。所以提供正確估計的良好匹配稱為內聚,其餘的稱為外聯。cv.findHomography()
在例子裡,先使用ORB來尋找兩個圖片的特徵點,接著根據設定條件為10個匹配特徵,如果滿足就會計算投影變換矩陣,一旦獲得3x3的矩陣,就可以把尋找的目標物件在圖片裡標記出來。最後在複雜的圖片裡用白色線條標記出來。
引數詳解:
srcPoints 源平面中點的座標矩陣,可以是CV_32FC2型別,也可以是vector<Point2f>型別
dstPoints 目標平面中點的座標矩陣,可以是CV_32FC2型別,也可以是vector<Point2f>型別
method 計算單應矩陣所使用的方法。不同的方法對應不同的引數,具體如下:
0 - 利用所有點的常規方法
RANSAC - RANSAC-基於RANSAC的魯棒演算法
LMEDS - 最小中值魯棒演算法
RHO - PROSAC-基於PROSAC的魯棒演算法
ransacReprojThreshold
將點對視為內點的最大允許重投影錯誤閾值(僅用於RANSAC和RHO方法)。如果
則點被認為是個外點(即錯誤匹配點對)。若srcPoints和dstPoints是以畫素為單位的,則該引數通常設定在1到10的範圍內。
mask
可選輸出掩碼矩陣,通常由魯棒演算法(RANSAC或LMEDS)設定。 請注意,輸入掩碼矩陣是不需要設定的。
maxIters RANSAC演算法的最大迭代次數,預設值為2000。
confidence 可信度值,取值範圍為0到1.
該函式能夠找到並返回源平面和目標平面之間的轉換矩陣H,以便於反向投影錯誤率達到最小。
演示使用的例子如下:
#python 3.7.4,opencv4.1 #蔡軍生 https://blog.csdn.net/caimouse/article/details/51749579 # import numpy as np import cv2 from matplotlib import pyplot as plt MIN_MATCH_COUNT = 10 #讀取檔案 img1 = cv2.imread('rmb3.png') img2 = cv2.imread('rmb4.png') #初始化ORB檢測器 orb = cv2.ORB_create() #用ORB查詢關鍵點 kp1,des1 = orb.detectAndCompute(img1,None) kp2,des2 = orb.detectAndCompute(img2,None) # FLANN引數 FLANN_INDEX_LSH = 6 index_params = dict(algorithm = FLANN_INDEX_LSH,table_number = 6,key_size = 12,multi_probe_level = 1) search_params = dict(checks=50) #或者使用一個空的字典 flann = cv2.FlannBasedMatcher(index_params,search_params) matches = flann.knnMatch(des1,des2,k=2) # 比率 good = [] for m,n in matches: if m.distance < 0.7*n.distance: good.append(m) if len(good)>MIN_MATCH_COUNT: src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2) dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,2) #找到投影變換矩陣 M,mask = cv2.findHomography(src_pts,dst_pts,cv2.RANSAC,5.0) matchesMask = mask.ravel().tolist() #進行投影變換 h,w,d = img1.shape pts = np.float32([ [0,0],[0,h-1],[w-1,0] ]).reshape(-1,2) dst = cv2.perspectiveTransform(pts,M) #畫變換後的外形 img2 = cv2.polylines(img2,[np.int32(dst)],True,(255,255,255),3,cv2.LINE_AA) else: print( "Not enough matches are found - {}/{}".format(len(good),MIN_MATCH_COUNT) ) matchesMask = Non draw_params = dict(matchColor = (0,0),# draw matches in green color singlePointColor = None,matchesMask = matchesMask,# draw only inliers flags = 2) img3 = cv2.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params) #顯示圖片 cv2.imshow('img3',img3) cv2.waitKey(0) cv2.destroyAllWindows()
結果輸出如下:
總結
以上所述是小編給大家介紹的在OpenCV裡使用特徵匹配和單對映變換的程式碼詳解,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回覆大家的。在此也非常感謝大家對我們網站的支援!
如果你覺得本文對你有幫助,歡迎轉載,煩請註明出處,謝謝!