0%

15行代码实现给图片戴口罩 - Python

万万没想到,疫情如此严重,只是反应迟了一点,发现口罩已经买不到了…只好写段代码,自动给图片戴上口罩,聊以慰藉。

我们先来看下原始图片和效果图片(图片是网上找来的,不追星,如有冒犯请见谅。):

技术方面主要用到人脸识别,首先安装依赖:

1
2
3
pip install face_recognition
# face_recognition是一个开源的人脸识别框架,可以识别人脸的128个关键点
# Windows下推荐使用anaconda安装,不然安装dlib依赖可能会遇到各种莫名其妙的问题

OK,上代码:

1
2
3
4
5
6
7
8
9
10
11
12
from PIL import Image, ImageDraw
import face_recognition
import math
image = face_recognition.load_image_file("cai.jpg")
face_landmarks_list = face_recognition.face_landmarks(image)
pil_image = Image.fromarray(image)

for face_landmarks in face_landmarks_list:
d = ImageDraw.Draw(pil_image)
# 画一下人脸识别效果
for facial_feature in face_landmarks.keys():
d.line(face_landmarks[facial_feature], width=5)

来看一下人脸识别的效果:

嗯,还是很准确的,接下来就给他戴上口罩:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    # 首先确定口罩大小,下面四行注释是我找到的四个关键点(上图可见)
# d.text(face_landmarks['chin'][3], 'l')
# d.text(face_landmarks['chin'][13], 'r')
# d.text(face_landmarks['chin'][8], 'b')
# d.text(face_landmarks['nose_bridge'][2], 'u')
mask_image = Image.open('mask.png')
mask_length = face_landmarks['chin'][13][0]-face_landmarks['chin'][3][0]
mask_height = face_landmarks['chin'][8][1]-face_landmarks['nose_bridge'][2][1]
mask_image = mask_image.resize((mask_length, mask_height))
# 口罩的角度也要随着脸型调整一下
rotation = math.atan2(face_landmarks['nose_bridge'][3][0] - face_landmarks['nose_bridge'][0][0], face_landmarks['nose_bridge'][3][1] - face_landmarks['nose_bridge'][0][1])*100
mask_image = mask_image.rotate(rotation)
# 因为素材是N95口罩,所以要相应的处理下y轴的坐标
pil_image.paste(mask_image, (face_landmarks['chin'][3][0], face_landmarks['chin'][3][1] - int(mask_height/2)), mask_image)

pil_image.show()

当然,也可以给一群人都戴上口罩,上面只是很简单的一个脚本,优化空间还有很多,比如口罩的旋转角度算法、低分辨率下的人脸识别等等。

最后呼吁大家提高对本次疫情的重视程度,种种迹象表明这次比非典要严重很多很多。

希望大家平安无事!早日战胜疫情!加油!