python 图片背景前景分离_【绝了】用 Python 把朋友头像变表情包!

19c154c156fd932e8bc3978a4e70d4b9.png

正文
在日常生活中,我们经常会存取一些朋友们的丑照,在这个项目中,我们以萌萌哒的熊猫头作为背景,然后试着在背景图上加入朋友们的照片,效果如下图所示。

e6f4abd586ad93957ffc916f8c9ba118.png

9229e3599d5ba434f523cec52656fc7a.pngb369318ea9e4b1ab86662f36a196ff0c.png

实现步骤

  • 导入朋友的照片(前景照片);

  • 处理前景照片(缩放、旋转,填充);

  • 导入熊猫头照片(背景照片);

  • 将前景和背景拼接起来形成表情包;

  • 在表情包下面添加文字。

1、导入需要的库

import cv2import numpy as mpimport matplotlib.pyplot as pltfrom PIL import Image, ImageDraw, ImageFont

这个项目主要是通过 opencv 完成,但如果要在表情包下面写中文的话,PIL(pillow)库是必不可少的。

2、绘图函数

这里写一个绘图函数,方便绘图操作。

def plt_show(img):    imageRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)    plt.imshow(imageRGB)    plt.show()

3、导入前景照片

image = cv2.imread('SXC.jpg', 0)  # 导入灰度图即可plt_show(image)

bf7a9d5c24dd985f70349714781c10e6.png

4、等比例缩放前景照片

因为我们发现前景照片的尺寸比背景尺寸还要大,这显然是不合适的,所以要先对其进行等比例(0.3)缩放。

image_resize = cv2.resize(image, None, fx=0.3, fy=0.3, interpolation = cv2.INTER_CUBIC)plt_show(image_resize)

7f6a1133f86046214da99235e2f899b8.png

5、对前景照片进行二值化处理

在这里,我们将像素值大于 80 的区域设置为 255;小于 80 的区域设置成 0。

ret, image_binary = cv2.threshold(image_resize, 80, 255, cv2.THRESH_BINARY)plt_show(image_binary)

3ef52e63b65f7c65fc0b4ae72537e320.png

6、提取出感兴趣区域

image_roi = image_binary[74: 185, 0: 150]plt_show(image_roi)

260e4669f091e3306a8d37f632c16356.png

7、旋转图片

因为我们的背景图片(熊猫头)是正的,而前景图片有些向右倾斜,所以要先对其进行旋转操作(大概逆时针旋转 15 度即可)。

rows, cols = image_roi.shapeM = cv2.getRotationMatrix2D(((cols-1)/2.0, (rows-1)/2.0), 15, 1)  # (旋转中心,逆时针旋转角度,各个方向同等扩大比例)image_rotate = cv2.warpAffine(image_roi, M, (140, 130))  # (140, 130) 是指旋转后的画布大小plt_show(image_rotate)

aaa466c3a492fbea4dbaf4b2a6ea190d.png

8、将一些不需要的黑色区域删除掉

在这里我们使用 cv2.fillPoly 函数对不需要的区域用白色进行填充。

h, w = image_rotate.shapeimage_rotate_copy = image_rotate.copy()pts1 = np.array([[0, 20],  [64, 0], [0, 0]], np.int32)pts2 = np.array([[0, 18],  [0, h], [80, h]], np.int32)pts3 = np.array([[0, 100],  [0, h], [w, h], [w, 100]], np.int32)pts4 = np.array([[111, 0],  [w, 0], [w, 30]], np.int32)pts5 = np.array([[124, 0],  [115, h], [w, h]], np.int32)pts6 = np.array([[120, 40],  [95, 100], [120, 100]], np.int32)foreground = cv2.fillPoly(image_rotate_copy, [pts1], (255, 255, 255))  # (图片,填充区域,填充颜色)foreground = cv2.fillPoly(image_rotate_copy, [pts2], (255, 255, 255))foreground = cv2.fillPoly(image_rotate_copy, [pts3], (255, 255, 255))foreground = cv2.fillPoly(image_rotate_copy, [pts4], (255, 255, 255))foreground = cv2.fillPoly(image_rotate_copy, [pts5], (255, 255, 255))foreground = cv2.fillPoly(image_rotate_copy, [pts6], (255, 255, 255))plt_show(foreground)

4b711482e882948fb51b306c8d9ff15a.png

9、再次提取感兴趣区域并缩放

foreground_roi = foreground[0: 93, 0: 125]plt_show(foreground_roi)foreground_roi_resize = cv2.resize(foreground_roi, None, fx=2.5, fy=2.5, interpolation = cv2.INTER_CUBIC)plt_show(foreground_roi_resize)

8d8550bda40f7c24ec8a126e377788ee.png82288a4f6b9f082c5876c4b986998802.png

10、导入背景图片

background = cv2.imread('back.jpg', 0)plt_show(background)

