前言
OpenCV-Python|特征匹配+单应性+鼠标事件实现四点投影变换
代码
import numpy as np
import cv2 as cv
img1 = cv.imread('pikachu.png')
img2 = cv.imread('screen.png')
j = 0 # 全局变量,用来记录鼠标点击次数
# 源图四个顶点
src_pts = np.array([[0,0],
[0,img1.shape[0]-1],
[img1.shape[1]-1,img1.shape[0]-1],
[img1.shape[1]-1,0]])
dst_pts = [] # 四个顶点在目标图中的对应点
def mouse_homo(event, x, y, flags, param):
global j
if event == cv.EVENT_LBUTTONDOWN:
dst_pts.append([x, y])
elif event == cv.EVENT_LBUTTONUP:
cv.circle(tmp, (x,y), 3, (0,0,255))
j += 1
cv.namedWindow('image')
cv.setMouseCallback('image', mouse_homo)
tmp = img2.copy() # 拷贝目标图,用来画出鼠标点击的点
while(j>=0 and j<4):
cv.imshow('image', tmp)
cv.waitKey(1)
cv.imshow('image', tmp)
src_pts = np.float32(src_pts)
dst_pts = np.float32(dst_pts)
# 从四对点获取单应性矩阵
H = cv.getPerspectiveTransform(src_pts, dst_pts)
# 创建源图的掩码
mask = np.ones_like(img1)
# 投影变换
dst = cv.warpPerspective(img1, H, (img2.shape[1],img2.shape[0]))
mask = cv.warpPerspective(mask, H, (img2.shape[1],img2.shape[0]))
cv.imshow('dst', dst)
cv.imshow('mask', mask*255)
result = dst*mask + img2*(1-mask)
cv.imshow('result', result)
cv.waitKey(0)
cv.destroyAllWindows()
代码详解
首先我们给出两幅图像,img1是源图,img2是目标图,我们要把img2中的电脑屏幕替换成一张自己的图片。
要实现替换图片,需要通过投影变换。投影变换至少需要8个点,源图和目标图各4个。这里选取源图的四个顶点,对应目标图上的四个点可以通过鼠标点选。注意,四个顶点的顺序是按下左上、左下、右下、右上的逆时针顺序,在鼠标点选时也要按照这个顺序。
然后定义一个鼠标回调函数mouse_homo,在鼠标按下时记录点的坐标,在鼠标抬起时的位置画出圆圈。同时通过一个全局变量 j 来计数,在鼠标选了四个点之后退出循环。
得到了源图四个顶点和目标图对应的四个点后,接着就可以通过这8个点计算出投影变换矩阵,通过cv.warpPerspective()函数对源图进行投影变换。
最后,通过图像掩膜操作就可以将投影变换后的源图和目标图合成啦。
运行结果
![](https://i-blog.csdnimg.cn/blog_migrate/cedc67dc4a7625085abd269656a80c1f.png)
![](https://i-blog.csdnimg.cn/blog_migrate/555f879f24be6435a229217be62fa15d.png)
![](https://i-blog.csdnimg.cn/blog_migrate/b8fcaa96c94334f7763649003dbb320a.png)
![](https://i-blog.csdnimg.cn/blog_migrate/eb004327cd1856c12ea59964d3a05861.png)