【图像处理算法】直方图均衡化「建议收藏」

【图像处理算法】直方图均衡化「建议收藏」参考文献:RafaelC.Gonzalez,RichardE.Woods,DigitalImageProcessing(ThirdEdition) 胡学龙.数字图像处理(第三版) 左飞.图像处理中的数学修炼目录直方图均衡化的介绍直方图的概念直方图均衡化的理论基础手工实现直方图均衡化MATLAB上实现直方图均衡化直方图均衡化的缺点直方图均衡…

大家好,又见面了,我是你们的朋友全栈君。

参考文献:

  1. Rafael C. Gonzalez, Richard E. Woods,Digital Image Processing (Third Edition)
  2. 胡学龙. 数字图像处理(第三版)
  3. 左飞. 图像处理中的数学修炼

目录

直方图均衡化的介绍

直方图的概念

直方图均衡化的理论基础

手工实现直方图均衡化

MATLAB上实现直方图均衡化

直方图均衡化的缺点


直方图均衡化的介绍

直方图均衡化是一种简单有效的图像增强技术,通过改变图像的直方图来改变图像中各像素的灰度,主要用于增强动态范围偏小的图像的对比度。原始图像由于其灰度分布可能集中在较窄的区间,造成图像不够清晰。例如,过曝光图像的灰度级集中在高亮度范围内,而曝光不足将使图像灰度级集中在低亮度范围内。采用直方图均衡化,可以把原始图像的直方图变换为均匀分布(均衡)的形式,这样就增加了像素之间灰度值差别的动态范围,从而达到增强图像整体对比度的效果。换言之,直方图均衡化的基本原理是:对在图像中像素个数多的灰度值(即对画面起主要作用的灰度值)进行展宽,而对像素个数少的灰度值(即对画面不起主要作用的灰度值)进行归并,从而增大对比度,使图像清晰,达到增强的目的。举个例子,如图1所示,左图为原始图像,右图为直方图均衡化后的图像。

【图像处理算法】直方图均衡化「建议收藏」
图1 直方图均衡化前后效果对比

直方图的概念

对一幅灰度图像,其直方图反映了该图像中不同灰度级出现的统计情况。图2给出了一个直方图的示例,其中图(a)是一幅图像,其灰度直方图可表示为图(b),其中横轴表示图像的各灰度级,纵轴表示图像中各灰度级像素的个数。(需要注意,灰度直方图表示了在图像中各个单独灰度级的分布,而图像对比度则取决于相邻近像素之间灰度级的关系。)

【图像处理算法】直方图均衡化「建议收藏」
图 2 图像及其直方图

在MATLAB中可以使用函数imhist()来计算灰度图像的直方图。我们计算一下图1中左图的灰度直方图,结果如图3所示。

I = imread('pout.tif'); 
figure; 
subplot(121), imshow(I); 
subplot(122), imhist(I); 
axis([0, 256, 0, 4000]);
【图像处理算法】直方图均衡化「建议收藏」
图 3 灰度图像及其直方图

严格地说,图像的灰度直方图是一个一维的离散函数,可写成:

                                                                     h(k)=n_{k}        k = 0, 1, ..., L-1                                                               (公式1)

式中,n_{k}是图像f(x,y)中灰度级为k的像素的个数。直方图的每一列(称为bin)的高度对应n_{k}。直方图提供了原图中各种灰度值分布的情况,也可以说直方图给出了一幅图像所有灰度值的整体描述。直方图的均值和方差也是图像灰度的均值和方差。图像的视觉效果与其直方图有对应关系,或者说,直方图的形状和改变对图像有很大的影响。

在直方图的基础上,进一步定义归一化的直方图为灰度级出现的相对频率P_{r}(k)。即:

                                                                                     P_{r}(k) = n_{k} / N                                                                             (公式2)

式中,N表示图像f(x,y)的像素的总数,n_{k}是图像f(x,y)中灰度级为k的像素的个数。

我们以图1中左图为例,计算其归一化的直方图,结果如图4所示。

I = imread('pout.tif'); 
N = numel(I);  % 求图像像素的总数
Pr = imhist(I) / N; 
k = 0 : 255; 
figure; 
subplot(121), imshow(I); 
subplot(122), bar(k, Pr); 
【图像处理算法】直方图均衡化「建议收藏」
图 4 灰度图像及其归一化直方图

