换发型算法_GitHub-DylanMaengyry:yry(颜如⽟)——⼀ 颜如⽟
颜如⽟ —— python ⼈脸融合程序,可实现类似天天P图疯狂换脸、face++⼈脸融合效果磁化杯
项⽬描述
最近随着各种技术的发展,图像⽅⾯的⼈脸处理技术越来越⼴泛。各⼤相机软件都有美颜、贴图、换发型、变脸等功能。天天P图与
Face++也都推出⼈脸处理的 API,不过价格⽅⾯就有点不亲民了。于是本⼈将之前研究完成的⼈脸融合算法开源出来。
效果对⽐
国际惯例,我们看看颜如⽟与天天P图、Face++合成效果的对⽐:
注:Face++ 为调⽤其官⽹ API ⽣成的效果,天天P图则是直接使⽤该 APP ⽣成的效果
使⽤
彩灯控制电路
安装 所需库
pip install -
运⾏ ModuleTest.py 的主函数
python ModuleTest.py
瞬时速度中心⽣成的结果图⽚ output.jpg 储存在 images ⽂件中
算法详解
零、融合函数
先看看程序⼊⼝函数
core.face_merge(src_img='images/model.jpg',
dst_img='images/20171030175254.jpg',
out_img='images/output.jpg',
face_area=[50, 30, 500, 485],
alpha=0.75,
blur_size=(15, 10),
mat_multiple=0.95)
参数含义:
src_img —— 模特图⽚
dst_img —— 待融合的图⽚
out_img —— 结果图⽚输出路径
face_area —— 指定模板图中进⾏⼈脸融合的⼈脸框位置。四个正整数数组,依次代表⼈脸框左上⾓纵坐标(top),左上⾓横坐标(left),⼈脸框宽度(width),⼈脸框⾼度(height),通过设定改参数可以减少结果的⼤范围变形,把变形风险控制在⼈脸框区域
alpha —— 融合⽐例,范围 [0,1]。数字越⼤融合结果包含越多融合图 (dst_img) 特征。
blur_size—— 模糊核⼤⼩,⽤于模糊⼈脸融合边缘,减少融合后的违和感
mat_multiple —— 缩放获取到的⼈脸⼼型区域
使⽤开源 Dlib 库检测及定位(定位68个关键点)
使⽤腾讯平台的⼈脸识别及定位API (定位90个关键点)
使⽤Face++平台的⼈脸识别定位API(定位106个关键点)
本⽂采⽤的是Face++的 api,因为商⽤情况下 Face++ 定位的定数最多
// 获取两张图⽚的⼈脸关键点(矩阵格式与数组格式)
src_matrix, src_points, err = core.face_points(src_img)
dst_matrix, dst_points, err = core.face_points(dst_img)
⼆、对齐⼈脸⾓度
在待融合图⼈像不是侧脸的情况下,我们可以同过调整平⾯位置及⾓度让其与模特图的⼈脸重合
// opencv 读取图⽚
src_img = cv2.imread(src_img, cv2.IMREAD_COLOR)
dst_img = cv2.imread(dst_img, cv2.IMREAD_COLOR)
dst_img = transformation_points(src_img=src_img, src_points=src_matrix[core.FACE_POINTS],
图像采集系统
dst_img=dst_img, dst_points=dst_matrix[core.FACE_POINTS])
注:src_points 已经 dst_points 传⼊参数为第⼀步获取的⼈脸关键点矩阵
对齐采⽤“常规 Procrustes 分析法”
具体算法来源:matthewearl 个⼈博客步骤2
对齐结果:
三、再次取点后融合脸部
对步骤⼆转换后的带融合图⽚再次取关键的,然后与模特图的关键点⼀起做三⾓融合成新的图⽚
dst_img = morph_img(src_img, src_points, dst_img, dst_points, alpha)
融合结果:
具体的三⾓融合算法解说参考这篇⽂章
四、处理加⼯模特图⽚
再次对上⼀步的结果图进⾏取点,然后运⽤三⾓仿射将模特图⽚脸部轮廓、关键点变形成上⼀步得到的脸部关键点src_img = tran_src(src_img, src_points, dst_points, face_area)
处理结果:
五、将融合后的脸部贴到模特图上
最后⼀步是将融合后的新图⽚脸部区域⽤泊松融合算法贴到模特图上。泊松融合可直接使⽤opencv提供的函数
dst_img = merge_img(src_img, dst_img, dst_matrix, dst_points, k_size, mat_multiple)
def merge_img(src_img, dst_img, dst_matrix, dst_points, k_size=None, mat_multiple=None):
face_mask = np.zeros(src_img.shape, dtype=src_img.dtype)
梭式止回阀for group in core.OVERLAY_POINTS:
cv2.fillConvexPoly(face_mask, vexHull(dst_matrix[group]), (255, 255, 255))
r = cv2.boundingRect(np.float32([dst_points[:core.FACE_END]]))
center = (r[0] + int(r[2] / 2), r[1] + int(r[3] / 2))
if mat_multiple:
mat = RotationMatrix2D(center, 0, mat_multiple)
face_mask = cv2.warpAffine(face_mask, mat, (face_mask.shape[1], face_mask.shape[0]))
if k_size:
face_mask = cv2.blur(face_mask, k_size, center)
return cv2.seamlessClone(np.uint8(dst_img), src_img, face_mask, center, cv2.NORMAL_CLONE)函数⽰意图: