换脸特效

    xiaoxiao2021-04-15  218

    目录

    摘要

    实验步骤

    关于应用到视频上


    摘要

    抖音上很多脸部特效很好玩,都可以一一实现来玩玩。下面介绍的是换脸特效。效果图如下,

    这是最近比较流行的一个效果。其实很简单。

    原文:http://matthewearl.github.io/2015/07/28/switching-eds-with-python/,不过需要对其中代码进行修改。

    原文给的是人脸,上图用的是狗脸融合,可以通过自己标准68个点,对应人脸的位置。

    实验步骤

    程序整体思想分为以下几个部分,

    (1)使用Dlib进行人脸检测和68个关键点定位

    dlib确定68个点是通过 “ 用回归树,一毫秒搞定人脸对齐。”, One Millisecond Face Alignment with an Ensemble of RegressionTrees,算是一种比较老的方法了。但是效果很好。

    (2)进行旋转,缩放,平移等变换,即aligement操作,使得第二个图和原始图相互吻合

    融合的效果的好坏是两个图片的分辨率,人脸是否矫正姿势,这是一部分是我加上去的。人脸姿势矫正是通过几个点来搞定的,思想是人的眼睛和鼻梁是垂直关系,鼻梁应该垂直于水平框,然后进行下一步放射,效果更好。

    这里使用的是普式变换(Ordinary Procrustes Analysis),最终结果是要使得变换过程满足下面式子最小化,简单的说,就是第一个图的68个点经过仿射变换(warp_affine)后,和第二个图的68个点的距离最小。

     

    其中,R是2*2的旋转变换矩阵,S是一个线性缩放矩阵,T是一个二维平移向量,p,q分别为上面计算的2个人的68个点。

    那么问题来了,现在只已经2个图的68个点,如何求解上面的S,R,T呢,这里使用奇异值SVD分解( Singular Value Decomposition),从而求出R。

    U, S, Vt = numpy.linalg.svd(points1.T * points2) R = (U * Vt).T

    最终返回变换矩阵

    return numpy.vstack([numpy.hstack(((s2 / s1) * R, c2.T - (s2 / s1) * R * c1.T)), numpy.matrix([0., 0., 1.])])

    有了该变换矩阵,就可以使用opencv的warpAffine函数,将第二张图片变为和第一种图片同样的空间位置。

    (3)将第二个图的颜色匹配到第一个图

    如果直接将第二个图覆盖到第一个图,会发现,在边缘地方2个人的肤色和关照等会出现明显的区别,这里使用了颜色平衡( RGB scaling colour-correction)的方法,这里主要进行的操作就是,分别对图片1,2进行高斯滤波,生成高斯滤波后的1,2图片,然后对第二个图片除以自己的高斯滤波后的图片,再乘以第一个图片的高斯滤波后的图片,从而生成最终变换后的图片。

    这里高斯核的选择是一个重点,太小的话,会将第一个图的特征显示到第二个图上,太大又会将人脸以外的区域覆盖到第二个图上,这里选取0.6倍的瞳距。

    im1_blur = cv2.GaussianBlur(im1, (blur_amount, blur_amount), 0) im2_blur = cv2.GaussianBlur(im2, (blur_amount, blur_amount), 0) # Avoid divide-by-zero errors. im2_blur += 128 * (im2_blur <= 1.0) return (im2.astype(numpy.float64) * im1_blur.astype(numpy.float64) / im2_blur.astype(numpy.float64))

    (4)将第二个图的人脸特征,通过使用掩码的方式混合融合进第一个图

    这里主要是要生成一个掩码,通过该掩码来进行图像融合,在掩码为1的地方显示图像2,掩码为1的地方显示图像1,掩码0-1之间的地方进行融合。

    生成掩码的思路为,先通过人脸关键点生成一个凸包(convexHull),然后扣出凸包中的像素,进行高斯滤波,生成mask,然后将1,2两幅图的mask进行max操作,生成最终的mask。

    最终通过一个阿尔法变换,用2个图片生成最终想要的结果。

    output_im = im1 * (1.0 - combined_mask) + warped_corrected_im2 * combined_mask

    关于应用到视频上

    1 用C++写代码,

    2 不用68个点,取其中主要的点,减少计算量。

     

     

     


    最新回复(0)