b106ef98af85fe87d2363bfef3f7e87b.png

11、组合两张图片成表情包

h_f, w_f = foreground.shapeh_b, w_b = background.shapeleft = (w_b - w_f)//2  # 前景图片在背景图片中的左边的横坐标right = left + w_f  # 前景图片在背景图片中的右边的横坐标top = 100  # 前景图片在背景图片中的上边的纵坐标bottom = top + h_f  # 前景图片在背景图片中的下边的纵坐标emoji = backgroundemoji[top: bottom, left: right] = foregroundplt_show(emoji)

8f912b6a7defae0627b3f98483e9a75a.png

12、在表情包下面添加文本

12.1 添加英文文本

如果只是要添加英文文本,用 opencv 就可以解决:

emoji_copy = emoji.copy()# (图片,文本,位置,字体,文本大小,文本颜色,文本粗细)cv2.putText(emoji_copy, "FXXK!!", (210, 500), cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 0, 0), 5)plt_show(emoji_copy)

d0edb7c446cd30dd2cf41be50a324f0e.png

12.2 添加中文文本

如果要添加中文文本,我们需要借助 PIL 库来实现。

PilImg = Image.fromarray(emoji)  # cv2 转 PILdraw = ImageDraw.Draw(PilImg)  # 创建画笔ttfront = ImageFont.truetype('simhei.ttf', 34)  # 设置字体draw.text((210, 450),"你瞅啥!!",fill=0, font=ttfront)  # (位置,文本,文本颜色,字体)emoji_text = cv2.cvtColor(np.array(PilImg),cv2.COLOR_RGB2BGR)  # PIL 转回 cv2plt_show(emoji_text)

8f5cbe744934c76227759bff96f60aae.png

13、保存表情包

cv2.imwrite('./emoji.png', np.array(emoji_text))

热文推荐:1、登顶热榜Top1,使用 Python实现所有算法!2、【思维导图】Python从入门到精通3、周末两天两夜写的飞机大战(附源码)4、Python版视频下载神器,支持80+网站,比迅雷还快!5、这可能是史上最全的Python算法集!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/472099.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 1899. 合并若干三元组以形成目标三元组

文章目录1. 题目2. 解题1. 题目 三元组 是一个由三个整数组成的数组。 给你一个二维整数数组 triplets ,其中 triplets[i] [ai, bi, ci] 表示第 i 个 三元组 。 同时,给你一个整数数组 target [x, y, z] ,表示你想要得到的 三元组 。 为了…

openpyxl 读写 excel

import openpyxl book openpyxl.load_workbook(b.xlsx) # 读取 # sheet book["name_tab"] sheet book.active # rowsheet.max_row # 行数 columnsheet.max_column # 列数 print(row) print(column) for r in range(2, row1): # 跳过表头,行号是从1开…

opengl计算帧率_或许是迄今为止第一篇讲解 fps 计算原理的文章吧

前言fps,是 frames per second 的简称,也就是我们常说的“帧率”。在游戏领域中,fps 作为衡量游戏性能的基础指标,对于游戏开发和手机 vendor 厂商都是非常重要的数据,而计算游戏的 fps 也成为日常测试的基本需求。目前…

041、基于CNN的样式迁移

之——基于CNN的滤镜 目录 之——基于CNN的滤镜 杂谈 正文 1.基于CNN的样式迁移 2.实现 杂谈 通过CNN的特征提取,可以实现将一个图片的样式模式特征迁移到另一张图像上。 正文 1.基于CNN的样式迁移 就是在某些层的输出上用其他的图片进行监督。 2.实现 一般来…

LeetCode 483. 最小好进制(二分查找)

文章目录1. 题目2. 解题1. 题目 对于给定的整数 n, 如果 n 的 k(k>2)进制数的所有数位全为1,则称 k(k>2)是 n 的一个好进制。 以字符串的形式给出 n, 以字符串的形式返回 n 的 最小 好进制。 示例 1&#xff…

LeetCode LCS 01. 下载插件

文章目录1. 题目2. 解题1. 题目 小扣打算给自己的 VS code 安装使用插件,初始状态下带宽每分钟可以完成 1 个插件的下载。 假定每分钟选择以下两种策略之一: 使用当前带宽下载插件将带宽加倍(下载插件数量随之加倍) 请返回小扣完成下载 n …

LeetCode LCS 02. 完成一半题目(计数+排序)

文章目录1. 题目2. 解题1. 题目 有 N 位扣友参加了微软与力扣举办了「以扣会友」线下活动。 主办方提供了 2*N 道题目,整型数组 questions 中每个数字对应了每道题目所涉及的知识点类型。 若每位扣友选择不同的一题,请返回被选的 N 道题目至少包含多少种…

摄像头图像分析目标物体大小位置_单个运动摄像头估计运动物体深度,谷歌挑战新难题...

