查看原文
其他

求求你给你的微信头像戴个圣诞帽吧!

刘早起 CSDN 2021-11-11

作者 |  刘早起  责编 | 张文
头图 | CSDN 下载自视觉中国
来源 | 早起Python(ID:zaoqi-python)
圣诞节快到了,每年一到圣诞节就会有很多人的头像上多了一顶小红帽。
那么你有想过如何用 Python 去实现吗?
本文将手把手教你如何用 Python 为你的微信头像添加一顶圣诞帽,并结合我们之前讲过 PySimpleGUI,做成一个带有 GUI 的小程序,先看效果:

本次主要分为两个部分讲解:
  • 用 opencv 对头像添加圣诞帽
  • 结合 PySimpleGUI 制作人性化圣诞帽添加软件
主要涉及的 Python 模块有:
  • PIL
  • PySimpleGUI
  • cv2
  • os
在开始之前,你需要使用 pip 对相关依赖库进行安装
pip install pillow #这是对模块PTL的安装pip install opencv-python #这是对cv2的安装pip install os pip install PySimpleGui
  

利用 opencv 对头像处理

本文用到的圣诞帽,是.png 格式的,如下

为了识别照片,我们需要安装一个 OpenCV 的内置人脸识别插件,安装步骤:
用浏览器打开网址 opencv.org---进入 Releases---下载对应版本的 OpenCV
和以前一样,我们先看本节全部代码,然后进行讲解👇
import cv2from PIL import ImagepersonPath = '3.jpg' #头像hatPath = 'sheng.png' #圣诞帽personImg = cv2.imread(personPath)face_haar = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')#存放的绝对路径faces = face_haar.detectMultiScale(personImg, 1.1,5)personImg = Image.open(personPath)personImg = personImg.convert('RGBA')hatImg = Image.open(hatPath)hatImg = hatImg.convert('RGBA')for face_x,face_y,face_w,face_h in faces: face_x -= face_w-180 face_y += face_h-250 face_w *= 1 face_h *= 1 hatImg = hatImg.resize((face_w, face_h)) bg = (face_x, face_y - face_h + 100 , face_x + face_w, face_y + 100 ) personImg.paste(hatImg, bg, mask = hatImg)#将调整好的帽子贴上去personImg.save('addHat.png')
下面对代码进行讲解。
首先,引入两个模块,用 cv2.imread(personPath)来读取相对路径下的图片。
cv2.imread('图像路径','读取方式'):默认为 cv2.imread_color 以彩色图像模式读取。
cv2.CascadeClassifier('分类器的路径'):简单来说就是做人脸检测的一个必备方面,专业名词叫做级联分类器。这个分类器到目前版本容纳了 Haar 特征器和 LBP 特征分类器两个分类器。这次我们使用常规用的 Harr 特征器
Haar 特征分类器就是一个 xml 文件,是 OpenCV 官方训练好的检测器,它能反应图像的灰度变化,以像素分模块求差值的一种特征
下面我们讲讲它的路径
在我们准备工作中我们在 OpenCV 的官网下载了人脸识别的插件。以安装在 D盘为例:Harr特征分类器就在我们的D:\opencv\opencv\sources\data\haarcascades\haarcascade_frontalface_default.xml
注意:在第 6 行代码中,我们调用这个特征器的路径最好使用绝对路径!上述代码只是演示
关键代码就是 detectMultiScale(image,scaleFactor,minNeighbors):检验出图片中的所有人脸,并以向量类型保存各个人脸的位置和大小,最后用矩形 Rect 类表示,该函数由分类器((也就是上述的 Haar 特征分类器))的对象进行调用。
其中参数如下:
image 是我们要做人脸检测的图片。
scaleFactor 表示在前后两次相继的扫描中,搜索窗口的比例系数。默认为 1.1即每次搜索窗口依次扩大 10%;
minNeighbors 表示构成检测目标的相邻矩形的最小个数(默认为 3 个)。
而后就是我们常见的用 Pillow 模块打开两张图片,不过这次的打开方式是以 RGBA 模式打开,即四通道模式(A 指透明度)
最后一个 for 循环就是读取用 cv2 解析出来的帽子 faces 参数。这里有趣的一点是,cv2 做人脸识别后,会在两眼之间画一条线,并以中间为原点,做 x 和 y 轴建立坐标系。最后调节 Pillow 解析出来的帽子 x 和 y 位置,摆到人头上方。所有这个方法对正脸敏感,对侧脸不太友好
personImg.save('addHat.png') 表示存储添加圣诞帽后的照片。

GUI 框架整合

