今天晚上没有课, 花了几分钟, 还是按照我昨天的思路把那个人脸变换程序实现了一下. 特地选了两张比较像的照片(人头的大小, 背景颜色, 脸的朝向), 其实也是自己截出来的, 还调整了不少, 才做到了"相似".
变到 效果:
代码部分跟昨天相比稍微变了一点点, 就是实现了两张位图每个点的计算, 在Form的客户区打印出来.
2 {
3 using (Bitmap bmp1 = new Bitmap(@"C:\liang.png"))
4 using (Bitmap bmp2 = new Bitmap(@"C:\liu.png"))
5 {
6 Bitmap bm = new Bitmap(1, 1); //画一个点,调整这个点的大小
7 Graphics g = Graphics.FromHwnd(this.Handle);//这个点画在哪里
8 int X, Y;
9 for (X = 0; X < 160; X++)
10 for (Y = 0; Y < 180; Y++)
11 {
12 Color pixelColor1 = bmp1.GetPixel(X, Y); //[X][Y]点坐标的颜色
13 Color pixelColor2 = bmp2.GetPixel(X, Y);
14 int red = (pixelColor2.R - pixelColor1.R)[* ?/?] + pixelColor1.R;
15 int green =(pixelColor2.G - pixelColor1.G)[* ?/?] + pixelColor1.G;
16 int blue = (pixelColor2.B - pixelColor1.B)[* ?/?] + pixelColor1.B;
17 Color drawcolor = Color.FromArgb(red, green, blue);
18 bm.SetPixel(0, 0, drawcolor);//"画点", 这个点的颜色
19 g.DrawImageUnscaled(bm, X, Y);//开始在[X][Y]点画了
20 }
21 }
22 }
想想昨天那个一个点一个点输出位图, 都是一竖行一竖行的输出, 效果不行. 今天就只想输出10帧, 然后每帧都截图, 再用其它的图片制作软件把这10帧放在一起做成闪图的那种样式, 试试效果. 其中代码中红色标记的部分代表乘以一个数, 比如这次要运行处10帧中的第3帧, 红色部分就写成*3/10, 一次一次的试, 呵呵.
通过上图可以发现效果跟视频中程序的效果是不一样的. 如果仔细看视频中效果的做法, 可能就就如昨天辰评论说的那样:
1. 两张图片共同分割为大小相同的小块n
2. 第2张图的第n块黏贴到第一张图中
3. 保存图片为一个新的名字, 例如bmp001
4. 如此循环, 直到所有小块都被复制到第一张图
5. 打开acdsee,然后用迅雷不及掩耳盗铃的速度, 切换所有保存的图片, 就可以看到效果
所以我这种方法感觉有些山寨, 或者说呆笨. 当然这种山寨的做法也不是没有收获的, 仔细看其中的某些帧, 比如刘德华肩膀位置的西装, 梁朝伟图片的那个位置是没有衣服的, 只有背景. 让梁朝伟这个位置的颜色变成刘德华相应的点颜色, 在变化的过程中可以看出有一种半透明的效果, 当然在NET中早有定义颜色有这种半透明效果的函数, 现在自己无意间实现了一下:)
感谢大家对我上一篇人脸变换程序究竟要如何实现的指点, 有些博友贴上自己辛苦写的代码, 感慨万分啊. 也许我不该瞎嚷嚷, 连Computer Graphic还没学, 就在这嚷嚷这个东西, 是不是有点不应该? 也许最起码等我应该有点这方面的基础...搞的大家写的代码我都无法再给予回复(因为我不懂, 不知道写什么好, 只是心中默默的感谢...等我强大了, 只要博客园不消失, 再回头看看).
这种程序的实现, 也有一种说法是识别人脸, 比如识别两张图片人的鼻子, 眼睛, 嘴巴...然后进行拉伸, 变行, 颜色的改变. 貌似Flash中早有这种技术(把一个方形变成圆形, 不知是不是也是这种原理?)
总之, 要学习的还有很多很多, 加油, 愿每天都能进步一点点:-)