局部自适应自动色阶/对比度算法在图像增强上的应用。

    在限制对比度自适应直方图均衡化算法原理、实现及效果一文中针对全局直方图均衡化的一些缺点,提出了分块的自适应均衡化技术,很好的克服了全局直方图均衡化的一些缺点,对于图像增强也有着显著的作用,我们稍微回顾下CLAHE的算法流程,简单的可以用下面的过程描述:

for each Tile in Image 
{
   Calcuate( HistGram);
   ClipHistGram(HistGram, ClipLimit);
   MakeMapping(HistGram);
}
for each Tile in Image 
    for each Pixel in Tile
        use bilinear interpolation between four adjacent HistGram info to generate new Pixel

   原始的直方图均衡化算法的核心在上述 MakeMapping(HistGram)函数中得以体现,

void MakeMapping(int* Histgram)
{
    int I, Sum = 0, Amount = 0;
    for (I = 0; I < 256; I++) Amount += Histgram[I];
    for (I = 0; I < 256; I++)
    {
        Sum += Histgram[I];
        Histgram[I] = Sum * 255/ Amount;     // 计算分布
    }
}

上述Histgram[I] = Sum * 255/ Amount;   一句就是HE算法的核心,就直方图数据重新分布。

    我们回顾一下PS的调整菜单,除了直方图均衡化是一键式菜单(即点击无可调参数界面,实际上直翻图均衡化还是有的,在有选区的情况下回弹出一个框),还有另外三个常用的一键操作,即:自动色阶、自动对比度以及自动颜色。从本质上讲,这三个算法同直方图均衡化一样,在内部也是一个直方图重新分布和像素重新映射的过程,因此,如果把这里的MakeMapping函数总映射过程替换他们三者中的某一种会是什么情况和效果呢, 这其实是了解了CLAHE算法的原理后,很自然的能拓宽和联想到的。

     关于自动色阶和自动对比度的原理,我在调整图像- 自动对比度、自动色阶算法一文中已经有了较为详细的实现,而关于自动颜色的原理,目前为止我似乎没有发现有任何人对其进行了详细的解释。我在Imageshop中也只是做了一种简单的模拟,这里就不提了。

     以自动色阶为例,上述MakeMapping函数的形式可能如下所示:

void MakeMapping(int* Histgram,float CutLimit=0.01)
{
    int I, Sum = 0, Amount = 0;
    const int Level = 256;
    for (I = 0; I < Level; I++) Amount += Histgram[I];
    int MinB,MaxB;
    for (I = 0; I < Level; I++)
    {
        Sum = Sum + Histgram[I];
        if (Sum >= Amount * CutLimit )
        {
            MinB = I;                              
            break;
        }
    }  
    Sum = 0;
    for(I = Level-1; I >= 0; I--)
    {
        Sum = Sum +Histgram[I];
        if (Sum >= Amount * CutLimit )
        {
            MaxB = I ;                            
            break;
        }   
    }
        
    if (MaxB!=MinB)
    {
        for (I = 0; I < Level; I++)
        {
            if (I<MinB)
                Histgram[I] =0;
            else if(I>MaxB)
                Histgram[I]=255;
            else
                Histgram[I] = 255* (I - MinB) / (MaxB - MinB) ;     
        }
    }
    else
    {
        for (I = 0; I < Level; I++) Histgram[I]=MaxB;        //     必须有,不然会有一些图像平坦的部位效果出错
    }
}

  注意在这个函数里我增加了CutLimit参数,这个参数名和CLAHE的一样,实际上是因为自动色阶这种工作方式,就是对直方图的一种裁剪,因此CLAHE算法的ClipHistGram过程就可以舍去了,而把CutLimit作为自动色阶的一个调节参数也是顺其自然的一个事情了。

      在上述代码代码中,if (MaxB!=MinB)的判断主要是防止出现除以0的错误,同时在这种情况发生时,必须把直方图中的所有数据都设置为MaxB(其实这种情况发生时,原始直方图数据中必然是大部分都等于MaxB,但可能还是有部分是不同的,如果不赋值为MaxB,处理的结果图像中会出现莫名其妙的纹理图)。

      把上述代码替换掉CLAHE算法中相应的部分,保持插值等代码不动,可获得如下效果:

          原图

                 块大小为200,CutLimit =0.01 处理后结果

     由上面的图可以看出,处理前后的增强效果还是很明显的,整个图像显得更清晰。

     根据上述代码分析,这样处理的效果肯定是原先图像中的黑的部分更黑,白的部分更白,因此,对比度更加宣明。为了能控制整个对比度调节的程度,我们新增加一个参数,用来调节在最后隐射阶段的最大值。我这里做了如下的处理:

void MakeMapping(int* Histgram,float CutLimit=0.01,float Contrast = 1)
{
    int I, Sum = 0, Amount = 0;
    const int Level = 256;
    for (I = 0; I < Level; I++) Amount += Histgram[I];
    int MinB =0 ,MaxB=255;
    int Min = 0,Max=255;
    for (I = 0; I < Level; I++)
    {
        if  (Histgram[I]!=0) 
        {
            Min = I ;
            break;
        }
    }

    for(I = Level-1; I >= 0; I--)
    {
        if  (Histgram[I]!=0) 
        {
            Max = I ;
            break;
        }
    }
    for (I = 0; I < Level; I++)
    {
        Sum = Sum + Histgram[I];
        if (Sum >= Amount * CutLimit )
        {
            MinB = I;                              
            break;
        }
    }
  
    Sum = 0;
    for(I = Level-1; I >= 0; I--)
    {
        Sum = Sum +Histgram[I];
        if (Sum >= Amount * CutLimit )
        {
            MaxB = I ;                            
            break;
        }   
    }
    int Delta = (Max - Min) * Contrast * 0.5  ;
    Min = Min - Delta;
    Max = Max +    Delta ;
    if (Min    < 0) Min = 0;
    if (Max > 255) Max = 255;

    if (MaxB!=MinB)
    {
        for (I = 0; I < Level; I++)
        {
            if (I<MinB)
                Histgram[I] =Min;
            else if(I>MaxB)
                Histgram[I]=Max;
            else
                Histgram[I] = (Max-Min)* (I - MinB) / (MaxB - MinB) + Min ;     
        }
    }
    else
    {
        for (I = 0; I < Level; I++) Histgram[I]=MaxB;        //     必须有,不然会有一些图像平坦的部位效果出错
    }
}

