作者 |  刘早起  责编 | 张文

头图 | 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 年的演变!
Logo

20年前,《新程序员》创刊时,我们的心愿是全面关注程序员成长,中国将拥有新一代世界级的程序员。20年后的今天,我们有了新的使命:助力中国IT技术人成长,成就一亿技术人!

更多推荐