圣诞节,给你的照片戴个帽子

前言

圣诞节来了,听说前两天有不少同志被一则“票圈发自己照片并@微信官方,就可收到带圣诞帽的照片”的消息骗了,在这里我就用python 的人脸识别模块写个小应用,自动给你的照片带帽。

之前看,已经有不少大神实现了这个功能,但是看下来,采用的方法不是openCV(觉得识别准确度较低),就是dilb(准确度可以,但代码太长),这次我使用的是前面讲过的face_recognition,虽然这货也是基于dilb的,但是好用啊!感受下:

img


环境

  • Python 3.6.1
  • Windows 7 64位
  • PyCharm 2017.1.4

策略

库的安装

  • face_recognition(之前说过说过,它是基于dlib的人脸检测,比OpenCV更好用)

    ageitgey/face_recognition

    安装:

    1
    pip install face_recognition

    如果安装过程中出现问题,99%都是安装依赖的库时出现了问题,这货安装依赖较多:boost(boost_python),cmake,dlib这几个依赖和库,中间出现任何问题都可以通过Google解决(回头我写篇帖子吧这个坑填上)。

  • PIL库

    安装:

    1
    pip install pillow   #PIL库

思路

准备两张图,一张头像,一张帽子。先face_recognition人脸识别定位图片中的人脸,得到人脸范围坐标;再根据这个坐标确定帽子放置的坐标;最后将两张图片拼接后输出。(需要注意的是,帽子是不规则图像,除了主体外背景应该是透明的,因此必须是四通道png格式)。

img

代码

我的代码注释还是比较清晰的,应该基本都能看懂:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from PIL import Image
import face_recognition

# 头像图片的路径
img_path = "***********/test.jpg"

image = face_recognition.load_image_file(img_path)
face_locations = face_recognition.face_locations(image)
# 打印发现了几张脸
print("Found {} face(s) in this photograph.".format(len(face_locations)))

# 头像图像数据读入human_img中,并转换为四通道RGBA模式
human_img = Image.open(img_path)
human_img = human_img.convert("RGBA")

# 帽子图像数据读入hat_img中,并转换为四通道RGBA模式
hat_img = Image.open("./hat.png")
hat_img = hat_img.convert("RGBA")
proportion_hat = hat_img.size[1] / hat_img.size[0] # 帽子长宽比(高/宽)

至此,我们已经通过人脸识别得到了头像图片中的face_locations人脸数据列表,并且将头像图像数据human_img和帽子图像数据hat_img读入,同时得到了proportion_hat帽子长宽比(高/宽),待后续调用。

接下来遍历每一张face_locations

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
for face_location in face_locations:            # 对于每张脸
top, right, bottom, left = face_location # 得到 top, right, bottom, left
top -= 0 # 帽子相对与人脸框上线的偏移量
print("A face is located at pixel location Top: {}, Left: {}, Bottom: {}, Right: {}".format(top, left, bottom, right))

head_h = bottom-top # 脸部高度
head_w = right-left # 脸部宽度

factor = 1.5 # 帽子缩放因子
hat_w = int(round( head_w * factor))
hat_h = int(round( hat_w * proportion_hat))

# 调整帽子的大小
hat_img = hat_img.resize((hat_w, hat_h))
# 将帽子图像作为顶部图层图像
hat_region = hat_img
#hat_region = hat_region.rotate(6)

# 确定底部图层(头像图片)被覆盖的区域(就是帽子放置区域)
axis = 0.38 # 帽子穿戴轴线位置
offset = int(round( ( hat_w * axis ) - ( head_w * 0.5 ) ) ) # 偏移量
human_region = ( left - offset , top - hat_h , left - offset + hat_w , top )

# 把顶部图层与底部图层拼接
human_img.paste(hat_region, human_region,mask=hat_img)

# 完成输出
human_img.show()

帽子相对与人脸框上线的偏移量,帽子缩放因子factor 和 帽子穿戴轴线位置axis是可人为调整的参数。

在这里解释下第21行偏移量offset的计算方法:

img

所以

1
offset = ( hat_w * axis ) - ( head_w * 0.5 )

但是,最后被覆盖的区域human_region的输入数值必须是int,因此所有的计算结果都要先四舍五入round()后再int()

最后:

img

img

img

img

用钱砸我,不要停!