Image Warping-Morphing 实现人脸渐变
来源:互联网 发布:软件版本更新 编辑:程序博客网 时间:2024/06/03 10:07
这学期选修了计算机视觉与模式识别这门课,刚上几周,感觉挺有趣的。
课程上到Image Warping & Morphing的时候老师介绍了一样挺好玩的东西,我用它来做人脸渐变。
先看看效果图:
。。。。。。。。。。。。。。。。。。。。。。。。
简单介绍一下过程(我用的是matlab实现,因为matlab自带的函数还有矩阵运算实在太强大了,让我省掉好多功夫,可能以后还会用c++写一遍):
1、分别在原图和目的图上面标注特征点,并且把所有点的坐标记录下来,例如:
(说白了做的主要是五官的渐变,把五官用特征点标出来,当然可以用人脸识别的方法代替我手工标记。。。但知识和时间有限没有实现识别的代码,只能手动操作,以后补上)
2、有了所有这些特征点之后做三角剖分:(后面步骤介绍其作用)
就是每三个点画成一个三角形,互不相交的,得到的就是这样子:
(matlab有自带三角剖分的函数,delaunay,用法百度一下一堆)
3、求出当前所要画的中间过程图的每个点的像素值:
其实要画出中间过程图的是怎么做的呢?就是画出每个像素点的像素值!那我怎么知道像素值是多少,那当然是原图和目标图上对应点的像素值的加权平均啊,取系数不同就可以画出不同的中间过程。说白了我要找到原图和目标图上对应像素点读取像素值,首先我就要找到对应像素点的坐标!所以我们引入三角剖分,目的就是找出对应点的坐标,用一个例子来说明:
假设ABC是原图上的三角形,A'B'C'是我变换过程中图上对应的三角形
我们将左边的点弄成齐次矩阵,即:A的坐标矩阵就是[x; y; 1](注意这是3*1的),BC同理,ABC就是一个3*3的矩阵[A,B,C],然后我们定义一个3*3的M矩阵,M*ABC = A‘B'C';然后就有M = A‘B’C'*inv(ABC),inv是求逆。
这个矩阵可以推广到所有点,所以我们要找对应点的位置,就可以用该点的坐标,左乘inv(M),就得到原图上对应点的坐标啦!再读取一下像素值,这样就OK啦!
这里还有一个小技巧,做双线性插值,效果会比较好,但是我的图才几百乘几百差不了多少,所以我没做。
4、将所有点的像素值输出到图像上,matlab的imwrite,大功告成。。。
展示一下我做了几个效果图:
me to Harden:
me to Leon:
matlab代码:
clear all close all%原图~目标图%图片读入到矩阵originG = imread('%图片地址');targetG = imread('');%图片特征点,我是存到txt里面然后读取originT = load('%txt文件地址');targetT = load('');num = size(originT, 1);%三角剖分TRI = delaunay(originT(: , 1), originT(: , 2));%中间图的特征点medT = zeros(num, 2);P = 0.1 : 0.1 : 0.9;for j = 1: 9 %求出中间图特征点位置 for i = 1: num medT(i, 1) = P(j)*(targetT(i, 1) - originT(i, 1)) + originT(i, 1); medT(i, 2) = P(j)*(targetT(i, 2) - originT(i, 2)) + originT(i, 2); end %先弄一个全零矩阵,用来存中间图每个像素点像素值 medG = zeros(300, 200, 3); for x = 1: 300 for y = 1: 200 for k = 1: size(TRI, 1) mX = medT(TRI(k, :), 1); %某个三角形3个定点的x值 mY = medT(TRI(k, :), 2);%判断点是否在三角形内 [IN, ON] = inpolygon(x, y, mX, mY); if ON == 1 || IN == 1 m0 = [mX, mY, ones(3, 1)]'; m1 = [originT(TRI(k, :), 1), originT(TRI(k, :), 2), ones(3, 1)]'; %向原图转换 tran1 = m1 * m0^-1; pos1 = tran1 * [x; y; 1]; m2 = [targetT(TRI(k, :), 1), targetT(TRI(k, :), 2), ones(3, 1)]'; %向目标图转换 tran2 = m2 * m0^-1; pos2 = tran2 * [x; y; 1]; medG(x, y, :) = (1-P(j)) * originG(round(pos1(1,1)), round(pos1(2,1)), :) + P(j) * targetG(round(pos2(1,1)), round(pos2(2,1)), :); break; end end end end %画图 filename = ['%存放地址', num2str(j), '.jpg']; imwrite(uint8(medG), filename, 'jpg');end挺详细了,就这样吧!谢谢阅读!
- Image Warping-Morphing 实现人脸渐变
- image morphing
- Image Warping
- Image warping / distortion
- Image Warping --IDW/RBF
- Warping、Morphing与Deformation的联系和区别
- 2D Image Morphing Algorithms
- Ex5: Projective Transform & Image Morphing
- Morphing
- 图像变形算法思路(About Image Morphing)
- DIBR-3D图像变换(3D Image Warping)
- 图像仿射变换及图像扭曲(Image Warping)
- Swift 渐变 image
- bachground-image背景渐变笔记
- face morphing
- wait morphing
- html5用css3实现线性渐变background-image:linear-gradient使用方法
- DTW(Dynamic Time Warping / 动态时间归整) python实现
- 环境配置问题与解决方案:visual studio 2008 debug后窗口一闪而过
- 栈解决迷宫求解
- 关于.appref-ms文件后缀名
- 汉诺塔问题的递归解法
- 支付宝
- Image Warping-Morphing 实现人脸渐变
- 可视化编程与屏幕适配
- Combinations
- 蓝桥杯 历届试题 蚂蚁感冒
- 多线程
- 建立一个新链表和输出它的长度
- Block
- UICollectionView
- Java内存分配和String类型的深度解析