P87 11
1 图像查找(单应性矩阵)
特征匹配作为输入,获得单应性矩阵
点X
在img1和img2中的成像分别为x,x'
图中H即为单应性矩阵
2 单应性矩阵 应用举例
获取一个矩阵,通过与图像1就算可以得到图像2对应点的位置;
图像二通过计算可以得到点原始位置,同样图像一也可以经过计算得到点原始位置;
自动转正
更换广告牌中的内容
3 单应性矩阵 代码示例
在一节FLANN特征匹配的基础上增加了,单应性矩阵、透视变换、框图
#获取的单应性矩阵
#srcPts从匹配点good中获取,每次遍历都可以从kp1[m.queryIdx]中获取一个关键点
#关键点需要转成浮点型
#对获取到的关键点要重新变换reshape(-1, 1, 2),x值随意,y值1,z值2,即无数行,每行一个元素,每个元素有2个子元素
#queryIdx,trainIdx分别是第一幅图,第二幅图的描述子索引值
if len(good) >= 4:#单应性矩阵要求匹配点要大于等于4
srcPts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)#原关键点
dstPts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)#目标关键点
#单应性矩阵
H, mask = cv2.findHomography(srcPts, dstPts, cv2.RANSAC, 5.0)#cv2.RANSAC对错误匹配点过滤,阈值1~10,这里是5
#透视变换
#获取要搜索的图的四个角点(左上,左下,右下,右上),同样需要转成浮点型,然后reshape
h, w = img1.shape[:2]
pts = np.float32([[0,0], [0, h-1], [w-1, h-1], [w-1, 0]]).reshape(-1, 1, 2)
dst = cv2.perspectiveTransform(pts, H)
#多边形绘制,将找到的子图在原图中框出来吧
cv2.polylines(img2, [np.int32(dst)], True, (0, 0, 255))#目标图,32位整形,TRUE封口,
else:
print('the number of good is less than 4.')
exit()
效果如下:
完整代码
import cv2
import numpy as np
#读文件
img1 = cv2.imread('opencv_search.png')
img2 = cv2.imread('opencv_orig.png')
#灰度化
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
#创建sift对象
sift= cv2.xfeatures2d.SIFT_create()
#进行检测关键点,同时计算描述子
kp1 ,des1= sift.detectAndCompute(gray1, None)#掩码设置为NONE,即对整张图检测
kp2 ,des2= sift.detectAndCompute(gray2, None)#掩码设置为NONE,即对整张图检测
#创建flann匹配器
index_params=dict(algorithm=1,tree=5)
search_params=dict(checks=50)
flann=cv2.FlannBasedMatcher(index_params,search_params)
#对描述子进行特征匹配
matches=flann.knnMatch(des1,des2,k=2)
#对匹配点优化过滤
good=[]
for i,(m,n) in enumerate(matches):#对img1,img2中的匹配点进行遍历
if m.distance < 0.7* n.distance:#越小越精准
good.append(m)
#获取的单应性矩阵
#srcPts从匹配点good中获取,每次遍历都可以从kp1[m.queryIdx]中获取一个关键点
#关键点需要转成浮点型
#对获取到的关键点要重新变换reshape(-1, 1, 2),x值随意,y值1,z值2,即无数行,每行一个元素,每个元素有2个子元素
#queryIdx,trainIdx分别是第一幅图,第二幅图的描述子索引值
if len(good) >= 4:#单应性矩阵要求匹配点要大于等于4
srcPts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)#原关键点
dstPts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)#目标关键点
#单应性矩阵
H, mask = cv2.findHomography(srcPts, dstPts, cv2.RANSAC, 5.0)#cv2.RANSAC对错误匹配点过滤,阈值1~10,这里是5
#透视变换
#获取要搜索的图的四个角点(左上,左下,右下,右上),同样需要转成浮点型,然后reshape
h, w = img1.shape[:2]
pts = np.float32([[0,0], [0, h-1], [w-1, h-1], [w-1, 0]]).reshape(-1, 1, 2)
dst = cv2.perspectiveTransform(pts, H)
#多边形绘制,将找到的子图在原图中框出来吧
cv2.polylines(img2, [np.int32(dst)], True, (0, 0, 255))#目标图,32位整形,TRUE封口,
else:
print('the number of good is less than 4.')
exit()
#绘制匹配结果
img3=cv2.drawMatchesKnn(img1,kp1,img2,kp2,[good],None)
cv2.imshow('img3', img3)
cv2.waitKey(0)