本篇博文来自博主Imageshop,打赏或想要查阅更多内容可以移步至Imageshop。

转载自:https://www.cnblogs.com/Imageshop/p/3173090.html     侵删

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

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

           

这是个破坏性的滤镜,拿美女来说事是因为搞图像的人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 * 3 + 3) & 0XFFFFFFFC);byte[] ImageData = new byte[Stride * Height];                                    // 用于保存图像数据,(处理前后的都为他)byte[] ImageDataC = new byte[Stride * Height];                                   // 用于保存克隆的图像数据int[] OffsetX = new int[] { 4, -4, -4, 4 };                                      // 每个点的偏移量int[] OffsetY = new int[] { -4, -4, 4, 4 };fixed (byte* P = &ImageData[0], CP = &ImageDataC[0]){byte* DataP = P, DataCP = CP;BitmapData BmpData = new BitmapData();BmpData.Scan0 = (IntPtr)DataP;                                              //  设置为字节数组的的第一个元素在内存中的地址BmpData.Stride = Stride;Bmp.LockBits(new Rectangle(0, 0, Bmp.Width, Bmp.Height), ImageLockMode.ReadWrite | ImageLockMode.UserInputBuffer, PixelFormat.Format24bppRgb, BmpData);Stopwatch Sw = new Stopwatch();                                             //  只获取计算用时Sw.Start();System.Buffer.BlockCopy(ImageData, 0, ImageDataC, 0, Stride * Height);     //  填充克隆数据        for (Y = 0; Y < Height; Y++){Speed = Y * Stride;for (X = 0; X < Width; X++){SumB = 0; SumG = 0; SumR = 0;for (Z = 0; Z < 4; Z++)                                           //  累积取样点的取样和{XX = X + OffsetX[Z];YY = Y + OffsetY[Z];if (XX < 0)                                                    //   注意越界XX = 0;else if (XX >= Width)XX = Width - 1;if (YY < 0)YY = 0;else if (YY >= Height)YY = Height - 1;Index = YY * Stride + XX * 3;SumB += DataCP[Index];SumG += DataCP[Index + 1];SumR += DataCP[Index + 2];}DataP[Speed] = (byte)((SumB+2) >> 2);    //  求平均值(Sum+2)/4,为什么要+2,就为了四舍五入。比如如果计算结果为108.6,则取像素109更为合理     DataP[Speed + 1] = (byte)((SumG + 2) >> 2);DataP[Speed + 2] = (byte)((SumR + 2) >> 2);Speed += 3;                                                     //  跳往下一个像素}}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 < 0)XX = XX + Width;
while (YY >= Height)YY = YY - Height;
while (YY < 0)YY = YY + Height;

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

 if (XX >= 0 && XX < Width && YY >= 0 && 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

PhotoShop算法原理解析系列 - 像素化---》碎片相关推荐

  1. PhotoShop算法原理解析系列 - 像素化---》碎片。

    接着上一篇文章的热度,继续讲讲一些稍微简单的算法吧. 本文来讲讲碎片算法,先贴几个效果图吧:             这是个破坏性的滤镜,拿美女来说事是因为搞图像的人90%是男人,色色的男人. 关于碎 ...

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

    本篇博文来自博主Imageshop,打赏或想要查阅更多内容可以移步至Imageshop. 转载自:https://www.cnblogs.com/Imageshop/p/3171425.html    ...

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

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

  4. 索引算法原理解析(B-tree以及磁盘存储原理)

    刚开始学习的时候,百度去查,但发现好多说得太复杂不好理解,结合各个文章总结一下(建议大概看文字,不理解不要紧,然后再看图的执行步骤然后在结合文字,这样一切就清晰好多) B-tree,B是balance ...

  5. python文件去重算法_使用Python检测文章抄袭及去重算法原理解析

    在互联网出现之前,"抄"很不方便,一是"源"少,而是发布渠道少:而在互联网出现之后,"抄"变得很简单,铺天盖地的"源"源 ...

  6. python去重算法_使用Python检测文章抄袭及去重算法原理解析

    在互联网出现之前,"抄"很不方便,一是"源"少,而是发布渠道少:而在互联网出现之后,"抄"变得很简单,铺天盖地的"源"源 ...

  7. p.563算法原理解析

    p.563算法原理解析 1.概览 ​ 下图展示了,人工主观语音评估mos-lqs,双端和单端客观语音评估mos-lqo这三种方法的差异. ​ p563算法可以被想象成一个专家使用测试设备如传统的听筒侦 ...

  8. LruCache算法原理解析

    本来想写关于LruCache算法的原理解析文章,但是看到卡神的作品,写的太好了.所以这里我还是转载一下吧. 史上最详细LrcCache算法解析:https://blog.csdn.net/carson ...

  9. 十分详细的diff算法原理解析

    本文我们总结一下有关diff算法的相关内容和实现原理 开门见山,直接先给出大家diff算法的概念 diff算法可以看作是一种对比算法,对比的对象是新旧虚拟Dom.顾名思义,diff算法可以找到新旧虚拟 ...

最新文章

  1. Gotchas 44-引用和临时对象
  2. docker远程访问TLS证书认证shell
  3. python爬虫beautifulsoup爬当当网_Python爬虫包 BeautifulSoup 递归抓取实例详解_python_脚本之家...
  4. 如何聚焦自己的研究方向?一个实例研究
  5. 工作47:继续理解父子组件
  6. 最全的iOS物理引擎demo
  7. 几何修复_*ST海润:实施终止退市 光伏产业修复成几何?
  8. 毕业生,管好你的档案和户口
  9. Excel将多个工作簿加载到SQL Server中
  10. 简单创建两个线程,交替输出内容
  11. 解析oracle的dump文件,使用awk来解析dump文件
  12. pandas loc, iloc, ix, at, iat用法
  13. Nacos视频教程分享
  14. jquery 的税收计算器(仅限参考)
  15. oracle 11g 服务端下载地址及安装说明
  16. vim下fcitx优化
  17. 物联网开源平台KAA
  18. 不良资产证券化中信用评级国外发展史
  19. 06.破解Windows7密码
  20. Confluence备份恢复报错: AO_187CCC_SIDEBAR_LINK

热门文章

  1. 如何用新浪微博账号登陆第三方网站
  2. 个人打地鼠游戏制作流程
  3. 非标品如何写标题、选关键词?淘宝非标品关键词怎么进行布局?
  4. android 打开免打扰模式,开启安卓手机免打扰模式的教程
  5. ssh远程登陆配置、公私钥密码ssh体系构建
  6. empt注意事项 php_PHP empty()函数说明---用了N遍了就是记不住
  7. python pyecharts Bar柱状堆叠图
  8. 46道史上最全Redis面试题,面试官能问的都被我找到了(含答案)
  9. fgo网络错误Java_JAVA 线上故障排查全套路
  10. 你知道这把神奇的KAZbrella伞么