1. 程式人生 > 程式設計 >在OpenCV裡使用特徵匹配和單對映變換的程式碼詳解

在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裡使用特徵匹配和單對映變換的程式碼詳解,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回覆大家的。在此也非常感謝大家對我們網站的支援!
如果你覺得本文對你有幫助,歡迎轉載,煩請註明出處,謝謝!