接着上一篇文章的热度,继续讲讲一些稍微简单的算法吧。

本文来讲讲碎片算法,先贴几个效果图吧:

           

这是个破坏性的滤镜,拿美女来说事是因为搞图像的人90%是男人,色色的男人。

关于碎片滤镜的原理,网络上可找到的资料为:将图像创建四个相互偏移的副本,产生类似重影的效果。

就凭上述一句话,我们就可以动手了。

分析:通过上述几幅图像的比较,特别是眼睛部位,可以看出处理的图应该看得出像是单眼变成了4个眼睛,因此,网络上的说法可靠。

那么偏移的中心在哪里,偏移的数量又是多少呢,4个偏移,分别是往那些方向偏移呢,这些问题也很简单,可以那PS做验证:

具体步骤如下:打开一幅图像,在图像颜色比较单调的地方(比如上述美女的手臂处)填充一处2*2像素的红色,然后复制图层,对复制后的图层进行碎片滤镜处理,并调整图层透明度为50%,局部放大可得到如下图像:

如此效果,则可轻易得出结论:

偏移的中心就是以每个像素为中心,4个偏移分别以中心对称,斜45度均匀圆周布置,水平和垂直偏移各45度,偏移量4个像素。

那么如何叠加的问题应该可以猜测,是取四次偏移后累加值的平均值。

针对如此思路,我写出如下算法:

private void CmdFragment_Click(object sender, EventArgs e)
{
int X, Y, Z, XX, YY;
int Width, Height, Stride;
int Speed, Index;
int SumR, SumG, SumB;
Bitmap Bmp = (Bitmap)Pic.Image;
if (Bmp.PixelFormat != PixelFormat.Format24bppRgb) throw new Exception("不支持的图像格式."); Width = Bmp.Width; Height = Bmp.Height; Stride = (int)((Bmp.Width * + ) & 0XFFFFFFFC); byte[] ImageData = new byte[Stride * Height]; // 用于保存图像数据,(处理前后的都为他)
byte[] ImageDataC = new byte[Stride * Height]; // 用于保存克隆的图像数据
int[] OffsetX = new int[] { , -, -, }; // 每个点的偏移量
int[] OffsetY = new int[] { -, -, , };
fixed (byte* P = &ImageData[], CP = &ImageDataC[])
{
byte* DataP = P, DataCP = CP;
BitmapData BmpData = new BitmapData();
BmpData.Scan0 = (IntPtr)DataP; // 设置为字节数组的的第一个元素在内存中的地址
BmpData.Stride = Stride;
Bmp.LockBits(new Rectangle(, , Bmp.Width, Bmp.Height), ImageLockMode.ReadWrite | ImageLockMode.UserInputBuffer, PixelFormat.Format24bppRgb, BmpData); Stopwatch Sw = new Stopwatch(); // 只获取计算用时
Sw.Start();
System.Buffer.BlockCopy(ImageData, , ImageDataC, , Stride * Height); // 填充克隆数据 for (Y = ; Y < Height; Y++)
{
Speed = Y * Stride;
for (X = ; X < Width; X++)
{
SumB = ; SumG = ; SumR = ;
for (Z = ; Z < ; Z++) // 累积取样点的取样和
{
XX = X + OffsetX[Z];
YY = Y + OffsetY[Z];
if (XX < ) // 注意越界
XX = ;
else if (XX >= Width)
XX = Width - ;
if (YY < )
YY = ;
else if (YY >= Height)
YY = Height - ;
Index = YY * Stride + XX * ;
SumB += DataCP[Index];
SumG += DataCP[Index + ];
SumR += DataCP[Index + ];
} DataP[Speed] = (byte)((SumB+) >> ); // 求平均值(Sum+2)/4,为什么要+2,就为了四舍五入。比如如果计算结果为108.6,则取像素109更为合理
DataP[Speed + ] = (byte)((SumG + ) >> );
DataP[Speed + ] = (byte)((SumR + ) >> );
Speed += ; // 跳往下一个像素
}
}
Sw.Stop();
this.Text = "计算用时: " + Sw.ElapsedMilliseconds.ToString() + " ms";
Bmp.UnlockBits(BmpData); // 必须先解锁,否则Invalidate失败
}
Pic.Invalidate();
}

  算法中,OffsetX 和 OffsetY分别为取样点像素的偏移量。同样,由于该滤镜涉及到了领域操作,在处理前需要做像素备份,但这里没有对备份数据进行扩展。因此,在内部代码里就需要对取样点的坐标进行验证,看是否超过其范围,如果超过范围,通常在图像滤镜算法范围内,有3种处理方式:

(1)超过了则认为是其最接近的边界值,即重复边缘像素,这部分代码即上述贴出的if ..... else if 部分。

(2)折回,可用如下代码来描述:

while (XX >= Width)
XX = XX - Width;
while (XX < )
XX = XX + Width;
while (YY >= Height)
YY = YY - Height;
while (YY < )
YY = YY + Height;

(3) 只计算在图像范围内的像素: 

 if (XX >=  && XX < Width && YY >=  && YY < Height)
{
// 累加计算
}

当然这样做,就必须用一个变量记录下都做了多少次符合条件的计算。

有兴趣的朋友可以自己改改代码试一试。

上述代码段中DataP[Speed] = (byte)((SumB+2) >> 2);要对SumB加2的原因是为了让结果进行四舍五入的操作,这样才较为合理。

经过测试,上述代码和PS处理的效果100%的吻合。说明我们的猜测是完全正确的。

还可以对算法进一步扩展:  想的远一点,为什么非的是4个重影呢,非得是45度角度呢,非得是4个像素的水平和垂直偏移呢。我给出下图让有兴趣的读者自己研发吧。

