以前在论坛、微博经常看到一张脸,五官长得像A,脸型似乎又是B,觉得很有意思。

比如像这张图片。这张图片应该是网友用Photoshop完成的,他们取了郭大爷的五官,放在金元帅的脸上,在把边缘处理平滑。

而上面这张图片是另外一种效果,它不仅改变了五官,连脸型轮廓也一起改变了。这种技术称为face morphing,这篇随笔就聊一聊它吧。

Morphing是指把一张照片变换成另一张照片,中间的变换过程如行云流水一般自然。

Cross-Disolve

最方便的方法是像素值叠加,第一幅照片的像素值乘以系数k,加上第二幅照片的对应像素值乘以系数(1-k)。这个方法尽管操作方便,但是效果并不好。首先,要把两幅照片的尺寸调整到一样大小,然后图像中主要内容的位置也应该保持一致,否则直接叠加会形成虚影。

Feature-based Morphing

Beier和Neely对这个方法做了改进,他们提出了一种基于特征的图像变换新方法。

假设目标图像里有一条直线PQ表示施瓦辛格的鼻梁,在源图像里小布什的鼻梁是P'Q'。那么我们就可以得到一个函数对应关系P'(x,y) = f(P(x,y)), Q'(x,y) = f(Q(x,y)). 而图像里的其它任意点X则可以根据PQ和P'Q'的关系来推算。

如果只用这一对特征线段来计算,那么在线段附近的区域可以很好的预测,稍远的区域就难以估计了。于是,可以选择多条特征线段,比如眼眶、发际线、下巴、领口等区域。多对线段和一对线段的方法类似,根据前面一对特征线段的方法,点X对每一对线段PiQi都计算得到一个点Xi,同时按照点X和线段PQ距离的远近得到一个权重值wi,距离越远权重越小。最后,X= Σwi*Xi。对于照片上的每一个像素X(x,y)都做这个运算,就得到了合成图像。

Mesh-based Morphing

另一种方法是基于网格的变换,它的思路就是在源图像和目标图像上标注若干对应的特征点,按照特征点把整张图像分割成若干块三角形区域。为保证五官在变换中的完整,五官和脸的轮廓应该多放置特征点,但是过多的特征点又会使运算速度降低。图像A的特征点数目和图像B特征点的数目是一致的,所以可以按照PC = α*PA + (1-α)*PB 的公式融合生成特征点在新图像中的位置。α∈[0,1]表示图像A对新图像的贡献率,α=1时新图像就是图像A。

下一步,用inverse warping的方法,找出图像C的点在图像A和图像B的对应位置。用插值的方法求出在图像A和图像B的像素值。同样按照PC = α*PA + (1-α)*PB 的公式将两者混合。

上面三张照片是α=0.25, 0.56, 0.75时的效果。

比较

Cross-Disolve方法最简单,但是效果不好。Feature-based Morphing方法直观,容易理解,实现也比较方便,但是如果取得特征线段不好,会有“意外效果”出现。Mesh-based Morphing方法人工选择特征点的过程略微复杂,但是效果比较好。

附Matlab代码:

A = imread('imA.jpg');
height = size(A,1);
width = size(A,2);

imshow(A);
[xA,yA] = ginput(64);
xA = [xA;1;width;width;1];
yA = [yA;1;1;height;height];

B = imread('C:\ZHYH\code\pic\wb.jpg');
imshow(B);
[xB,yB] = ginput(64);
xB = [xB;1;width;width;1];
yB = [yB;1;1;height;height];

alpha = 0.75;

C = zeros(height,width,3);
xC = alpha*xA + (1-alpha)*xB;
yC = alpha*yA + (1-alpha)*yB;
triC = delaunay(xC,yC);
ntri = size(triC,1);

xCA = zeros(height,width);
yCA = zeros(height,width);
xCB = zeros(height,width);
yCB = zeros(height,width);

[X,Y] = meshgrid(1:width,1:height);