直方图均衡化的理论基础

为讨论方便起见,以 r 和 s 分别表示归一化了的原图像灰度和经直方图均衡化后的图像灰度(因为归一化了,所以 r 和 s 的取值在0到1之间)。当 r = s = 0时,表示黑色;当 r = s = 1时,表示白色;当 r, s ∈(0, 1)时,表示像素灰度在黑白之间变化。(所谓直方图均衡化,其实是根据直方图对像素点的灰度值进行变换,属于点操作范围。换言之,即:已知r,求其对应的s。)

在 [0,1] 区间内的任何一个 r ,经变换函数 T(r) 都可以产生一个对应的 s ,且

                                                                                      s = T(r)                                                                                     (公式3)

式中,T(r) 应当满足以下两个条件:

  1. 在 0 ≤ r ≤ 1 内,T(r) 为单调递增函数;(此条件保证了均衡化后图像的灰度级从黑到白的次序不变)
  2. 在 0 ≤ r ≤ 1 内有 0 ≤ T(r) ≤ 1。(此条件保证了均衡化后图像的像素灰度值在允许的范围内)

公式3的逆变换关系为:

                                                                                   r = T^{-1}(s)                                                                                   (公式4) 

式中,T^{-1}(s) 对 s 同样满足上述的两个条件。

由概率论可知,如果已知随机变量 r 的概率密度是 p_{r}(r),而随机变量 s 是 r 的函数,则 s 的概率密度 p_{s}(s) 可以由 p_{r}(r) 求出。假定随机变量 s 的分布函数用 F_{s}(s) 表示,根据分布函数的定义有

                                                                   F_{s}(s) = \int_{-\infty }^{s}p_{s}(s)ds = \int_{-\infty }^{r}p_{r}(r)dr                                                        (公式5)

又因为概率密度函数是分布函数的导数,因此公式5两边对 s 求导可得:

                                             p_{s}(s) = \frac{\mathrm{d} F_{s}(s)}{\mathrm{d} s} = \frac{\mathrm{d} \left [ \int_{-\infty }^{r}p_{r}(r)dr \right ]}{\mathrm{d} s} = p_{r}(r)\frac{\mathrm{d} r}{\mathrm{d} s} = p_{r}(r)\frac{dr}{d[T(r)]}                                  (公式6)

从公式6可以看出,通过变换函数 T(r) 可以控制图像灰度级的概率密度函数 p_{s}(s),从而改善图像的灰度层次,这就是直方图均衡化的理论基础。

又有:从人眼视觉特性来考虑,一幅图像的灰度直方图如果是均匀分布的,那么该图像看上去效果比较好(参考冈萨雷斯数字图像处理3.3节)。因此要做直方图均衡化,这里的 p_{s}(s) 应当是均匀分布的概率密度函数。

由概率论知识可知,对于区间 [a,b]上的均匀分布,其概率密度函数等于 \frac{1}{b-a}。 如果原图像没有进行归一化,即 r \in [0, L-1], 那么p_{s}(s) = \frac{1}{(L-1)-0} = \frac{1}{L-1},归一化之后 r \in [0, 1],所以这里的 p_{s}(s) = \frac{1}{1-0} = 1

 

由公式6可以知道 p_{s}(s)ds = p_{r}(r)dr,又因为 p_{s}(s) = 1 ,所以有 ds = p_{r}(r)dr。对这个式子两边积分得:

                                                                         s = T(r) = \int_{0}^{r}p_{r}(r)dr                                                                         (公式7)

公式7就是我们所求的变换函数 T(r)。它表明当变换函数 T(r) 是原图像直方图的累积分布概率时,能达到直方图均衡化的目的。

对于灰度级为离散的数字图像,用频率来代替概率,则变换函数 T(r_{k}) 的离散形式可以表示为:

                                                                 s_{k} = T(r_{k}) = \sum_{i=0}^{k}p_{r}(r_{i}) = \sum_{i=0}^{k}\frac{n_{i}}{N}                                                                (公式8)