现在我们在上一节的基础上,将圣诞帽添加与 GUI 框架进行整合,还是先上代码之后拆分讲解
import PySimpleGUI as sgimport os.pathsg.change_look_and_feel("BrightColors")file_list_column = [ [sg.Submit('Go',tooltip='按下面的要素添加圣诞帽',size=(15, 1)), sg.Cancel(size=(15, 1))], [ sg.Text("图片位置"), sg.In(size=(25, 1), enable_events=True, key="-FOLDER-"), sg.FolderBrowse('浏览'), ], [ sg.Text("帽子宽度"), sg.In(size=(25, 1), enable_events=True, key="hat-w"), ], [ sg.Text("帽子高度"), sg.In(size=(25, 1), enable_events=True, key="hat-h"), ], [ sg.Text("帽子横移"), sg.In(size=(25, 1), enable_events=True, key="hat-x"), ], [ sg.Text("帽子纵移"), sg.In(size=(25, 1), enable_events=True, key="hat-y"), ], [ sg.Listbox( values=[], enable_events=True, size=(40, 20), key="-FILE LIST-" ) ],]image_viewer_column = [ [sg.Text("从左边图片列表中选择一张图片:",size=(60, 1),key = "notice")], [sg.Text("左边的四个参数调节是在上面的参数基础上进行加减乘除;其中宽度和高度调试单位为个位数(需要大于0且是整数),横纵移动调试单位可任意调",size=(50, 3), key="-TOUT-")], [sg.Image(key="-IMAGE-")],]layout = [ [ sg.Column(file_list_column), sg.VSeperator(), sg.Column(image_viewer_column), ]]window = sg.Window("圣诞帽添加软件", layout)while True: event, values = window.read() if event == "Cancel" or event == sg.WIN_CLOSED: break if event == "-FOLDER-": folder = values["-FOLDER-"] try: file_list = os.listdir(folder) except: file_list = [] fnames = [ f for f in file_list if os.path.isfile(os.path.join(folder, f)) and f.lower().endswith((".jpg", ".png")) ] window["-FILE LIST-"].update(fnames) elif event == "-FILE LIST-": try: filename = os.path.join( values["-FOLDER-"], values["-FILE LIST-"][0] ) window["-TOUT-"].update(filename)
except: pass elif event== "Go" : personPath = filename ''' 圣诞帽添加部分 ''' window["notice"].update() window["-IMAGE-"].update(filename='addHat.png')window.close()
代码解析。当然在做 PySimpleGUI 之前继续唠叨基本步骤:
Import   Create some widgets Create the window Create the event loop
由于这个 GUI 框架是进阶篇中的图片查看器的改进版,对 loop 事件循环做了改动和添加一些文本框,并没有增加新的元素,键的使用也是和往常一样,所以这里就不再介绍元素和键了。
这里我们 layout 的摆放思路如下:一个圣诞帽添加键、一个退出程序键、4 个文本框来调节图片中的圣诞帽、一个列表箱子装路径下的所有图片、一个图片显示框、几条用于提示用户的文本框。按照这个思路,我们就有了 while 循环上面的代码编写。
接着是 loop 事件循环:这里我们以 Go 键触发圣诞帽添加,所以我们以这个按钮为第一个主 if 元素。
在按钮 Go 触发前我们需要进行两个判断:
  1. 文本框没有输入任何东西,
  2. 文本框输入的东西。如果是前者,我们直接调动添加圣诞帽的程序(默认参数)并且在图片上方显示 4 个参数(x,y,w,h),即坐标和帽子大小。


如果是后者的话,我们会让添加圣诞帽程序中的 4 个参数在原基础上加减乘除用户输入的数字,并在图片上方显示最终的 4 个参数。
最终效果如下:


打包
最后简单讲一下如何将上面的程序打包为 exe 格式,让没有 Python 环境的用户也能使用,首先下载 pyinstaller 模块
pip install pyinstaller
如果你的上述项目代码文件命名为:hat.py。那么你要用下面命令在 cmd 窗口进行打包
pyinstaller hat.py
打包过程会有点慢。成功后,在 py 文件所在文件夹找到一个 dist 的子文件夹。进去之后,找到 pachong.exe 文件并运行它即可。文件夹里附带了很多文件,你可以删除它。
如果不打包的话,先把圣诞帽的图片(png格式)和代码程序放在相同路径下。
进到软件后先点击浏览按钮选择图片存储路径(注意:路径内不能出现中文,只能英文+数字,这可能是因为 Python 中的 OpenCV 库的 bug)。完毕后就可以看到下方所在文件夹的全部 .jpg 和.png 文件。点击一个你想要添加圣诞帽的图片,再按 Go 按钮,在右边的图片框中就会刷新已经戴上帽子的头像!同时,在程序的路径下也会有这张图片的.jpg 格式文件。
图片框中除了图片还有 4 个参数,4 个参数的作用就是调节帽子大小和位置。因为每张图片不同,所以帽子会出现大小不一、偏移的情况。而后,你就需要在左边的 4 个输入框中输入参数来调试(4 个输入框是在原参数基础上进行数乘运算),以达到帽子的最佳效果,如果超出范围,命令框会提示错误。输入后还是一样按 Go 键,结束按 Cancel 键。
以上就是本文的分享,你可以在本文的基础上进行修改来实现不同的效果,希望能给你一点帮助!


更多精彩推荐

计算机巨星陨落!图灵奖得主 Edmund Clarke 因感染“新冠”逝世

Github 超 20000 Star,最火开源视频库 FFmpeg 这 20 年!

跨平台将终结

曾被“劝退”的 C++ 20 正式发布!

最令人讨厌的编程语言:C++ Java 上榜

Rust 2020 调查报告出炉,95%的开发者吐槽Rust难学

从“卡脖子”到“主导”,国产数据库 40 年的演变!

: . Video Mini Program Like ,轻点两下取消赞 Wow ,轻点两下取消在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存