face morhper
图像变形背后的想法很简单。给定两个图像
,
我们想
通过将图像
和混合来创建中间图像
。图像的混合
和
由参数控制的
是在0和1之间(
)。当
为0时,变形
看起来像
,而当
为1 时,变形看起来
像
。天真的,您可以在每个像素上使用以下方程式混合图像

但是,使用上面的方程式将希拉里·克林顿国务卿和特德·克鲁兹参议员的图像
设置为0.5,会产生以下可怕结果。

产生的图像令人不安,但同时也会给您尖叫。恳求您在融合图像之前以某种方式对齐眼睛和嘴巴。当您尝试在不先调整思路的情况下将两种不同的政治意识形态融合在一起时,就会得到类似的令人不安的结果,但我离题了。
因此,要将图像变形
为图像,
我们需要首先在两个图像之间建立像素对应。换句话说,对于
图像中的每个像素
,我们需要找到它
在图像中的对应像素
。假设我们神奇地找到了这些对应关系,我们可以分两步混合图像。首先,我们需要计算
变形图像中像素的位置。由下式给出
(1) 
其次,我们需要
使用以下公式找到像素的强度
(2) 
而已。我们完了。现在,我们去投票给特朗普。开玩笑!就像特朗普一样,我省略了一些重要的细节。为图像I中的每个像素找到图像J中的对应点与在美国和墨西哥之间建立10英尺的墙一样困难。可以做到,但是它很昂贵,并不是真正必要的。
但是很容易找到一些点对应关系。为了使两个不同的对象(如猫的脸和人的脸)变形,我们可以单击两个图像上的几个点以建立对应关系,并为其余像素插值结果。接下来,我们将详细了解“脸部变形”的完成方式,但是相同的技术可以应用于任何两个对象。
脸部变形:逐步
可以使用以下步骤变形两个面。为了简单起见,我们将假定图像的大小相同,但这不是必需的。
1.使用面部特征检测找到点对应

让我们从获取相应点开始。首先,我们可以通过检测面部特征点来自动(或手动)获得很多点。我使用dlib来检测68个对应点。接下来,我又增加了四个点(一个在右侧耳朵上,一个在脖子上,另外两个在肩膀上)。最后,我还添加了图像的角点和这些角点之间的中间点作为对应点。不用说,可以在头和脖子周围添加更多点以获得更好的结果,或者删除手动单击的点以获得稍微差一点(但是全自动的)的结果。
2. Delaunay三角剖分
从上一步开始,我们有两组80个点-每个图像一组。我们可以计算两组中对应点的平均值,并获得一组80个点。在这组平均点上,我们执行Delaunay三角剖分。Delaunay三角剖分的结果是由80点数组中的点的索引表示的三角形列表。在这种特殊情况下,三角剖分产生了149个三角形,将80个点连接在一起。三角剖分存储为三列数组。三角剖分的前几行如下所示。
38 40 37
35 30 29
38 37 20
18 37 36
33 32 30
…
它显示点38、40和37形成一个三角形,依此类推。三角剖分显示在下面的两个图像中。