式中,0 \leqslant r_{k} \leqslant 1k = 0, 1, 2, ..., L-1(注:这里的 r_{k} = \frac{k}{L-1},表示归一化后的灰度级;k表示归一化前的灰度级)。由公式8可以知道,均衡化后各像素的灰度级 s_{k} 可直接由原图像的直方图算出来。需要说明的是,这里的 s_{k} 也是归一化后的灰度级,其值在 0 到 1 之间;有时需要将其乘以L-1再取整,使其灰度级范围在 0 到 L-1之间,与原图像一致。

手工实现直方图均衡化

了解直方图均衡化的原理之后,我们以一个简单的例子来手工计算均衡化后的图像。这里我们假设存在以下这张图像(假定图像的灰度级范围是 [0, 9]):

【图像处理算法】直方图均衡化「建议收藏」
图 5 原始图像

计算过程如下:

第一步,计算原始图像的灰度直方图 n_{k}

n(0) = 3,即原始图像中灰度级为0的像素的个数是3,直接从图5中可以数出来。按这样的方式分别得出 n(1)n(2), …, n(9)。这里我们可以得到  n_{k}= [3,2,4,4,1,1,4,1,2,3]

【图像处理算法】直方图均衡化「建议收藏」
图 6 原始图像的灰度直方图

第二步,计算原始图像的像素总个数。

这里 N = 5*5 = 25

第三步,计算原始图像的灰度分布频率。

p_{r}(k) = n_{k} / N = [3/25,2/25,4/25,4/25,1/25,1/25,4/25,1/25,2/25,3/25]k = 0, 1, 2, ..., 9

第四步,计算原始图像的灰度累积分布频率。

s_{k} = \sum_{i=0}^{k}\frac{n_{i}}{N}= [3/25,5/25,9/25,13/25,14/25,15/25,19/25,20/25,22/25,25/25]k = 0, 1, 2, ..., 9

第五步,将归一化的 s_{k} 乘以 L-1再四舍五入,以使得均衡化后图像的灰度级与归一化前的原始图像一致。

s_{0} = \frac{3}{25} *(L-1) = \frac{3}{25} *9 = 1.08,四舍五入之后其值为1,也就是说原始图像中灰度级0对应均衡化后的灰度级1,即0→1。

同理,s_{1} = 1.8,四舍五入之后为2,即1→2;s_{2} = 3.24,四舍五入之后为3,即2→3;s_{3} = 4.68,四舍五入之后为5,即3→5;s_{4} = 5.04,四舍五入之后为5,即4→5;s_{5} = 5.4,四舍五入之后为5,即5→5;s_{6} = 6.84,四舍五入之后为7,即6→7;s_{7} = 7.2,四舍五入之后为7,即7→7;s_{8} = 7.92,四舍五入之后为8,即8→8;s_{9} = 9,四舍五入之后为9,即9→9。

以上的映射关系,就是变换函数 T(r) 的作用。

第六步,根据以上映射关系,参照原始图像中的像素,可以写出直方图均衡化之后的图像,如图7所示。

【图像处理算法】直方图均衡化「建议收藏」
图 7 直方图均衡化之后的图像

以上过程即为手动计算直方图均衡化。接着,我们看一下均衡化后图像的灰度直方图,如图8所示。

【图像处理算法】直方图均衡化「建议收藏」
图 8 均衡化后图像的灰度直方图

根据图6和图8,说明一下直方图均衡化是如何增强图像对比度的。在图6中,原始图像灰度值为4,5,7的像素的个数为1,因此在图8中,这三个像素值点分别归并到相邻的灰度值中。因为有三个灰度值归并,因此在均衡化处理后,出现了三个空位,由这些空位将原来相邻的灰度值展开(举个例子:5和6相邻,均衡化后,变成5和7相邻),故而展宽了对比度,但是归并也带来了某些相邻像素对比度的降低(举个例子:4和5相邻,均衡化后,变成5和5相邻)。这也说明了直方图均衡化方法对灰度分布比较集中的图像的处理效果比较明显。

MATLAB上实现直方图均衡化

在MATLAB中提供了现成的函数histeq()来实现灰度图像的直方图均衡化,如下例所示:

close all; 
clear; 
clc; 

I = imread('pout.tif');
J = histeq(I,256);
imshowpair(I,J,'montage');
【图像处理算法】直方图均衡化「建议收藏」
图 9 使用函数histeq()进行直方图均衡化

但为了演示说明算法的原理,下面将在MATLAB中自行编码实现灰度图像的直方图均衡化。通过代码来演示这个算法显然更加直观,更加易懂。

