
OpenCV+Python 让你的朋友出现在《法制进行时》
发布日期:2021-05-06 23:44:04
浏览次数:27
分类:技术文章
本文共 3041 字,大约阅读时间需要 10 分钟。
文章目录
项目说明
通过 Python 中的 OpenCV 库实现一个类似于抠图的功能,如下图所示:



实现步骤
- 1、导入朋友的照片(前景图片);
- 2、选中前景图片中的四个顶点;
- 3、导入《法制进行时》栏目的照片(背景图片);
- 4、选取背景图片中要嵌入前景图片区域的四个顶点;
- 5、通过两组(八个)坐标计算单应性矩阵;
- 6、进行透视变换得到结果。
Python 实现
1、导入需要的库
import cv2import numpy as np
2、绘图函数
这里写一个绘图函数,方便绘图操作。
def cv_show(name,img): cv2.imshow(name, img) cv2.waitKey(0) cv2.destroyAllWindows()
3、前景图片
3.1 导入前景图片
fore = cv2.imread('fore.jpg')
3.2 选中前景图片中的四个顶点
size = fore.shapeH, W = size[:2]pts_fore = np.array([[0, 0], [W-1, 0], [W-1, H-1],[0, H-1]])
这里点的顺序为左上角、右上角、左下角和右下角,在背景图片中选点的时候也要遵循这个顺序。
坐标说明如下图所示:

4、背景图片
4.1 导入背景图片
back = cv2.imread('back.jpg')
4.2 选取背景图片中要嵌入前景图片区域的四个顶点
这个要比选取前景图片中的顶点难一些,因为要嵌入前景图片的区域的四个顶点并非整张图片的四个顶点,于是,在这里我们使用鼠标事件来找顶点坐标:
back_copy = back.copy() # 复制一个背景图片用于找顶点坐标,否则找出来的坐标会留在背景上a =[] # 空列表用于存放顶点横坐标b = [] # 空列表用于存放顶点纵坐标def on_EVENT_LBUTTONDOWN(event, x, y, flags, param): if event == cv2.EVENT_LBUTTONDOWN: # 鼠标事件:点击鼠标 xy = "%d,%d" % (x, y) # x 是这个点的横坐标;y 是这个点的纵坐标 a.append(x) b.append(y) cv2.circle(back_copy, (x, y), 1, (255, 0, 0), thickness=-1) # 在这个点上标红 cv2.putText(back_copy, xy, (x, y), cv2.FONT_HERSHEY_PLAIN, 1.0, (0, 0, 255), thickness=2) # 将这个点的坐标写在旁边 cv2.imshow("image", back_copy)cv2.namedWindow("image")cv2.setMouseCallback("image", on_EVENT_LBUTTONDOWN)cv2.imshow("image", back_copy)cv2.waitKey(0)cv2.destroyAllWindows()
【注】这里选点的顺序必须和前景图片中选点的顺序一致。
4.3 将顶点坐标写成前景图片顶点坐标的形式
pts_back = np.zeros((4, 2))for i in range(4): pts_back[i, :] = [a[i], b[i]]
5、透视变换
5.1 计算单应性矩阵
h, status = cv2.findHomography(pts_fore, pts_back)
5.2 对前景图片进行透视变换
out = cv2.warpPerspective(fore, h, (fore.shape[1], fore.shape[0]))
注意这里是 (fore.shape[1], fore.shape[0])。
透视变换的结果为:

6、将透视变换的结果放入背景图片中并保存
for i in range(H): for j in range(W): if out[i, j, :].all() != 0: back[i, j, :] = out[i, j, :]cv2.imwrite('out.jpg', back)
完整代码
import cv2import numpy as npdef cv_show(name,img): cv2.imshow(name, img) cv2.waitKey(0) cv2.destroyAllWindows()fore = cv2.imread('fore.jpg')size = fore.shapeH, W = size[:2]pts_fore = np.array([[0, 0], [W-1, 0], [W-1, H-1],[0, H-1]])back = cv2.imread('back.jpg')back_copy = back.copy()a =[]b = []def on_EVENT_LBUTTONDOWN(event, x, y, flags, param): if event == cv2.EVENT_LBUTTONDOWN: xy = "%d,%d" % (x, y) a.append(x) b.append(y) cv2.circle(back_copy, (x, y), 1, (255, 0, 0), thickness=-1) cv2.putText(back_copy, xy, (x, y), cv2.FONT_HERSHEY_PLAIN, 1.0, (0, 0, 255), thickness=2) cv2.imshow("image", back_copy)cv2.namedWindow("image")cv2.setMouseCallback("image", on_EVENT_LBUTTONDOWN)cv2.imshow("image", back_copy)cv2.waitKey(0)cv2.destroyAllWindows()pts_back = np.zeros((4, 2))for i in range(4): pts_back[i, :] = [a[i], b[i]]h, status = cv2.findHomography(pts_fore, pts_back)out = cv2.warpPerspective(fore, h, (fore.shape[1], fore.shape[0]))for i in range(H): for j in range(W): if out[i, j, :].all() != 0: back[i, j, :] = out[i, j, :]cv2.imwrite('out.jpg', back)
发表评论
最新留言
第一次来,支持一个
[***.219.124.196]2025年03月15日 03时07分06秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
09-01 Java语言基础(package、import)
2019-03-03
11-01 Java语言基础(Scanner类)
2019-03-03
12-04 Java语言基础(Arrays类)
2019-03-03
Accessing Excel Spreadsheets via C++
2019-03-04
excel上传核心
2019-03-04
json.parse细节
2019-03-04
redis
2019-03-04
ReID基础 | ReID工程中的一些小trick
2019-03-04
LINQ之Single,SingleOrDefault
2019-03-04
OpenCV6边缘检测[Canny算法]
2019-03-04
Hadoop_Scala操作Hbase
2019-03-04
Scala_1.控制台打印,变量定义,函数定义
2019-03-04
十五.Python异常处理
2019-03-04
c++备考期末必须看的知识点(一篇就够了)
2019-03-04
qt中初始化界面的几种方法
2019-03-04
【图论】游乐场
2019-03-04
【图论】【最短路】USACO 2.4 牛的旅行 (最短路)
2019-03-04
【图论】【最短路】工厂的烦恼
2019-03-04
【图论】刻录光盘
2019-03-04
C语言初阶——指针
2019-03-04