请注意,两个图像中的三角形捕获了近似相似的区域。我们从点对应开始,现在由于三角剖分,我们有了三角形(或区域)对应。
3.扭曲图像和Alpha混合
现在,我们可以智能地融合两个图像。如前所述,混合量将由参数控制
。使用以下步骤创建变形。
- 在变形图像中找到特征点的位置:在变形图像中
,我们可以
使用等式(1)找到所有80个点的位置。 - 计算仿射变换:因此我们在图像1中有一组80点,在图像2中有另一组80点,在变形图像中有第三组80点。我们也知道在这些点上定义的三角剖分。在图像1中选择一个三角形,在变形图像中选择一个相应的三角形,并计算仿射变换,该仿射变换将图像1中的三角形的三个角映射到变形图像中相应的三角形的三个角。在OpenCV中,可以使用getAffineTransform完成此操作。为每对149个三角形计算仿射变换。最后,重复图像2和变形图像的过程。
- 变形三角形:对于图像1中的每个三角形,使用在上一步中计算出的仿射变换将三角形内的所有像素变换为变形图像。对图像1中的所有三角形重复此操作以获得图像1的变形版本。类似地,获得图像2的变形版本。在OpenCV中,这可以通过使用warpAffine函数来实现。但是,warpAffine会获取图像,而不是三角形。诀窍是计算三角形的边界框,使用warpAffine扭曲边界框内的所有像素,然后遮盖三角形外部的像素。使用fillConvexPoly创建三角形蒙版。使用warpAffine时,请确保使用blendMode BORDER_REFLECT_101。与克林顿国务卿掩盖她的电子邮件相比,它掩盖了接缝。
- Alpha混合变形图像:在上一步中,我们获得了图像1和图像2的变形版本。可以使用公式(2)将这两个图像进行Alpha混合,这是您最终的变形图像。在代码中,我提供了变形三角形和alpha混合,将它们合并在一个步骤中。
脸部变形结果
应用上述技术的结果如下所示。中间的图像是左右图像的50%混合。此页面顶部的视频显示了具有不同alpha值的动画。动画是一种廉价的技巧,可以将变形中的许多缺陷隐藏起来。特德·克鲁兹(Ted Cruz)参议员会喜欢的。
大多数面部特征都很好地对齐了。脸部以外的图像部分排列得不太好,因为在该区域中对应的点较少。可以手动添加其他点来修复错位并获得更好的结果。



总结:
point 68
point 80
delaunay 149
图1三角映射
图2三角映射
比例Alpha混合
Delaunay
原文:https://www.learnopencv.com/face-morph-using-opencv-cpp-python/
--
face morhper的更多相关文章
随机推荐
- ccze - A robust log colorizer(强大的日志着色器)
这些程序遵循通常的GNU命令行语法,长选项以两个破折号(` - ')开头.选项摘要如下. -a, - argument PLUGIN = ARGUMENTS 使用此选项将AR ...
- 小顶堆第二弹-----堆降序排序(C语言非递归)
现在po一下C语言版本的,留作以后接口使用. 1 #include <stdio.h> #include <stdlib.h> #define HEAP_SIZE 100 #d ...
- 【ocata】计算节点的 neutron 报错
挂起/关闭实例时,/var/log/neutron/linuxbridge-agent.log中报错,但不影响使用 -- :: INFO neutron.plugins.ml2.drivers.age ...
- PAT_A1059
这是一道素数因子分解的问题: 1.先打印素数表出来,以便后期使用,素数表的大小就是10^5级别就可以,因为输入的数是long int(即就是int而已),大小最大21亿(10^10量级的),我们这里素 ...
- 使用wc -l 来统计代码行数
Linux使用wc来统计行数真的好用 如在当前路径下统计一共多少行代码 $ find ./ -name *.c |xargs wc -l #包括了空行 ##-l :lines 如果不包括空行 ¥fin ...
- [牛客网 -leetcode在线编程 -02] minimum-depth-of-binary-tree -树的最短深度
题目描述 题目描述 Given a binary tree, find its minimum depth.The minimum depth is the number of nodes along ...
- Ajax -异步请求 -jquery中ajax分类 -第一层 $.ajax -第二层($.get /$.post) -第三层($.getJson/$.getScript) -相应演示
Ajax 1.标准请求响应时浏览器的动作(同步操作) 1.1浏览器请求什么资源,跟随显示什么资源2.ajax:异步请求. 2.1局部刷新,通过异步请求,请求到服务器资源数据后,通过脚本修改页面中部分内 ...
- 《Exceptioning团队》第六次作业:团队项目系统设计改进与详细设计
一.项目基本介绍 项目 内容 这个作业属于哪个课程 任课教师博客主页链接 这个作业的要求在哪里 作业链接地址 团队名称 Exception 作业学习目标 1.掌握面向对象软件设计方法:2.完善系统设计 ...
- Mybatis下Oracle插入新增返回主键id
具体xml中sql是这样写,但是要注意SQ_USER.Nextval,SQ_USER是序列,你要替换下自己要进行操作的表的序列,不知道序列的话,可以sql查找下,select * from user_ ...
- Flume组件
1.什么是Flume:apache顶级项目,主要用来做数据采集.分布式.高可用,将海量日志进行采集.聚合.传输的系统.能够对数据进行简单处理在发送到接收方. 2.Flume组件:source.chan ...