close all; 
clear; 
clc; 

% 首先读入灰度图像,并提取图像的高度和宽度
image = imread('pout.tif'); 
[height, width] = size(image); 

% 然后统计每个灰度的像素值的累计数目
NumPixel = zeros(1,256);  % 建立一个256列的行向量,以统计各灰度级的像素个数
for i = 1 : height
   for j = 1 : width
       k = image(i,j);  % k是像素点(i,j)的灰度值
       % 因为NumPixel数组的下标是从1开始的,但是图像像素的取值范围是0~255
       % 所以用NumPixel(k+1)
       NumPixel(k+1) = NumPixel(k+1) + 1;  % 对应灰度值像素点数量加1 
   end
end

% % 这里我们将数组NumPixel显示出来,以观测效果
% figure;
% subplot(121), imshow(image);
% subplot(122), bar(NumPixel);  % 灰度图像的直方图可以正确显示出来

% 接下来,将频数值算为频率
ProbPixel = zeros(1,256); % 统计各灰度级出现的频率
for i = 1 : 256
    ProbPixel(i) = NumPixel(i) / (height * width);
end

% % 这里我们将数组ProbPixel显示出来,以观测效果
% figure;
% subplot(121), imshow(image);
% subplot(122), bar(ProbPixel);  % 灰度图像的归一化直方图可以正确显示出来

% 再用函数cumsum()来计算累积分布函数(CDF),并将频率(取值范围是0~1)映射到0~255的无符号整数
CumPixel = cumsum(ProbPixel);  % 这里的数组CumPixel大小也是1×256
CumPixel = uint8((256-1) .* CumPixel + 0.5); 

% % 这里我们将数组CumPixel显示出来,以观测效果
% figure;
% subplot(121), imshow(image);
% subplot(122), bar(CumPixel);  % 数组CumPixel可以正确显示出来 

% 在下列用作直方图均衡化实现的赋值语句右端,image(i,j)被用来作为CumPixel的索引
% 例如,image(i,j)=120,则从CumPixel中取出第120个值作为image(i,j)的新像素值
outImage = uint8(zeros(height, width));  % 预分配数组
for i = 1 : height
   for j = 1 : width
      outImage(i,j) = CumPixel(image(i,j));
   end
end

% 显示直方图均衡化前后的图像,可以发现,与调用函数histeq()的效果一致
imshowpair(image, outImage, 'montage'); 

实验效果如图10所示。

【图像处理算法】直方图均衡化「建议收藏」
图 10 自行编码实现的直方图均衡化效果

上述讨论的是灰度图像的直方图均衡化。对于彩色图像而言,可以分别对R、G、B三个分量来做直方图均衡化,这也确实是一种方法。但有些时候,这样做很有可能会导致结果图像色彩失真。因此有人建议将RGB空间转换为HSV之后,对V分量进行直方图均衡化,以保证图像色彩不失真。(HSV分别指色调、饱和度、亮度)。

下面我们采用图像处理工具箱中的测试用图(图11)分别做RGB空间和HSV空间的直方图均衡化。

【图像处理算法】直方图均衡化「建议收藏」
图 11 MATLAB自带的图像

首先在RGB空间进行直方图均衡化处理。这里为了简便,直接调用MATLAB函数histeq()。

close all; 
clear; 
clc; 

I = imread('baby.jpg');
% figure,imshow(I);

% 分别提取R、G、B三个分量
R = I(:, :, 1); 
G = I(:, :, 2); 
B = I(:, :, 3); 

% 分别对三个分量进行直方图均衡化
R = histeq(R, 256); 
G = histeq(G, 256); 
B = histeq(B, 256); 

J = I;
J(:, :, 1) = R; 
J(:, :, 2) = G; 
J(:, :, 3) = B; 

imshowpair(I, J, 'montage'); 

在RGB空间进行直方图均衡化的前后图像如图12所示。

【图像处理算法】直方图均衡化「建议收藏」
图 12 RGB空间直方图均衡化前后效果对比

接下来,我们在HSV空间对V分量进行直方图均衡化处理。这里的代码可以采用调用MATLAB函数histeq()的方式,但是我们使用自行编码的方式进行处理。

close all; 
clear; 
clc; 

