1.图像查找=特征匹配+单应性矩阵
(1)函数讲解
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;
(2)透视变换
透视变换(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矩阵的乘法运算
(3)代码实战
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')