在限制对比度自适应直方图均衡化算法原理、实现及效果一文中针对全局直方图均衡化的一些缺点,提出了分块的自适应均衡化技术,很好的克服了全局直方图均衡化的一些缺点,对于图像加强也有着显著的做用,咱们稍微回顾下CLAHE的算法流程,简单的能够用下面的过程描述:html
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算法的核心,就直方图数据从新分布。app
咱们回顾一下PS的调整菜单,除了直方图均衡化是一键式菜单(即点击无可调参数界面,实际上直翻图均衡化仍是有的,在有选区的状况下回弹出一个框),还有另外三个经常使用的一键操做,即:自动色阶、自动对比度以及自动颜色。从本质上讲,这三个算法同直方图均衡化同样,在内部也是一个直方图从新分布和像素从新映射的过程,所以,若是把这里的MakeMapping函数总映射过程替换他们三者中的某一种会是什么状况和效果呢, 这实际上是了解了CLAHE算法的原理后,很天然的能拓宽和联想到的。 函数
关于自动色阶和自动对比度的原理,我在调整图像- 自动对比度、自动色阶算法一文中已经有了较为详细的实现,而关于自动颜色的原理,目前为止我彷佛没有发现有任何人对其进行了详细的解释。我在Imageshop中也只是作了一种简单的模拟,这里就不提了。 post
以自动色阶为例,上述MakeMapping函数的形式可能以下所示:url
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做为自动色阶的一个调节参数也是顺其天然的一个事情了。spa
在上述代码代码中,if (MaxB!=MinB)的判断主要是防止出现除以0的错误,同时在这种状况发生时,必须把直方图中的全部数据都设置为MaxB(其实这种状况发生时,原始直方图数据中必然是大部分都等于MaxB,但可能仍是有部分是不一样的,若是不赋值为MaxB,处理的结果图像中会出现莫名其妙的纹理图)。code
把上述代码替换掉CLAHE算法中相应的部分,保持插值等代码不动,可得到以下效果:htm
原图 块大小为200,CutLimit =0.01 处理后结果blog
由上面的图能够看出,处理先后的加强效果仍是很明显的,整个图像显得更清晰。
根据上述代码分析,这样处理的效果确定是原先图像中的黑的部分更黑,白的部分更白,所以,对比度更加宣明。为了能控制整个对比度调节的程度,咱们新增长一个参数,用来调节在最后隐射阶段的最大值。我这里作了以下的处理:
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 转载请保留本行信息************************