雷锋网 AI 科技评论按:人类视觉系统有一个我们习以为然但其实极其强大的功能,那就是可以从平面图像反推出对应的三维世界的样子。即便在有多个物体同时移动的复杂环境中,人类也能够对这些物体的几何形状、深度关系做出合理的推测。然而类似的…

LeetCode LCS 03. 主题空间(广度优先搜索BFS)

文章目录1. 题目2. 解题1. 题目 「以扣会友」线下活动所在场地由若干主题空间与走廊组成,场地的地图记作由一维字符串型数组 grid,字符串中仅包含 “0"~"5” 这 6 个字符。 地图上每一个字符代表面积为 1 的区域,其中 …

SQL SERVER PIVOT 行转列、列传行

在数据库操作中,有些时候我们遇到需要实现“行转列”的需求,例如一下的表为某店铺的一周收入情况表: WEEK_INCOME(WEEK VARCHAR(10),INCOME DECIMAL) 我们先插入一些模拟数据: INSERT INTO WEEK_INCOME SELECT 星期一,1000 UNION…

mysql cluster 查看数据库表名称_MySQL Cluster如何创建磁盘表方法解读

MySQL Cluster采用一系列的Disk Data objects来实现磁盘表;接下来为您详细介绍一、概念MySQL Cluster采用一系列的Disk Data objects来实现磁盘表。Tablespaces:作用是作为其他Disk Data objects的容器。Undo log files:存储事务进行回滚需要的信息&…

(运算符) 运算符

& 运算符既可作为一元运算符也可作为二元运算符。 备注 一元 & 运算符返回操作数的地址(要求 unsafe 上下文)。 为整型和 bool 类型预定义了二进制 & 运算符。 对于整型,& 计算操作数的逻辑按位“与”。 对于 bool 操作数&am…

LeetCode 1903. 字符串中的最大奇数

文章目录1. 题目2. 解题1. 题目 给你一个字符串 num ,表示一个大整数。 请你在字符串 num 的所有 非空子字符串 中找出 值最大的奇数 ,并以字符串形式返回。如果不存在奇数,则返回一个空字符串 “” 。 子字符串 是字符串中的一个连续的字符…

mysql分页插件springboot_SpringBoot--使用Mybatis分页插件

1、导入分页插件包和jpa包org.springframework.bootspring-boot-starter-data-jpacom.github.pagehelperpagehelper-spring-boot-starter1.2.52、增加分页配置# 主键自增回写方法,默认值MYSQL,详细说明请看文档mapper:identity: MYSQL# 设置 insert 和 update 中,是…

LeetCode 1904. 你完成的完整对局数

文章目录1. 题目2. 解题1. 题目 一款新的在线电子游戏在近期发布,在该电子游戏中,以 刻钟 为周期规划若干时长为 15 分钟 的游戏对局。 这意味着,在 HH:00、HH:15、HH:30 和 HH:45 ,将会开始一个新的对局,其中 HH 用一…

LeetCode 1905. 统计子岛屿(BFS)

文章目录1. 题目2. 解题1. 题目 给你两个 m x n 的二进制矩阵 grid1 和 grid2 ,它们只包含 0 (表示水域)和 1 (表示陆地)。 一个 岛屿 是由 四个方向 (水平或者竖直)上相邻的 1 组成的区域。 任…

vue是什么软件_Angular vs React vs Vue:2020年的最佳选择是什么?

在2020年,想象没有HTML,CSS和Javascript的Web开发是不切实际的。 Javascript是Web应用程序前端开发的灵魂。 如果您登陆此页面,那么我认为您在Java语言和Java编程语言的不同框架和库之间感到困惑。企业和软件开发人员最常见的一些查询是&…

LeetCode 1910. 删除一个字符串中所有出现的给定子字符串

文章目录1. 题目2. 解题1. 题目 给你两个字符串 s 和 part ,请你对 s 反复执行以下操作直到 所有 子字符串 part 都被删除: 找到 s 中 最左边 的子字符串 part ,并将它从 s 中删除。 请你返回从 s 中删除所有 part 子字符串以后得到的剩余…

tcp长连接和短连接的区别_TCP --- 连接

一个TCP连接由4个元组组成:2个ip地址和2个端口号tcp三次握手为什么是三次握手解决历史连接问题通过三次握手才能阻止重复历史连接的初始化通过三次握手,才能对通讯双方的初始序号初始化如果只有2次握手,发送方一旦发送创建连接的请求就无法撤…

LeetCode 1911. 最大子序列交替和(动态规划)

文章目录1. 题目2. 解题1. 题目 一个下标从 0 开始的数组的 交替和 定义为 偶数 下标处元素之 和 减去 奇数 下标处元素之 和 。 比方说,数组 [4,2,5,3] 的交替和为 (4 5) - (2 3) 4 。 给你一个数组 nums ,请你返回 nums 中任意子序列的 最大交替和…