博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
图像柔光效果(SoftGlow)的原理及其实现。
阅读量:5952 次
发布时间:2019-06-19

本文共 3249 字,大约阅读时间需要 10 分钟。

  图像柔光效果在很多商业软件中都有实现,比如美图秀秀,光影魔术手等。其能针对原始图像产生一副新的比较平滑感觉光线比较柔和的效果,给人一种朦胧美,如下面几幅图所示:

                                    

      目前,关于该算法的可控参数,美图秀秀只提供了一个程度(0-100%)控制量,其算法调节的效果和幅度都较小,光影魔术手有柔化程度和高光柔化两个参数,其中柔化程度控制柔化的朦胧效果,高光柔化调节图像的亮度。 还有一些开源的软件如Imagestone、paint.net、gimp也有softglow算法,他们都提供了3个控制量:半径、亮度、对比度(锐度),其中Imagestone其实是翻译的gimp的算法,而GIMP和paint.net的算法在基本原理上是一样的,细节上有所区别而已。

     我们以paint.net的实现过程为例进行说明,在paint.net的源代码中,GlowEffect.cs为实现该效果的文件,我抽取其部分源代码简要说明下这个算法的过程。

public GlowEffect()  : base(StaticName, StaticImage, null, EffectDirectives.None, true)        {            this.blurEffect = new BlurEffect();            this.bcAdjustment = new BrightnessAndContrastAdjustment();            this.screenBlendOp = new UserBlendOps.ScreenBlendOp();        }

     以及代码片段:

public override unsafe void Render(            EffectConfigToken parameters,             RenderArgs dstArgs,             RenderArgs srcArgs,             System.Drawing.Rectangle[] rois,             int startIndex,             int length)        {            // First we blur the source, and write the result to the destination surface            // Then we apply Brightness/Contrast with the input as the dst, and the output as the dst            // Third, we apply the Screen blend operation so that dst = dst OVER src            ThreeAmountsConfigToken token = (ThreeAmountsConfigToken)parameters;            AmountEffectConfigToken blurToken = new AmountEffectConfigToken(token.Amount1);            this.blurEffect.Render(blurToken, dstArgs, srcArgs, rois, startIndex, length);            BrightnessAndContrastAdjustmentConfigToken bcToken = new BrightnessAndContrastAdjustmentConfigToken(token.Amount2, token.Amount3);            this.bcAdjustment.Render(bcToken, dstArgs, dstArgs, rois, startIndex, length);            for (int i = startIndex; i < startIndex + length; ++i)            {                Rectangle roi = rois[i];                for (int y = roi.Top; y < roi.Bottom; ++y)                {                    ColorBgra* dstPtr = dstArgs.Surface.GetPointAddressUnchecked(roi.Left, y);                    ColorBgra* srcPtr = srcArgs.Surface.GetPointAddressUnchecked(roi.Left, y);                    screenBlendOp.Apply(dstPtr, srcPtr, dstPtr, roi.Width);                }            }        }

    由以上代码初步得出结论:他们是以高斯模糊以及亮度对比度调节两个滤镜为基础,稍作混合即可。

      第一步:备份原始图像;

      第二步:对原始图像按指定的半径进行高斯模糊;

      第三步:对模糊后的图像继续进行亮度和对比度的调整;

      第四步:用原始图像的备份数据通原始图像(经过上述二及三处理后的图像)按照Photoshop的滤色(Screen)方式进行混合。

      关于滤色方式的混合算法这里简单的提一下:  Blend = X + Y - X * Y / 255 ;  其中X和Y分别表示基色和混合色,Blend表示结果色。

      算法的源码可以参考我在上面说的几个开源的软件,当然这可能需要你有一定的编程基础,毕竟那些软件的框架都比较复杂。 

      关于算法的执行速度可以说只取决于第二步,因为亮度对比度的调节实际上是个查表的过程(PS的亮度对比度指令其实要比大家想象的复杂点的,这个有机会再谈,也可以参考阿发伯的博文),而第四步其实也是可以用查表的方式来加速的(不过一定要用一位的方式)。高斯模糊这个老生长谈的问题,在我所搜索过的网页中是没有谁给出过一个完整的、完美的、执行速度和指定半径无关的、可运行的VB或VC或JAVA程序源代码(一般都是给出参考文章介绍)。我自己有这个方面的代码,不过我也不愿意共享。真正有兴趣的我推荐你去找GIMP的算法代码,在GIMP的整个源码系统,至少给出了三种高斯模糊优化的代码,分别位于blur-gauss.c(给出了2种:RLE及IIR优化代码)以及contrast-retinex.c中(代码特别简洁),当然,那些代码如果提取出来还应该进行代码层面的整理和优化。Paint.net也提供了高斯模糊函数,不过期实质并不是高斯模糊,而是一种用线性分布的权重函数代替恒值权重,不过那个算法里面没有浮点运算,并且还存在比Paint.net里的代码快很多即执行时间于半径无关的优化算法,而且该优化算法比任何真正的高斯模糊优化算法要快1倍多,而效果上区别不大,可作为实时性特别强的场合的备用算法。

    同样,提供个编译好的文件给有兴趣研究该算法的朋友看看效果:

   

    

 

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

 

转载于:https://www.cnblogs.com/Imageshop/p/3145216.html

你可能感兴趣的文章
HDU_2689_Sort it
查看>>
urllib模块使用笔记
查看>>
mysql 连接慢的问题(超过了1秒)
查看>>
1297. [SCOI2009]迷路【矩阵乘法】
查看>>
Linux嵌入式GDB调试环境搭建
查看>>
java分析jvm常用指令
查看>>
【Linux】Linux 在线安装yum
查看>>
oracle 管理操作 (转)
查看>>
DEV 等待窗口
查看>>
实验03博客园总结
查看>>
VS2017发布微服务到docker
查看>>
lombok
查看>>
Dev-FAT-UAT-PRO
查看>>
Maven, IntellJ Idea 配置注意点
查看>>
Android开发学习总结(五)——Android应用目录结构分析(转)
查看>>
观察者模式
查看>>
[PHP]PHP rpc框架hprose测试
查看>>
Atom 编辑器系列视频课程
查看>>
C#三种定时器
查看>>
范数 L1 L2
查看>>