图中,角度为32度,半径为10,碎片数为7,可产生类似下面的效果(可用我的Imageshop进行验证):

       

完整工程下载地址:http://files.cnblogs.com/Imageshop/Fragement.rar

***************************作者: laviewpbt   时间: 2013.7.5   联系QQ:  33184777  转载请保留本行信息*************************

PhotoShop算法原理解析系列 - 像素化---》碎片。的更多相关文章

  1. PhotoShop算法原理解析系列 - 风格化---》查找边缘。

    之所以不写系列文章一.系列文章二这样的标题,是因为我不知道我能坚持多久.我知道我对事情的表达能力和语言的丰富性方面的天赋不高.而一段代码需要我去用心的把他从基本原理-->初步实现-->优化 ...

  2. 2. Attention Is All You Need(Transformer)算法原理解析

    1. 语言模型 2. Attention Is All You Need(Transformer)算法原理解析 3. ELMo算法原理解析 4. OpenAI GPT算法原理解析 5. BERT算法原 ...

  3. 3. ELMo算法原理解析

    1. 语言模型 2. Attention Is All You Need(Transformer)算法原理解析 3. ELMo算法原理解析 4. OpenAI GPT算法原理解析 5. BERT算法原 ...

  4. 4. OpenAI GPT算法原理解析

    1. 语言模型 2. Attention Is All You Need(Transformer)算法原理解析 3. ELMo算法原理解析 4. OpenAI GPT算法原理解析 5. BERT算法原 ...

  5. 5. BERT算法原理解析

    1. 语言模型 2. Attention Is All You Need(Transformer)算法原理解析 3. ELMo算法原理解析 4. OpenAI GPT算法原理解析 5. BERT算法原 ...

  6. FastText算法原理解析

    1. 前言 自然语言处理(NLP)是机器学习,人工智能中的一个重要领域.文本表达是 NLP中的基础技术,文本分类则是 NLP 的重要应用.fasttext是facebook开源的一个词向量与文本分类工 ...

  7. LRU算法原理解析

    LRU是Least Recently Used的缩写,即最近最少使用,常用于页面置换算法,是为虚拟页式存储管理服务的. 现代操作系统提供了一种对主存的抽象概念虚拟内存,来对主存进行更好地管理.他将主存 ...

  8. 最全排序算法原理解析、java代码实现以及总结归纳

    算法分类 十种常见排序算法可以分为两大类: 非线性时间比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此称为非线性时间比较类排序. 线性时间非比较类排序:不通过 ...

  9. CGI原理解析系列之中的一个----CGI怎样获取WEBserver数据

    //gcc get_post.c -o get_post.ums; #include <stdio.h> #include <stdlib.h> #include <un ...

随机推荐

  1. [Asp.net 5] Logging-新日志系统目录

    楼主有个美好的愿望——把asp.net 5所有能看懂的代码一一呈现给大家(比如C++,楼主就看不懂).现在已经做完了依赖注入.多语言.配置文件三部分,比较基础的日志就成为了楼主的下一个目标.下面是楼主 ...

  2. mvc实现上传视频预览

    上个项目中用到了上传视频,本来打算用百度的webuploader做的,但是webuploader可能有个毛病就是不能上传太大的东西. 于是乎,只能换个方法做了啊,看了半天最终决定用传统的uploade ...

  3. canvas孙悟空脚踩白云今年是猴年

    效果查看:http://hovertree.com/texiao/html5/30/ 使用HTML5的canvas画的孙悟空,CSS3画的白云飘飘. 刚擒住了几个妖 又降住了几个魔 魑魅魍魉怎么他就这 ...

  4. jQuery弹出深色系层菜单

    低调奢华jQuery弹出层菜单,使用新版的jQuery库,兼容多种浏览器.Demo展示: http://hovertree.com/texiao/layer/3/ 本特效可以作为网站的引导页,使用jQ ...

  5. 基于小脚丫DDS 调频 调幅 调相 切换波形 AD5601输出模拟波形

    先讲讲里面的矩阵键盘,矩阵键盘列有下拉电阻,默认全为0000,默认行输入为1111,当有按键按下的时候,列输入会被拉高,这时控制行的输出做行扫描,电子琴用key_flag_r0电平作为使能,这里用ke ...

  6. CRM(四川网脉系统)项目总结

    CRM系统(四川网脉系统)项目总结 为期八天的四川网脉系统(CRM系统)项目结束了,不管是在做这个项目的过程中还是答辩的过程中都有一些收获,下面对整个项目的开发做一个大致的总结. 一.项目概况 四川网 ...

  7. HTTP 2.0与HTTP 1.1区别

    1.什么是HTTP 2.0 HTTP/2(超文本传输协议第2版,最初命名为HTTP 2.0),是HTTP协议的的第二个主要版本,使用于万维网.HTTP/2是HTTP协议自1999年HTTP 1.1发布 ...

  8. SpringMVC基本使用

    springMVC是一个MVC框架,他控制着请求相应的整个流程,从请求一进入到应用服务器到相应离开,都离不开mvc框架 请求在应用服务器中 先说说请求相应在应用服务器的整个过程 DisptacherS ...

  9. (转)SQL 优化原则

    一.问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用 系统提交实际应用后,随着数据库中数据的增加,系 ...

  10. SharePoint 2013 工作流之Visual Studio开发示例篇

    SharePoint 2013引用了WF4.0 Foundation,支持使用Designer和Visio进行设计,但是功能受限,而Visual Studio可以开发功能更加丰富的工作流,下面我们简单 ...