for k = 1:ntri
[w1,w2,w3,r] = inTri(X, Y, xC(triC(k,1)), yC(triC(k,1)), xC(triC(k,2)), yC(triC(k,2)), xC(triC(k,3)), yC(triC(k,3)));
w1(~r)=0;
w2(~r)=0;
w3(~r)=0;
xCA = xCA + w1.*xA(triC(k,1)) + w2.*xA(triC(k,2)) + w3.*xA(triC(k,3));
yCA = yCA + w1.*yA(triC(k,1)) + w2.*yA(triC(k,2)) + w3.*yA(triC(k,3));
xCB = xCB + w1.*xB(triC(k,1)) + w2.*xB(triC(k,2)) + w3.*xB(triC(k,3));
yCB = yCB + w1.*yB(triC(k,1)) + w2.*yB(triC(k,2)) + w3.*yB(triC(k,3));
end

VCA(:,:,1) = interp2(X,Y,double(A(:,:,1)),xCA,yCA);
VCA(:,:,2) = interp2(X,Y,double(A(:,:,2)),xCA,yCA);
VCA(:,:,3) = interp2(X,Y,double(A(:,:,3)),xCA,yCA);

VCB(:,:,1) = interp2(X,Y,double(B(:,:,1)),xCB,yCB);
VCB(:,:,2) = interp2(X,Y,double(B(:,:,2)),xCB,yCB);
VCB(:,:,3) = interp2(X,Y,double(B(:,:,3)),xCB,yCB);

C = alpha*VCA + (1-alpha)*VCB;
imshow(uint8(C));

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% inTri checks whether input points (vx, vy) are in a triangle whose
% vertices are (v0x, v0y), (v1x, v1y) and (v2x, v2y) and returns the linear
% combination weight, i.e., vx = w1*v0x + w2*v1x + w3*v2x and
% vy = w1*v0y + w2*v1y + w3*v2y. If a point is in the triangle, the
% corresponding r will be 1 and otherwise 0.
%
% This function accepts multiple point inputs, e.g., for two points (1,2),
% (20,30), vx = (1, 20) and vy = (2, 30). In this case, w1, w2, w3 and r will
% be vectors. The function only accepts the vertices of one triangle.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [w1,w2,w3,r] = inTri(vx, vy, v0x, v0y, v1x, v1y, v2x, v2y)
v0x = repmat(v0x, size(vx,1), size(vx,2));
v0y = repmat(v0y, size(vx,1), size(vx,2));
v1x = repmat(v1x, size(vx,1), size(vx,2));
v1y = repmat(v1y, size(vx,1), size(vx,2));
v2x = repmat(v2x, size(vx,1), size(vx,2));
v2y = repmat(v2y, size(vx,1), size(vx,2));
w1 = ((vx-v2x).*(v1y-v2y) - (vy-v2y).*(v1x-v2x))./...
((v0x-v2x).*(v1y-v2y) - (v0y-v2y).*(v1x-v2x)+eps);
w2 = ((vx-v2x).*(v0y-v2y) - (vy-v2y).*(v0x-v2x))./...
((v1x-v2x).*(v0y-v2y) - (v1y-v2y).*(v0x-v2x)+eps);
w3 = 1 - w1 - w2;
r = (w1>=0) & (w2>=0) & (w3>=0) & (w1<=1) & (w2<=1) & (w3<=1);
end

