findHomography(srcPoints, dstPoints, method=None, ransacReprojThreshold=None, mask=None, maxIters=None, confidence=None)
srcPoints:源平面中點的坐標矩陣;
dstPoints:目標平面中點的坐標矩陣;
method:計算單應矩陣所使用的方法。不同的方法對應不同的參數,具體如下:
0: 利用所有點的常規方法;
RANSAC:基於RANSAC的魯棒算法;
LMEDS:最小中值魯棒算法;
RHO:基於PROSAC的魯棒算法;
ransacReprojThreshold:將點對視為內點的最大允許重投影錯誤阈值(僅用於RANSAC和RHO方法)若srcPoints和dstPoints是以像素為單位的,則該參數通常設置在1到10的范圍內。
mask:可選輸出掩碼矩陣,通常由魯棒算法(RANSAC或LMEDS)設置。 請注意,輸入掩碼矩陣是不需要設置的;
maxIters:RANSAC算法的最大迭代次數,默認值為2000;
confidence:置信度,取值范圍為0到1;
透視變換(Perspective Transformation)是將成像投影到一個新的視平面(Viewing Plane),也稱作投影映射(Projective Mapping)
perspectiveTransform(src, m, dst=None)
Src:輸入雙通道或三通道浮點數組;每個元素是要變換的二維/三維向量
。M:3x3或4x4浮點轉換矩陣
。Dst:與src大小和類型相同的param dst輸出數組
。
注:perspectiveTransform()輸⼊⾄少需要4個點,且點的坐標矩陣為(-1,1,2)即n個⼀⾏兩列的坐標矩陣,兩列代表橫縱坐標,其等價於將坐標齊次化後,與H矩陣的乘法運算
import os
import cv2
import numpy as np
#讀取圖片和縮放圖片
img1=cv2.imread('images/img1.jpg')
img1=cv2.resize(src=img1,dsize=(450,450))
gray1=cv2.cvtColor(src=img1,code=cv2.COLOR_BGR2GRAY)
img2=cv2.imread('images/img2.jpg')
img2=cv2.resize(src=img2,dsize=(450,450))
gray2=cv2.cvtColor(src=img2,code=cv2.COLOR_BGR2GRAY)
#創建SIFT
sift=cv2.xfeatures2d.SIFT_create()
#計算特征點和描述點
kp1,des1=sift.detectAndCompute(gray1,None)
kp2,des2=sift.detectAndCompute(gray2,None)
#使用KDTREE算法,樹的層級使用5
index_params=dict(algorithm=1,trees=5)
search_params=dict(checks=50)
#創建匹配器
flann=cv2.FlannBasedMatcher(index_params,search_params)
#特征點匹配
match=flann.knnMatch(des1,des2,k=2)
print('mathc: {}'.format(match))
#繪制匹配特征點
good=[]
for i ,(m,n) in enumerate(match):
if m.distance<0.7*n.distance:
good.append(m)
#當匹配項大於4時
if len(good)>=4:
#查找單應性矩陣
srcPoints=np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1,1,2)#轉換為n行的元素,每一行一個元素,並且這個元素由兩個值組成
dstPoints=np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1,1,2)
#獲取單應性矩陣
H,_=cv2.findHomography(srcPoints=srcPoints,dstPoints=dstPoints,method=cv2.RANSAC,ransacReprojThreshold=5.0)
#要搜索的圖的四個角點
h,w=np.shape(img1)[0],np.shape(img1)[1]
pts=np.float32([[0,0],[0,h-1],[w-1,h-1],[w-1,0]]).reshape(-1,1,2)
dst=cv2.perspectiveTransform(src=pts,m=H)
#繪制多邊形
cv2.polylines(img=img2,pts=[np.int32(dst)],isClosed=True,color=(0,255,0))
dest=cv2.drawMatchesKnn(img1=img1,keypoints1=kp1,img2=img2,keypoints2=kp2,matches1to2=[good],outImg=None,matchColor=(0,255,0))
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__ == '__main__':
print('Pycharm')