以前在论坛、微博经常看到一张脸,五官长得像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. 2014北邮新生归来赛解题报告d-e

    D: 399. Who Is Joyful 时间限制 3000 ms 内存限制 65536 KB 题目描述 There are several little buddies standing in a ...

  2. 2.4.2电子书fb.c文件

    显示层面头文件 定义结构体,为显示统一标准 int (*DeviceInit)(void); 显示类驱动初始化 int (*ShowPixel)(int iPenX, int iPenY, unsig ...

  3. Python中通过多个字符分割(split)字符串的方法

    python中字符串自带的split方法一次只能使用一个字符对字符串进行分割,但是python的正则模块则可以实现多个字符分割 import re re.split('-|_','sharejs_ha ...

  4. Rhel6-tomcat+nginx+memcached配置文档

    理论基础: User - > web ->nginx  ->tomcat1 ->*.jsp 80          8080 ↓      -> tomcat2 html ...

  5. OpenCV之响应鼠标(四):在图像上绘制出矩形并标出起点的坐标

    涉及到两方面的内容:1. 用鼠标画出矩形.2.在图像上绘制出点的坐标 用鼠标绘制矩形,涉及到鼠标的操作,opencv中有鼠标事件的介绍.需要用到两个函数:回调函数CvMouseCallback和注册回 ...

  6. Unity4.3.3激活

    Unity4.X Win版本的破解方法: <ignore_js_op> 1.安装unity4.X,一路按提示下一步,要断网,直到激活运行软件后再联网2.将Unity 4.x Pro Pat ...

  7. SimpleDateFormat()简单了解

    比如:SimpleDateFormat sdf1 = new  SimpleDateFormat("yyyy年MM天dd日 HH时mm分ss秒 一年中的第 D 天 一年中第w个星期 一月中第 ...

  8. python tuple 操作

    特点:不可改(与字符串一样.不允许删除和修改) 操作:1.print 可使用跟%的元祖  print( '%s is %d years old' % (name, age)) 2.像列表一样有索引 3 ...

  9. poj1160 dp

    //Accepted 564 KB 63 ms //和hdu1227一样 //dp[i][j]=min(dp[i][j],dp[k][j-1]+cost[k+1][i]) //初始化条件,dp[0][ ...

  10. sap 根据TOCE找 USER_EXIT

    *&---------------------------------------------------------------------* *& Report  ZUSER_EX ...