图像处理之face morphing的更多相关文章

  1. Atitit 图像处理和计算机视觉的分类 三部分 图像处理 图像分析 计算机视觉

    Atitit 图像处理和计算机视觉的分类 三部分 图像处理 图像分析 计算机视觉 1.1. 按照当前流行的分类方法,可以分为以下三部分:三部分 图像处理 图像分析 计算机视觉1 1.2. 图像处理需要 ...

  2. Atitit 图像处理的摩西五经attilax总结

    Atitit 图像处理的摩西五经attilax总结 1. 数字图像处理(第三版)1 2. 图像处理基础(第2版)(世界著名计算机教材精选)1 3. 计算机视觉特征提取与图像处理(第三版)2 4. Op ...

  3. Atitit 图像处理的心得与疑惑 attilax总结

    Atitit 图像处理的心得与疑惑 attilax总结 1.1. 使用类库好不好??还是自己实现算法1 1.2. 但是,如果遇到类库体积太大,后者没有合适的算法,那就只能自己开发算法了1 1.3. 如 ...

  4. Atitit 图像处理 调用opencv 通过java  api   attilax总结

    Atitit 图像处理 调用opencv 通过java  api   attilax总结 1.1. Opencv java api的支持 opencv2.4.2 就有了对java api的支持1 1. ...

  5. Atitit MATLAB 图像处理 经典书籍attilax总结

    Atitit MATLAB 图像处理 经典书籍attilax总结 1.1. MATLAB数字图像处理1 1.2. <MATLAB实用教程(第二版)>((美)穆尔 著)[简介_书评_在线阅读 ...

  6. Atitit 图像处理类库大总结attilax qc20

    Atitit 图像处理类库大总结attilax qc20 1.1. 选择与组合不同的图像处理类库1 1.2. Halcon 貌似商业工具,功能强大.1 1.3. Openvc  Openvc功能也是比 ...

  7. Atitit MATLAB 图像处理attilax总结

    Atitit MATLAB 图像处理attilax总结 1.1. 下载 Matlab7.0官方下载_Matlab2012 v7.0 官方简体中文版-办公软件-系统大全.html1 1.2. Matla ...

  8. 使用MATLAB对图像处理的几种方法(下)

     试验报告 一.试验原理: 图像点处理是图像处理系列的基础,主要用于让我们熟悉Matlab图像处理的编程环境.灰度线性变换和灰度拉伸是对像素灰度值的变换操作,直方图是对像素灰度值的统计,直方图均衡是对 ...

  9. 使用MATLAB对图像处理的几种方法(上)

    实验一图像的滤波处理 一.实验目的 使用MATLAB处理图像,掌握均值滤波器和加权均值滤波器的使用,对比两种滤波器对图像处理结果及系统自带函数和自定义函数性能的比较,体会不同大小的掩模对图像细节的影响 ...

随机推荐

  1. comboBox绑定数据库、模糊查询

    实现: 一.绑定数据库 点击查询按钮,comboBox显示从数据库查到的某字段的一列数据 方法:在按钮的点击事件绑定数据库 private void button1_Click(object send ...

  2. CodeIgniterCodeigniter+PHPExcel导出数据到Excel文件

    解压压缩包里的Classes文件夹中的内容到application\libraries\目录下,目录结构如下:--application\libraries\PHPExcel.php--applica ...

  3. 【codevs1036】商务旅行 LCA 倍增

    1036 商务旅行  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题目描述 Description 某首都城市的商人要经常到各城镇去做生意,他们按自己的 ...

  4. format 字符串

    http://www.cnblogs.com/mumble/archive/2011/05/25/2056462.html ShowMessage( Format('this is %.0f',[ t ...

  5. CSS基本特性

    1.块状元素有大小:行内元素没有,除非脱离文档流(如float.absolute) 2.内部元素决定大小 不管外面元素是哪种类别(块状或行内),里面元素都可以撑大外面 3.外部元素决定位置

  6. 读者写者问题(有bug 后续更改)

    与上一篇<秒杀多线程第十篇 生产者消费者问题>的生产者消费者问题一样,读者写者也是一个非常著名的同步问题.读者写者问题描述非常简单,有一个写者很多读者,多个读者可以同时读文件,但写者在写文 ...

  7. js库之art.dialog

    自适应内容 artDialog的特殊UI框架能够适应内容变化,甚至连外部程序动态插入的内容它仍然能自适应,因此你不必去考虑消息内容尺寸使用它.它的消息容器甚至能够根据宽度让文本居中或居左对齐——这一切 ...

  8. html5 placeholder

    placeholder是html5<input>标签的一个属性,placeholder 属性提供可描述输入字段预期值的提示信息(hint).该提示会在输入字段为空时显示,并会在字段获得焦点 ...

  9. python中的面向对象编程

    在python中几乎可以完成C++里所有面向对象编程的元素. 继承:python支持多继承: class Derived(base1, base2, base3): pass 多态:python中的所 ...

  10. GSM短信侦听的便宜方案

    侦听GSM短信常用的是OsmocomBB + C118方案,主要是用luca/gsmmap分支.使用ccch_scan这个程序可以把通信封装成GSMTAP发给本机,然后用WireShark接收GSMT ...