前言
这是计算机视觉的实验一作业,采用Homography方法来对广告牌上的图片进行修改,这里主要是记录下代码,以及一些理解。
图一(im_dst)
图二(im_src)
Homography(单应性)变换及理解
和图像处理的其他变换一样,需要使用到对应的变换矩阵,这是一个3*3的矩阵
该矩阵所有对应的值,都是未知的;同时在数学上理解,给定坐标系上一点(x1,y1),同时使用一定的映射关系,可以将该点映射到坐标系的另一点(x2,y2),它们之间的桥梁就是对应的映射矩阵;
对于上述的问题来说,我们可以通过图片查看器大致知道需要映射的点对的(x1,y1)(x2,y2);现在的关键在于这样的点对需要多少组,取哪里的点对。对于解未知数,首先就是建立其对应的方程组。只从矩阵的未知数来看,我们需要解出9个未知数;但是实际上只有8个未知数要解,因为H的对应值显然不是全0的,则取一个非0的值,所有的值同除于该值,则H矩阵将至少有一个已知数1,则对于8个未知数,我们需要8组方程式;而每一组对应的点对,可以创建两组方程组,这里需要4组对应点,即恰好可以取需要的四边形的顶点即可。其实该问题的主要代码实现难度是如何更高效的表示和解决方程的解。但是幸运的是,前人已经做了很多工作,在理解的基础上,我们可以调用opencv的相应函数即可;
因为需要在图一中的广告牌中修改,所以需要找到图二需要映射到的四个边界点,这里使用图片浏览器打开图一,记录下就行,如图(左下角为对应的像素):
而图片二就相对简单了,它对应的四个点就是图片的边界点,即(0,0), (0, W-1), (H - 1, 0), (H - 1, W - 1);
代码为:
im_src = cv2.imread('image/post.jpg')
im_dst = cv2.imread('image/place.jpg')
h, w, c = im_src.shape
pts_src = np.array([[0, 0], [w - 1, 0], [0, h - 1], [w - 1, h - 1]])
pts_dst = np.array([[70, 130], [169, 216], [20, 200], [149, 267]])
H, status = cv2.findHomography(pts_src, pts_dst) # 根据四个点间的关系找到Homography映射
im_out = cv2.warpPerspective(im_src, H, (im_dst.shape[1], im_dst.shape[0]))
映射完之后,除映射区域其他区域都是黑色,如图:
然后是进行拼接,根据生成图像的特定,创建函数:
def ADD(im_out,im_dst):
h, w, c = im_dst.shape
res = np.zeros((h, w, 3))
for i in range(h):
for j in range(w):
if im_out[i][j][0]==0:
res[i][j]=im_dst[i][j]
else:
res[i][j]=im_out[i][j]
res = cv2.convertScaleAbs(res)
return res
调用拼接:
im_out = ADD(im_out, im_dst)
结果为(可以看到广告牌中图片发生了变换):
完整代码:
# @coding: utf-8
# @time : 2021/3/10 9:21
# @Author: zhongbin
import cv2
import numpy as np
def ADD(im_out,im_dst):
h, w, c = im_dst.shape
res = np.zeros((h, w, 3))
for i in range(h):
for j in range(w):
if im_out[i][j][0]==0:
res[i][j]=im_dst[i][j]
else:
res[i][j]=im_out[i][j]
res = cv2.convertScaleAbs(res)
return res
if __name__ == "__main__":
im_src = cv2.imread('image/post.jpg')
im_dst = cv2.imread('image/place.jpg')
h, w, c = im_src.shape
pts_src = np.array([[0, 0], [w - 1, 0], [0, h - 1], [w - 1, h - 1]])
pts_dst = np.array([[70, 130], [169, 216], [20, 200], [149, 267]])
H, status = cv2.findHomography(pts_src, pts_dst) # 根据四个点间的关系找到Homography映射
im_out = cv2.warpPerspective(im_src, H, (im_dst.shape[1], im_dst.shape[0]))
im_out = ADD(im_out, im_dst)
cv2.imwrite('image/res.jpg', im_out)
cv2.imshow("1", im_out)
cv2.waitKey()