对比度受限的自适应直方图均衡化(CLAHE)
直方图均衡化(HE)是一种很常用的直方图类方法,基本思想是通过图像的灰度分布直方图确定一条映射曲线,用来对图像进行灰度变换,以达到提高图像 对比度的目的。该映射曲线其实就是图像的累计分布直方图(CDF)(严格来说是呈正比例关系)。然而HE是对图像全局进行调整的方法,不能有效地提高局部 对比度,而且某些场合效果会非常差。如:
上述原图和HE结果图的直方图分别为:
因为从原图的直方图中求取的映射函数(CDF)形状为:
将它作用于原图像会导致直方图被整体右移,没有充分利用整个灰度动态范围。
为了提高图像的局部对比度,有人提出将图像分成若干子块,对子块进行HE处理,这便是AHE(自适应直方图均衡化),使用AHE处理上图得到:
结果直方图:
可 以看出结果图像的灰度较好地分布在了全部动态范围上。从结果图像上也可以看出,局部对比度的确得到了提高,视觉效果要优于HE。但是仍然有个问题:AHE 对局部对比度提高过大,导致图像失真。看看背景区,本来的黑色背景现在已经变成白色了,原因是因为背景区中的局部子块统计得到的直方图在0灰度处幅值太高 (实际上全黑子图基本上就集中在0灰度处),这样导致映射曲线斜率过高,将所有灰度值都映射到整个灰度轴的右侧,所以结果图中背景偏白(另外局部对比度过 高还会放大图像中的噪声,不过上图并没有体现这一点)。
为了解决这个问题,我们必须对局部对比度进行限制,这就是我们今天的主题:CLAHE。
从HE中我们知道,映射曲线T与CDF关系为:(M为最高灰度值,N为像素个数)
限制对比度,其实就是限制CDF的斜率,又因累计分布直方图CDF是灰度直方图Hist的积分:
反过来:
也就是说限制CDF的斜率就相当于限制Hist的幅度。
因此我们需要对子块中统计得到的直方图进行裁剪,使其幅值低于某个上限,当然裁剪掉的部分又不能扔掉,我们还需要将这部分裁剪值均匀地分布在整个灰度区间上,以保证直方图总面积不变,如下图:
可以看到,这时直方图又会整体上升了一个高度,貌似会超过我们设置的上限。其实在具体实现的时候有很多解决方法,你可以多重复几次裁剪过程,使得上升的部分变得微不足道,或是用另一种常用的方法:
设 裁剪值为ClipLimit,求直方图中高于该值的部分的和totalExcess,此时假设将totalExcess均分给所有灰度级, 求出这样导致的直方图整体上升的高度L=totalExcess/N,以upper= ClipLimit-L为界限对直方图进行如下处理:
(1)若幅值高于ClipLimit,直接置为ClipLimit;
(2)若幅值处于Upper和ClipLimit之间,将其填补至ClipLimit;
(3)若幅值低于Upper,直接填补L个像素点;
经过上述操作,用来填补的像素点个数通常会略小于totalExcess,也就是还有一些剩余的像素点没分出去,这个剩余来自于(1)(2)两处。这时我们可以再把这些点均匀地分给那些目前幅值仍然小于ClipLimit的灰度值。
这里给出一段代码:(摘自Matlab的adapthisteq.m),描述的就是上述过程:
% total number of pixels overflowing clip limit in each bin
totalExcess = sum(max(imgHist - clipLimit,)); % clip the histogram and redistribute the excess pixels in each bin
avgBinIncr = floor(totalExcess/numBins);
upperLimit = clipLimit - avgBinIncr; % bins larger than this will be
% set to clipLimit % this loop should speed up the operation by putting multiple pixels
% into the "obvious" places first
for k=:numBins
if imgHist(k) > clipLimit
imgHist(k) = clipLimit;
else
if imgHist(k) > upperLimit % high bin count
totalExcess = totalExcess - (clipLimit - imgHist(k));
imgHist(k) = clipLimit;
else
totalExcess = totalExcess - avgBinIncr;
imgHist(k) = imgHist(k) + avgBinIncr;
end
end
end % this loops redistributes the remaining pixels, one pixel at a time
k = ;
while (totalExcess ~= )
%keep increasing the step as fewer and fewer pixels remain for
%the redistribution (spread them evenly)
stepSize = max(floor(numBins/totalExcess),);
for m=k:stepSize:numBins
if imgHist(m) < clipLimit
imgHist(m) = imgHist(m)+;
totalExcess = totalExcess - ; %reduce excess
if totalExcess ==
break;
end
end
end k = k+; %prevent from always placing the pixels in bin #
if k > numBins % start over if numBins was reached
k = ;
end
end
CLAHE和AHE中另一个重要的问题:插值。
将图像进行分块处理,若每块中的像素点仅通过该块中的映射函数进行变换,则会导致最终图像呈块状效应:
为了解决这个问题,我们需要利用插值运算,也就是每个像素点出的值由它周围4个子块的映射函数值进行双线性插值得到,如下图:
上图中,为了求蓝色像素点处的值,需要利用它周围四个子块的映射函数分别做变换得到四个映射值,再对这四个值做双线性插值即可。
当 然对于边界处的像素点则不是通过四个子块进行插值,如上图红色像素点直接以一个子块的映射函数做变换,绿色像素则以两个子块做映射函数做线性插值。这里讲 的边界处像素是指落在图像左上角,左下角、右上角,右下角的四个子块中心像素点围成的四边形之外的像素。如下图,将图像分为8x8子块,边界像素即落在灰 色区域的像素点。
利用插值对图像进行处理的整体架构如下:
for (Y = ; Y <= TileY; Y++) //TileY为Y方向网格数
{
if (Y == )
{
SubY = TileYDim >> ; YU = ; YB = ;
}
else if (Y == TileY)
{
SubY = TileYDim >> ; YU = TileY-; YB = YU;
}
else
{
SubY = TileYDim; YU = Y - ; YB = Y;
}
for (X = ; X <= TileX; X++) //TileX为X方向网格数
{
if (X == )
{
SubX = TileXDim >> ; XL = ; XR = ;
}
else if (X == TileX)
{
SubX = TileXDim >> ; XL = TileX - ; XR = XL;
}
else
{
SubX = TileXDim; XL = X - ; XR = X;
}
MapLU = &pMapArray[numBins * (YU * TileX + XL)];//左上角映射函数
MapRU = &pMapArray[numBins * (YU * TileX + XR)];//右上角映射函数
MapLB = &pMapArray[numBins * (YB * TileX + XL)];//左下角映射函数
MapRB = &pMapArray[numBins * (YB * TileX + XR)];//右下角映射函数
Interpolate(pImPointer,Stride,Channel,MapLU,MapRU,MapLB,MapRB,SubX,SubY,aLUT);//插值
pImPointer += SubX;
}
pImPointer+=(SubY-)*Stride;
}
注意的是,上述循环需要(TileX+1)*(TileY+1)次,而不是TileX*TileY次。,原因很简单,以X方向为例,两侧边界处的半宽子块(灰色区)也各需要处理一次,如下图:
通过双线性插值可以基本消除块状效应:
对
于彩色图像,三通处理分开处理会导致严重的偏色,故我们可以将其进行颜色空间转换(如RGB转为HSV),然后仅对亮度分量处理,再反变换回RGB空间。
不过网上有高手将R、G、B统一处理[2](也就相当于把一个像素点拆成三个像素点),这样得到的效果也不错,而且省去了颜色空间转换的时间,我们这里也
仿照他来吧:
另外,CLAHE对雾天图像处理效果也不错:
至于编程,我基本就是翻译adaphisteq.m,另外还有一些参考资源:CLAHE代码(MATLAB)
这里给出编译好的文件,有兴趣的朋友可以下载看看:ImageProcess(CLAHE)
参考:
[1]https://en.wikipedia.org/wiki/Adaptive_histogram_equalization
[2]http://www.cnblogs.com/Imageshop/archive/2013/04/07/3006334.html
对比度受限的自适应直方图均衡化(CLAHE)的更多相关文章
- 图像增强 | CLAHE 限制对比度自适应直方图均衡化
1 基本概述 CLAHE是一个比较有意思的图像增强的方法,主要用在医学图像上面.之前的比赛中,用到了这个,但是对其算法原理不甚了解.在这里做一个复盘. CLAHE起到的作用简单来说就是增强图像的对比度 ...
- 【图像增强】CLAHE 限制对比度自适应直方图均衡化
文章目录: 目录 1 基本概述 2 竞赛中的CLAHE实现 3 openCV绘制直方图 4 对比度Contrast 5 Contrast Stretching 6 Histogram Equaliza ...
- 机器学习进阶-直方图与傅里叶变化-直方图均衡化 1.cv2.equalizeHist(进行直方图均衡化) 2. cv2.createCLAHA(用于生成自适应均衡化图像)
1. cv2.equalizeHist(img) # 表示进行直方图均衡化 参数说明:img表示输入的图片 2.cv2.createCLAHA(clipLimit=8.0, titleGridSiz ...
- opencv —— equalizeHist 直方图均衡化实现对比度增强
直方图均匀化简介 从这张未经处理的灰度图可以看出,其灰度集中在非常小的一个范围内.这就导致了图片的强弱对比不强烈. 直方图均衡化的目的,就是把原始的直方图变换为在整个灰度范围(0~255)内均匀分布的 ...
- S0.6 直方图均衡化
S0.6 直方图均衡化 直方图均衡化能提高图像的质量 累积直方图 这是后面均衡化所要知道的先验知识. 如果说直方图统计的是等于像素值的数量,那么累积直方图统计的就是小于等于像素值的数量 均衡化步骤 我 ...
- OpenCV计算机视觉学习(9)——图像直方图 & 直方图均衡化
如果需要处理的原图及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice 1, ...
- OpenCV2马拉松第9圈——再谈对照度(对照度拉伸,直方图均衡化)
收入囊中 lookup table 对照度拉伸 直方图均衡化 葵花宝典 lookup table是什么东西呢? 举个样例,假设你想把图像颠倒一下,f[i] = 255-f[i],你会怎么做? for( ...
- 【16位RAW图像处理三】直方图均衡化及局部直方图均衡用于16位图像的细节增强。
通常我们生活中遇到的图像,无论是jpg.还是png或者bmp格式,一般都是8位的(每个通道的像素值范围是0-255),但是随着一些硬件的发展,在很多行业比如医疗.红外.航拍等一些场景下,拥有更宽的量化 ...
- 图像增强算法(直方图均衡化、拉普拉斯、Log、伽马变换)
一.图像增强算法原理 图像增强算法常见于对图像的亮度.对比度.饱和度.色调等进行调节,增加其清晰度,减少噪点等.图像增强往往经过多个算法的组合,完成上述功能,比如图像去燥等同于低通滤波器,增加清晰度则 ...
随机推荐
- AspNetPager真假分页对照实例
从開始学习BS已经有一段时间了. 对于BS的设计,都是进行的网页设计,当中包含从数据库中取出来的数据.显示在页面上.曾经在CS中,都是使用GridView等表格控件进行显示,因为数据小.并且右側又有滚 ...
- 开源yYmVc项目,邀您和我一起开发:)
打算在闲暇时间写个MVC框架,要有什么功能一步一步边写边加,仿照struts 2 和 spring mvc.假设您感兴趣的话,能够私密我,给您加入key:). 欢迎您的到来~ 项目放在基于GIT的CS ...
- 为经典版eclipse添加web and JavaEE插件
地址:http://download.eclipse.org/releases/juno. 选择Web,XML,Java EE and OSGI Enterprise Development,之后ne ...
- iOS 沙盒文件操作
//获得document +(NSString *)documentsPath { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDoc ...
- Response.ContentLength获取文件大小
Response.ContentLength返回的是请求内容的大小,而不是请求文件的大小,当我们用Http断点续传的时候,比如文件大小为100M,第一次下载的时候ContentLength的大小就是1 ...
- 2016/2/25 1、<表单验证<form></form> 2、正则表达式 3、事件
1.<表单验证<form></form> (1).非空验证(去空格) (2).对比验证(跟一个值对比) (3).范围验证(根据一个范围进行判断) (4).固定格式验证:电 ...
- Hbase权限配置以及使用手册
1.Hbase权限控制简介 Hbase的权限控制是通过AccessController Coprocessor协处理器框架实现的,可实现对用户的RWXCA的权限控制. 2.配置 配置hbase-sit ...
- VS2013如何调用别人发布的WebService程序
这篇经验会告诉我们如何调用别人发布的WebService,并且需要注意的事项.现在就拿获取天气预报的接口举例,因为文中不允许有链接,所以在下文图中有WebService链接的地址. 工具/原料 VS2 ...
- IntentFilter打印方法
转载请注明出处:http://blog.csdn.net/droyon 在我们进行Android应用程序开发时.我们有时须要对某个对象进行打印输出.以方便我们进行调试. 非常多对象实现了toStrin ...
- python ConfigParser模块 配置文件解析
ConfigParser模块主要是用来解析配置文件的模块,像mysql,或者win下面的ini文件等等 下面我们来解析mysql的配置文件my.cnf my.cnf配置文件内容 [mysqld] da ...