万圣节教你用 OpenCV Remix 一张 n 合1脸

本文深入探讨了如何使用ImageMorphing技术合成两张人脸的平均脸,并通过Delaunay三角剖分和仿射变换实现了人脸对齐。此外,还介绍了如何通过叠加多张人脸来获得一组人的平均面貌。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

640?wx_fmt=gif


大家好,我是为人造的智能操碎了心的智能禅师。

在这个多逝之秋,禅师要哀悼一下金庸先生。昨晚上惊闻噩耗,顿感无比感慨。金庸先生的武侠,影响了好几代人。沧海一声笑,滔滔两岸潮。浮沉随浪只记今朝,先生一路走好!

今天是万圣节?,就是国外的中元节。可能是唯一一个没有被过程情人节、能让人体会真正快乐的,年轻人中流行的节日。禅师在这里,祝愿大家每年万圣节都是 Coser,不被 Cos。?

每年万圣节,大家一般都是化妆成?啊、?啊,?啊……反正是怎么?怎么丑怎么来。

今年禅师就想,老是这些东西也没什么新鲜的。昨晚上打开柜子,看着里面躺着去年买的?面具,前年买的?面具,大前年买的?,?,?……突然有一个大胆的想法:

要是所有凶恶的脸,用 CV 给合成为一张量,是不是就能出现一张独一无二、天下第一凶恶的脸呢?

缘,妙不可言。

咱们的特约作者李烨老师还真就有一篇 OpenCV + dlib + Caffe 合成人脸的文章。

顺便推荐一下 Google 的万圣节 Doodle 对战小游戏,可以和网友 battle。下面是禅师的对战视频:

全文大约2000字。读完可能需要好几首下面这首歌的时间

?

640?wx_fmt=png

解决方案

通过 Image Morphing 技术,给定两张图片 I 和 J ,就可以叠加(或者叫做混合)I 和 J 来获得一张中间状态的图片 M。

I 和 J 的叠加由一个参数[0,1]区间内的参数 alpha 来控制。当 alpha=0时,M 就等同于 I,而 aphla=1时,M 就为 J。

换言之, M 中的每一个像素 M(x,y),都可以通过这样一个公式来得到它的值:

M(x,y) = (1 – alpha)·I(x,y) + alpha·J(x,y)

当 alpha=0.5的时候,I 和 J 就五五开,平均贡献了 M。如果 I 和 J 是两张人脸照片的话,M 自然也就成了它们的“平均脸”。

看起来好容易哦,那我们赶紧找两张照片来试试吧!就用这两张:

640?wx_fmt=jpeg

这两张照片alpha=0.5后直接叠加的结果是这样的:

640?wx_fmt=jpeg

从这张“重影图”上不难看出来,之所以这样,是因为最基本的五官都没有对齐。虽然差强人意,但还算的上比较顺利吧。接下来我们把把两个人的眼睛和嘴对齐,看看是什么效果。

对齐人脸

要想对齐两张人脸,需要建立两张照片中像素的对应关系。

对 I 中的某一个像素点(xi,yi),找到它在 J 中的对应点 (xj,yj),进一步找到 M 中这两个点叠加之后所处位置(xm,ym)。再用下面算式1(记住这个标号,后面有用)计算出 M 中对应点的像素值:

xm = (1-alpha) · xi + alpha · xj

ym = (1-alpha) · yi + alpha · yj

将上面的过程运用到整幅画每一个像素点上算式2(记住这个标号,后面有用):

M(xm,ym) = (1 – alpha)·I(xi,yi) + alpha·J(xj,yj)

接下来,可以把一张人脸分割成若干三角形的区域,叠加两张脸上对应的三角区域。

具体方法如下:

1. 获取人脸特征

我们先在每张面孔上获取68个面部基准点?。

640?wx_fmt=jpeg

2. Delaunay 三角剖分

在获得了68个面部基准点之后,我们结合人脸所在的矩形的四个顶点和每条边的中心点,将人脸所在的矩形分割成如下图所示的三角形的组合。

640?wx_fmt=jpeg

3. 基于Delaunay剖分三角形的仿射变换

得到这些Delaunay剖分三角形后,再分别对齐各个区域,对其中像素值进行平均。

使用前述的算式1,根据图像I和图像J中已经获得的76个点,在叠加的结果图像M中找到76个点(xm, ym)

从图像I中选取一个三角形 ti,在 M 中找到对应区域 tm,通过 ti 三个顶点到 tm 三个顶点的映射关系来计算 ti 到 tm 的仿射变换。同理计算出tj到tm的仿射变换。 

重复这个过程,处理图像 I 中的每一个三角形,得到一个扭曲的(warped)图像 I'。用同样的方法处理图像 J,获得扭曲的图像 J'。

得到了扭曲的图像 I'和图像 J'。这两个图像就可以直接使用算式2进行叠加了。最后得到叠加结果:

640?wx_fmt=png

叠加人脸

算式2用于叠加2张人脸,在alpha=0.5时求取的是两张脸的平均。

那么我们把算式推广一下,从图像I和图像J推广为图像I_1, I_2, I_3, ..., I_n;令 alpha=1/n;则算式2变形为如下:

M(xm,ym) = 1/n · [I_1(xi_1, yi_1) + I_2(xi_2, yi_2) + ... ... + I_n(xi_n, yi_n)]

由此,我们也就得到了n张脸的平均。

用这个方法,我们可以得到6位美国总统的平均脸:

640?wx_fmt=jpeg

他们平均之后的样子是这样的:

640?wx_fmt=jpeg

代码实现

代码下载:

https://github.com/juliali/AverageFace

之前是从描述角度来讲解平均脸原理。现在,我们来看看code。

[Code -1 ] 使用dlib来进行人脸识别和人脸特征点的提取

640?wx_fmt=png

[Code-2] 根据特征点获得Delaunay剖分三角

640?wx_fmt=png

[Code-3] 计算仿射变换

640?wx_fmt=png

[Code-4] 通过仿射变换扭曲Delaunay剖分三角形

640?wx_fmt=png

区分性别

经过尝试,合成后的脸怎么看都感觉是男的。至于如何训练模型来区分性别,扫描下方二维码来获取答案吧 ?

640?wx_fmt=png

参考资料

【1】 AverageFace 代码、模型及样例图片

【2】 FaceGenderClassification 配置文件及命令

【3】 原始的性别分类模型

【4】Delaunay三角剖分原理


640?wx_fmt=png

幸福
无非就是
我  AI  你


640?wx_fmt=gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值