首先分析获得原始块中的最大值和最小值,然后再这个的基础上按照设定的参数向黑和白两个方向同等程度扩展,这样就避免了无论什么情况下的分布都直接扩展到0-255内。有效的抑制了噪音的放大。

  修改后,我们看看一些效果:

         原图

                    CutLimit =0.01,Contrast=1

                    CutLimit =0.05,Contrast=1

    分析:上面这幅图原始图像整体就比较亮,因此,在Contrast=1的时候,很多块调整后的Min=0,Max也等于255了,因此继续增加Contrast参数,图像的效果基本没有什么变化了。而增加CutLimit值使得图像的映射表由两个极端向中间靠拢,图像会稍微显得浓烈一些。

  原图

                    CutLimit =0.01,Contrast=1

                     CutLimit =0.01,Contrast=2.5    

    而上面这幅图像,则由于整体比较暗,增加Contrast的效果就比较明显了,当Contrast=2.5,图像顶部的一些细节信息也能清晰的表达出来。

    另外,分析原始代码的双线性插值部分可知,在四周边缘处,特备是离边缘小于TileX/2或小于TileY/2的部分,由于其临近信息的缺失,实际上是没有进行双线性插值的,这样对于部分图像,边缘处显得有点不自然,弥补的方式就是在处理前对图像进行扩展,分别向四周扩展TileX/2和TileY/2大小,当然扩展部分的数据需要按照镜像的方式填充数据。

    在贴一些这个算法的处理效果:

   特别是最后一幅图,处理的效果都要比我博客中其他的几种方法来的好,感觉真是帅呆了。

      实际中还发现,如果每个块的大小太小,处理的速度和效果都会有所下降,太大就相当于全局的处理了,因此,一般情况下可取将一副图平均分成约4*4块大小的块大小。同时,调节块大小时还会出现一些点突然过亮或过暗的现象,这个问题可能会影响一部分图的效果。

用C写个DLL,并提供了C#调用的实例:http://files.cnblogs.com/Imageshop/AdaptAutoContrastTest.rar

上图中通道分离选项可以看成是局部自动色阶和自动对比度算法的切换,在勾选通道分离选项时,对于部分图像会发现有偏色的现象,这个现象在PS中使用自动色阶和自动对比度时也会出现。

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏PaddlePaddle

PaddlePaddle发布新版API,简化深度学习编程

PaddlePaddle是百度于2016年9月开源的一款分布式深度学习平台,为百度内部多项产品提供深度学习算法支持。为了使PaddlePaddle更加易用,我们...

3238
来自专栏程序人生 阅读快乐

《算法Ⅰ~Ⅳ(C++实现)——基础、数据结构、排序和搜索 (第三版)》

本书通过C++实现方案以简洁、直接的方式对书中的算法和数据结构进行表述,并向学生提供在实际应用中验证这种方法的手段。

532
来自专栏1007261的专栏

基于图像识别的自动化

导语 在客户端自动化中,如果需要对UI进行操作,控件识别和操作是最基础的能力。在windows标准控件中,我们可以通过FindWindow来找到窗口,FindW...

1.1K7
来自专栏一“技”之长

Cocos2d-x-v3中3D网格特效动画的应用

        基础的动作是对节点整体进行移动,变形等操作,网格特效的原理是将节点分割成多个尺寸相同的网格,根据改变每个网格块的属性使整体节点产生3D的效果。

782
来自专栏AI研习社

一文详解如何用 R 语言绘制热图

AI 研习社按:作为目前最常见的一种可视化手段,热图因其丰富的色彩变化和生动饱满的信息表达被广泛应用于各种大数据分析场景。同时,专用于大数据统计分析、绘图和可视...

3305
来自专栏Deep learning进阶路

caffe随记(二) --- 数据结构简介

caffe随记(二) --- 数据结构简介 注:这篇文章博文我写的内容有点多,建议看一下左上角的目录,对本文结构有个大致了解。 1、Blob Blob其实...

2210
来自专栏人人都是极客

【免费教学】Tensorflow Lite极简入门

边缘计算时代离我们越来越近,当前嵌入式设备的智能框架还是 TensorFlow Lite比较成熟,这里我准备用一系列免费课程和大家一起讨论下 TensorFlo...

922
来自专栏顶级程序员

Caffe源码直播

0.预告 开源项目名称:Caffe—— deep learning framework 语言:C++ 时间:10月22日(周六)早11:00-12:00 参与方...

3728
来自专栏计算机视觉life

自识别标记(self-identifying marker) -(2) 用于相机标定的CALTag介绍

CALTag介绍 CALibration Tag(简记为CALTag)是一种平面自识别标记,专门用于自动化相机标定。这种方法有如下几个必杀技完爆传统的标定方法:...

20110
来自专栏天天P图攻城狮

移动端将胶片底片转为数码照片的尝试

胶片底片需要通过暗室显影才能呈现出色彩,该过程就是传统所说的相片冲洗工艺。本文利用移动端图像处理工具,尝试在手机上实现彩色负片(常用的135mm胶片种类)的数码...

791

扫码关注云+社区