浏览量: 125 次浏览

利用贴图实现的人脸特效

2019年5月19日 0 作者 Nie Hen

随着人脸检测技术的不断成熟,人脸特效也逐渐进入我们的生活中,各个美颜相机软件,p图软件都能够检测到人脸,添加人脸特效。最近尝试着做了一下,一种比较简单的人脸特效,利用贴图来实现的。

这是效果图
enter description here

思维导图

enter description here

下面根据思维导图 讲解具体的实现方法
完整代码链接

制作贴图

这个可以根据自己的需求使用ps制作,或者网上下载。
网上下载的有些贴图,因为有背景颜色,或则其他原因,无法获取到想要的那部分。
比如会这样在这里插入图片描述 贴图处理后在这里插入图片描述 添加后在这里插入图片描述
下面讲解使用PIL消除掉背景色的具体实现方法。
利用到Alpha通道
一个图像的每个像素都有 RGB 三个通道,后来 Alvy Ray Smith 提出每个像素再增加一个 Alpha 通道,取值为0到1,用来储存这个像素是否对图片有「贡献」,0代表透明、1代表不透明。也就是说,「Alpha 通道」储存一个值,其外在表现是「透明度」。
把图像中特定颜色的A值转换为0,就可以把背景色消除掉,应用到下一步

# #---------  This function clears the specified color to be empty
from PIL import Image
img = Image.open('maozi-1.png')
img = img.convert("RGBA")  #代表Red(红色) Green(绿色) Blue(蓝色)和 Alpha的色彩空间
datas = img.getdata()

newData = []
for item in datas:
    if item[0] == 0 and item[1] == 0 and item[2] == 0: #背景色为黑色 的像素点
        newData.append((0, 0, 0, 0))  # 把A值设置为0
    else:
        newData.append(item)

img.putdata(newData)
img.save("img2.png", "PNG")  # 保存下来

人脸检测获取到关键点

我使用到的是face_recognition 感觉效果还可以,当然也可以使用face++的效果会更好些,这里不再介绍其他使用方法,想要研究的可以到我博客中其他文章找其他模块获取人脸关键点的方法。

image = face_recognition.load_image_file("../face_photos/yiqi.jpg")
face_landmarks_list = face_recognition.face_landmarks(image) #人脸关键点信息
facial_features = [
        'chin',  # 下巴
        'left_eyebrow',  # 左眉毛
        'right_eyebrow',  # 右眉毛
        'nose_bridge',  # 鼻樑
        'nose_tip',  # 鼻尖
        'left_eye',  # 左眼
        'right_eye',  # 右眼
        'top_lip',  # 上嘴唇
        'bottom_lip'  # 下嘴唇
    ]  #这些参数都在face_landmarks_list 中可以找到

计算人脸倾斜角度

通过鼻梁来计算人脸倾斜角度应该算是一种比较简单的方法,也是相对比较准确的。
但是鼻梁上的关键点连一块不一定是一条直线,这里需要用一下拟合的方法,把上面的所有关键点拟合成一条直线。
使用scipy中的optimize.curve_fit 来拟合直线,并计算出斜率和截距

for nose in face_landmarks['nose_bridge']:
        nose_x.append(nose[0])
        nose_y.append(nose[1])
 A1, B1 = optimize.curve_fit(f_1, nose_x, nose_y)[0]  #拟合出鼻梁所在的直线 A1为斜率 B1为截距

其中里面的参数f_1 需要写一下

def f_1(x, A, B):
    return A*x + B

获取到了斜率就可以通过斜率来计算倾斜角度
利用math.atan() 函数先计算弧度 再用公式计算角度

radian = atan(A1)  # 利用反三角函数 计算出角度的弧度制
angele =  radian*180/(3.14)  # 计算出角度

改变贴图的尺寸和倾斜度

贴图的大小一定要跟人脸大小相匹配,所以贴图的大小是由人脸的大小来决定的。
贴图的长/人脸的长 = 贴图的宽/人脸的宽

map_setsize_h = int(map_h/map_w)*face_w
map_set = map.resize((face_w,map_setsize_h)) #设定logo大小  宽, 高

人脸倾斜,贴图当然也要跟着倾斜。

map_set = map_set.rotate(angele,expand = 1)

其中的参数 expend需要设置,如果不设置默认为false ,图片旋转会按照原尺寸大小,会有损失,而设置为True则图片会随着旋转而改变尺寸大小。
expend为False时,旋转图片就会这样损失一部分,按照原尺寸变化。enter description here
expend=True的时候,图片旋转,尺寸会随之发生变化!enter description here

计算贴图位置

这个要根据不同的贴图要计算,不过大致思路是一样的 。
下面以制作帽子贴图为例。
因为关键点没有额头和发际线初,所以需要计算,根据人脸比例,人脸横着分可分为三部分,
enter description here
这样从眉毛的中心位置和下巴的最低点可以计算出额头的竖直高度。
获得数值高度后,通过之前鼻梁拟合出的那条线,就可以计算出发际正中间的点的坐标。
enter description here
(简单画的一个图,不是很准确)
线1那条线是 根据计算得出的发际线的数值位置 线2就是鼻梁拟合出的那条线。
两条线相交的位置就是发际的中心点,也就是点3.
获取到的这个点也是贴图旋转后logo的斜着的中心点
enter description here
上面图中 红色虚线是旋转后贴图的图片,根据中心点位置 利用初中学的几何知识就可以求出红色虚线左上角点的位置。

把贴图放到相应的位置

使用PIL库中paste函数实现图片的叠加。 其中mask参数要写上,不然贴图的背景还是会显示出来。

pil_image.paste(map_set,(map_setx,map_sety),mask= map_set)  #mask 能够去掉掩码

over

到这步利用贴图实现的人脸特效就完成了! (原创)
代码链接 https://github.com/niehen6174/face_detection_and_recognition/tree/master/%E4%BA%BA%E8%84%B8%E7%89%B9%E6%95%88

人脸识别模块介绍链接地址
http://niehen.cn/category/face-reco/

欢迎加入人工智能-人脸识别 技术交流群 894243022
点击下面图片即可加群
人工智能-人脸识别
该文章有使用链接,如有侵权还请见谅。使用本文章或代码还请声明。
参考 https://github.com/niehen6174/faceai/blob/master/faceai/compose.py

原文链接