matlab ahe,基于直方图的图像增强算法(HE、CLAHE、Retinex)之(二)
作为图像增强算法系列的第二篇文章,下面我们将要介绍功能强大、用途广泛、影响深远的对比度有限的自适应直方图均衡(CLAHE,Contrast Limited Adaptive Histogram Equalization)算法。尽管最初它仅仅是被当作一种图像增强算法被提出,但是现今在图像去雾、低照度图像增强,水下图像效果调节、以及数码照片改善等方面都有应用。这个算法的算法原理看似简单,但是实现起来却并不那么容易。我们将结合相应的Matlab代码来对其进行解释。希望你在阅读本文之前对朴素的直方图均衡算法有所了解,相关内容可以参见本系列的前一篇文章:
先来看一下待处理的图像效果:
下面是利用CLAHE算法处理之后得到的两个效果(后面我们还会具体介绍我们所使用的策略):
效果图A 效果图B
对于一幅图像而言,它不同区域的对比度可能差别很大。可能有些地方很明亮,而有些地方又很暗淡。如果采用单一的直方图来对其进行调整显然并不是最好的选择。于是人们基于分块处理的思想提出了自适应的直方图均衡算法AHE。维基百科上说的也比较明白:AHE improves on this by transforming each pixel with a transformation function derived from a neighbourhood region. 但是这种方法有时候又会将一些噪声放大,这是我们所不希望看到的。于是荷兰乌得勒支大学的Zuiderveld教授又引入了CLAHE,利用一个对比度阈值来去除噪声的影响。特别地,为了提升计算速度以及去除分块处理所导致的块边缘过渡不平衡效应,他又建议采用双线性插值的方法。关于算法的介绍和描述,下面这两个资源已经讲得比较清楚。
[1] https://en.wikipedia.org/wiki/Adaptive_histogram_equalization#Contrast_Limited_AHE
[2] K. Zuiderveld: Contrast Limited Adaptive Histogram Equalization. In: P. Heckbert: Graphics Gems IV, Academic Press 1994 (http://www.docin.com/p-119164091.html)
事实上,尽管这个算法原理,然而它实现起来却仍然有很多障碍。但在此之前,笔者还需说明的是,Matlab中已经集成了实现CLAHE的函数adapthisteq(),如果你仅仅需要一个结果,其实直接使用这个函数就是最好的选择。我给出一些示例代码用以生成前面给出之效果。函数adapthisteq()只能用来处理灰度图,如果要处理彩色图像,则需要结合自己编写的代码来完成。上一篇文章介绍了对彩色图像进行直方图均衡的两种主要策略:一种是对R、G、B三个通道分别进行处理;另外一种是转换到另外一个色彩空间中再进行处理,例如HSV(转换后只需对V通道进行处理即可)。
首先,我们给出对R、G、B三个通道分别使用adapthisteq()函数进行处理的示例代码:
img = imread(‘space.jpg‘);
rimg = img(:,:,1);
gimg = img(:,:,2);
bimg = img(:,:,3);
resultr = adapthisteq(rimg);
resultg = adapthisteq(gimg);
resultb = adapthisteq(bimg);
result = cat(3, resultr, resultg, resultb);
imshow(result);上述程序之结果效果图A所示。
下面程序将原图像的色彩空间转换到LAB空间之后再对L通道进行处理。
clear;
img = imread(‘space.jpg‘);
cform2lab = makecform(‘srgb2lab‘);
LAB = applycform(img, cform2lab);
L = LAB(:,:,1);
LAB(:,:,1) = adapthisteq(L);
cform2srgb = makecform(‘lab2srgb‘);
J = applycform(LAB, cform2srgb);
imshow(J);
上述程序所得之结果如图B所示。
如果你希望把这个算法进一步提升和推广,利用用于图像去雾、低照度图像改善和水下图像处理,那么仅仅知其然是显然不够的,你还必须知其所以然。希望我下面一步一步实现的代码能够帮你解开这方面的困惑。鉴于前面所列之文献已经给出了比较详细的算法描述,下面将不再重复这部分内容,转而采用Matlab代码来对其中的一些细节进行演示。
首先来从灰度图的CLAHE处理开始我们的讨论。为此清理一下Matlab的环境。然后,读入一张图片(并将其转化灰度图),获取图片的长、宽、像素灰度的最大值、最小值等信息。
clc;
clear all;
Img = rgb2gray(imread(‘space.jpg‘));
[h,w] = size(Img);
minV = double(min(min(Img)));
maxV = double(max(max(Img)));
imshow(Img);图像的初始状态显示如下。此外该图的 Height = 395,Width = 590,灰度最大值为255,最小值为8。
我们希望把原图像水平方向分成8份,把垂直方向分成4份,即原图将被划分成4 × 8 = 32个SubImage。然后可以算得每个块(tile)的height = 99,width = 74。注意,由于原图的长、宽不太可能刚好可被整除,所以我在这里的处理方式是建立一个稍微大一点的图像,它的宽和长都被补上了deltax和deltay,以保证长、宽都能被整除。
NrX = 8;
NrY = 4;
HSize = ceil(h/NrY);
WSize = ceil(w/NrX);
deltay = NrY*HSize - h;
deltax = NrX*WSize - w;
tmpImg = zeros(h+deltay,w+deltax);
tmpImg(1:h,1:w) = Img;
对长和宽进行填补之后,对新图像的一些必要信息进行更新。
new_w = w + deltax;
new_h = h + deltay;
NrPixels = WSize * WSize;
然后指定图像中直方图横坐标上取值的计数(也就指定了统计直方图上横轴数值的间隔或计数的精度),对于色彩比较丰富的图像,我们一般都要求这个值应该大于128。
% NrBins - Number of greybins for histogram ("dynamic range")
NrBins = 256;
然后用原图的灰度取值范围重新映射了一张Look-Up Table(当然你也可以直接使用0~255这个范围,这取决你后续建立直方图的具体方法),并以此为基础为每个图像块(tile)建立直方图。
LUT = zeros(maxV+1,1);
for i=minV:maxV
LUT(i+1) = fix(i - minV);%i+1
end
Bin = zeros(new_h, new_w);
for m = 1 : new_h
for n = 1 : new_w
Bin(m,n) = 1 + LUT(tmpImg(m,n) + 1);
end
end
Hist = zeros(NrY, NrX, 256);
for i=1:NrY
for j=1:NrX
tmp = uint8(Bin(1+(i-1)*HSize:i*HSize, 1+(j-1)*WSize:j*WSize));
%tmp = tmpImg(1+(i-1)*HSize:i*HSize,1+(j-1)*WSize:j*WSize);
[Hist(i, j, :), x] = imhist(tmp, 256);
end
end
Hist = circshift(Hist,[0, 0, -1]);
注意:按通常的理解,上面这一步我们应该建立的直方图(集合)应该是一个4×8=32个长度为256的向量(你当然也可以这么做)。但由于涉及到后续的一些处理方式,我这里是生成了一个长度为256的4×8矩阵。Index = 1的矩阵其实相当于是整张图像各个tile上灰度值=0的像素个数计数。例如,我们所得的Hist(:, :, 18)如下。这就表明图像中最左上角的那个tile里面灰度值=17的像素有零个。同理,它右边的一个tile则有46个灰度值=17的像素。
Hist(:,:,18) =
0 46 218 50 14 55 15 7
0 0 21 18 114 15 74 73
0 1 0 0 2 67 124 82
0 0 0 0 0 1 9 2
然后来对直方图进行裁剪。Matlab中内置的函数adapthisteq()中cliplimit参数的取值范围是0~1。这里我们所写的方法则要求该值>1。当然这完全取决你算法实现的策略,它们本质上并没有差异。然后我们将得到新的(裁剪后的)映射直方图。
ClipLimit = 2.5;
ClipLimit = max(1,ClipLimit * HSize * WSize/NrBins);
Hist = clipHistogram(Hist,NrBins,ClipLimit,NrY,NrX);
Map=mapHistogram(Hist, minV, maxV, NrBins, NrPixels, NrY, NrX);
最后,也是最关键的步骤,我们需要对结果进程插值处理。这也是Zuiderveld设计的算法中最复杂的部分。
yI = 1;
for i = 1:NrY+1
if i == 1
subY = floor(HSize/2);
yU = 1;
yB = 1;
elseif i == NrY+1
subY = floor(HSize/2);
yU = NrY;
yB = NrY;
else
subY = HSize;
yU = i - 1;
yB = i;
end
xI = 1;
for j = 1:NrX+1
if j == 1
subX = floor(WSize/2);
xL = 1;
xR = 1;
elseif j == NrX+1
subX = floor(WSize/2);
xL = NrX;
xR = NrX;
else
subX = WSize;
xL = j - 1;
xR = j;
end
UL = Map(yU,xL,:);
UR = Map(yU,xR,:);
BL = Map(yB,xL,:);
BR = Map(yB,xR,:);
subImage = Bin(yI:yI+subY-1,xI:xI+subX-1);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
sImage = zeros(size(subImage));
num = subY * subX;
for i = 0:subY - 1
inverseI = subY - i;
for j = 0:subX - 1
inverseJ = subX - j;
val = subImage(i+1,j+1);
sImage(i+1, j+1) = (inverseI*(inverseJ*UL(val) + j*UR(val)) ...
+ i*(inverseJ*BL(val) + j*BR(val)))/num;
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
output(yI:yI+subY-1, xI:xI+subX-1) = sImage;
xI = xI + subX;
end
yI = yI + subY;
end这个地方,作者原文中已经讲得比较清楚了,我感觉我也没有必要狗尾续貂,班门弄斧了。下面截作者原文中的一段描述,足以说明问题。
最后来看看我们处理的效果如何(当然,这里还需要把之前我们填补的部分裁掉)。
output = output(1:h, 1:w);
figure, imshow(output, []);
来看看结果吧~可以对比一下之前的灰度图,不难发现,图像质量已有大幅改善。
===========从来不看博客私信的主页君说:通常我会把我所了解的算法尽可能讲清楚,但除了必要的辅助演示之代码,我不会再额外提供源码下载,无论什么时候人都应该靠自己,只有当你能真正写出代码时,那个代码才是属于你的。===========无冥冥之志者,无昭昭之明,无惛惛之事者,无赫赫之功。===========如果你是图像处理的同道中人,欢迎加入图像处理学习群(529549320)。为避免广告推销等骚扰信息,入群需回答门槛问题(例如:x平方的一阶导数等于多少?有木有感觉so easy,不过不要笑,管理员收到的答案是五花八门的!注意每人仅有一次尝试机会哦)。Cheers~
更多有趣有用的图像处理算法还可以参考我的《数字图像处理原理与实践(Matlab版)》
原文:http://blog.csdn.net/baimafujinji/article/details/50660189
matlab ahe,基于直方图的图像增强算法(HE、CLAHE、Retinex)之(二)相关推荐
- 基于直方图的图像增强算法(HE、CLAHE)之(二)
作为图像增强算法系列的第二篇文章,下面我们将要介绍功能强大.用途广泛.影响深远的对比度有限的自适应直方图均衡(CLAHE,Contrast Limited Adaptive Histogram Equ ...
- 基于直方图的图像增强算法(HE、CLAHE、Retinex)
直方图是图像色彩统计特征的抽象表述.基于直方图可以实现很多有趣的算法.例如,图像增强中利用直方图来调整图像的对比度.有人利用直方图来进行大规模无损数据隐藏.还有人利用梯度直方图HOG来构建图像特征进而 ...
- 小波图像增强matlab,用Matlab实现基于小波变换的图像增强技术
用Matlab实现基于小波变换的图像增强技术 管琼 [期刊名称]<科技资讯> [年(卷),期]2013(000)025 [摘要]小波是有限宽度的基函数,这些基函数不仅在频率上而且在位置上是 ...
- 基于采样的规划算法之RRT家族(二):RRT-Connect
RRT家族和 A* 家族的共性是:都是生成一棵不断靠近目标的路径树.只是生成的方式不同,RRT家族通过随机采样结点来拓展路径树, A* 家族则基于贪心策略在规划问题图(graph)上搜索叶点来拓展路径 ...
- 惯性gps组合导航matlab,Strong-tracking-filter 基于强跟踪滤波算法的惯性加GPS组合导航matlab仿真程序 238万源代码下载- www.pudn.com...
文件名称: Strong-tracking-filter下载 收藏√ [ 5 4 3 2 1 ] 开发工具: matlab 文件大小: 82 KB 上传时间: 2013-09-01 下载次数 ...
- matlab实现基于DPCA密度峰值算法的图像分割
matlab代码如下 图像最好小一点,不然因为那个距离矩阵为(mn)(m*n)真的很慢很慢,运算上亿次了,电脑根本跑不动. clear close allIy=imread('1.jpg'); fig ...
- COI实验室技能:常见的图像增强算法(含MATLAB代码)
COI实验室技能:常见的图像增强算法(含MATLAB代码) 成像系统采集到的图片有时不一定具有很好的图像质量,往往需要进行一些图像增强的操作.本文主要整理了几种常见的图像增强算法,包括:同态滤波. ...
- matlab自定义灰度变换,MATLAB实现基于灰度变换图像增强孙明朗140303006
<MATLAB实现基于灰度变换图像增强孙明朗140303006>由会员分享,可在线阅读,更多相关<MATLAB实现基于灰度变换图像增强孙明朗140303006(8页珍藏版)>请 ...
- 图像去雾(二)Retinex图像增强算法
前一段时间研究了一下图像增强算法,发现Retinex理论在彩色图像增强.图像去雾.彩色图像恢复方面拥有很好的效果,下面介绍一下我对该算法的理解. Retinex理论 Retinex理论始于Land和M ...
最新文章
- 服务器云ide_语言服务器协议如何影响IDE的未来
- 人工智能的恶意用途:预测、预防和缓解
- OS- -计算机硬件简介
- Component Configuration.js - 所有支持属性列表 - configuration priority
- 斯坦福大学深度学习视频(CS231n课程)
- eclipse中下载spring-tool-suite插件遇到的问题
- 苹果发布iOS 13.2测试版 iPhone 11拍照更牛了
- JBoss的部署机制
- 自己使用过比较好用的VSCode插件
- android modbus 串口,手机Modbus 安卓Modbus调试软件
- yolov3的loss计算公式
- 基于Kinect 2.0深度图像的快速体积测量
- php doctrine 使用,php – Doctrine 2 – 多数据库配置和使用
- 匈牙利命名法鼻祖---查尔斯·西蒙尼
- GN_1_在Ubuntu22.04安装GN
- 【video frame interpolation系列1】背景知识: forward and backward image warping (图像扭曲/变换)
- jdbc:mysql://localhost:3306/webshopping?useUnicode=trueamp;characterEncoding=UTF-8
- Anti_TexturePacker工具
- APIO2018 新家
- JAVA学习笔记—IO流
热门文章
- labview制成app_有没有大佬知道labview能开发app么?
- ROS vim退出快捷键
- 【SciPy库】scipy.optimize.fmin_l_bfgs_b进行L-BFGS优化
- 微商如何做百度引流?微商百度引流怎么做?
- 终端运行pip提示:LookupError: unknown encoding: cp65001 解决方案
- 段码液晶屏笔段电压范围_可以用段码液晶屏的驱动方式驱动数码管屏吗?
- 孙亚芳-探索以色列崛起之迹
- sklearn中的fit_transform、获取特征、标签转换
- 根据起点坐标、两点距离、方向角,计算另一点坐标
- 每周全球科技十大新闻(2020.8.24-8.30)