I = imread('baby.jpg'); 

% 将RGB空间转换为HSV空间
hsvImage = rgb2hsv(I); 

% 提取V分量
v = hsvImage(:, :, 3);  % 这里的v是double类型的矩阵

% 以下代码与前面介绍基本一致,这里不再做过多注释
[height, width] = size(v); 

v = uint8(v .* 255 + 0.5); % 这里的0.5有必要加上,以免矩阵v中出现0

N = zeros(1, 256); 
for i = 1 : height
   for j = 1 : width
      k = v(i,j);
      N(k+1) = N(k+1) + 1; 
   end
end

ProbPixel = zeros(1, 256);
for i = 1 : 256
    ProbPixel(i) = N(i) / (height * width); 
end

CumPixel = cumsum(ProbPixel);
CumPixel = uint8(255 .* CumPixel + 0.5); % 四舍五入

for i = 1 : height
   for j = 1 : width
      v(i,j) = CumPixel(v(i,j));  % 这里的v(i,j)不能为0,否则数组索引出错
   end
end

v = im2double(v); 
hsvImage(:, :, 3) = v; 
outImage = hsv2rgb(hsvImage); 

imshowpair(I, outImage, 'montage');

在HSV空间进行直方图均衡化的前后图像如图13所示。

【图像处理算法】直方图均衡化「建议收藏」
图 13 HSV空间直方图均衡化前后效果对比

直方图均衡化的缺点

如果一幅图像整体偏暗或者偏亮,那么直方图均衡化的方法很适用。但直方图均衡化是一种全局处理方式,它对处理的数据不加选择,可能会增加背景干扰信息的对比度并且降低有用信号的对比度(如果图像某些区域对比度很好,而另一些区域对比度不好,那采用直方图均衡化就不一定适用)。此外,均衡化后图像的灰度级减少,某些细节将会消失;某些图像(如直方图有高峰),经过均衡化后对比度不自然的过分增强。针对直方图均衡化的缺点,已经有局部的直方图均衡化方法出现。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/145278.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • js和html全局变量,JavaScript全局变量与局部变量

    js和html全局变量,JavaScript全局变量与局部变量原文:深入理解JavaScript的变量作用域在学习JavaScript的变量作用域之前,我们应当明确几点:JavaScript的变量作用域是基于其特有的作用域链的。JavaScript没有块级作用域。函数中声明的变量在整个函数中都有定义。1、JavaScript的作用域链首先看下下面这段代码:varrain=1;functionrainman(){varman=2;function…

  • LARGE_INTEGER解析和使用

    LARGE_INTEGER解析和使用这里解释前面碰到的LARGE_INTEGER结构。与可能的误解不同,64位数据并非要在64位操作系统下才能使用。在VC中,64位数据的类型为__int64。定义写法如下:     __int64file_offset;     上面之所以定义的变量名为file_offset,是因为文件中的偏移量是一种常见的要使用64位数据的情况。同时,文件的大小也是如此(回忆上一

  • SQL中EXISTS的用法

    SQL中EXISTS的用法比如在Northwind数据库中有一个查询为SELECTc.CustomerId,CompanyNameFROMCustomerscWHEREEXISTS(SELECTOrderIDFR

  • MySQL下载与安装教程(超详细)

    MySQL下载与安装教程(超详细)一、MySQL下载下载地址:https://dev.mysql.com/downloads/mysql/根据自己需要下载对应的版本,我下载的是mysql-5.7.31二、MySQL安装教程1.解压安装包下载后得到.zip安装包,解压到自己想要安装到的文件目录下(最好建一个专门存放环境的文件夹),我解压到的是D:\environment\mysql-5.7.312.添加环境变量我的电脑->右键->属性->高级系统设置->环境变量选择Path->编辑-&g

  • HTML在线转换JS「建议收藏」

    HTML在线转换JS「建议收藏」HTML在线转换JS工具,它可以在线将html代码转换成js代码,您只需要将需要转换的代码放置于代码框内,然后点击对应的转换按钮。简单、实用、方便、快捷、无干扰。

  • GridView删除事件

    GridView删除事件首先:转摘一段GridView删除的文章RowDeleting和RowDeleted事件RowDeleting发生在删除数据之前,RowDeleted发生在删除数据之后。使用RowDeletin

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号