灰度直方图描述了一幅图像的灰度级统计信息,主要应用于图像分割和图像灰度变换等处理过程中。
从数学上来说,图像直方图描述图像的各个灰度级的统计特性,它是图像灰度值的函数,统计一幅图像中各个灰度级出现的次数或概率。有一种特殊的直方图叫做归一化直方图,可以直接反映不同灰度级出现的频率。
从图形上来说,灰度直方图是一个二维图,横坐标为图像中各个像素点的灰度级别,纵坐标表示具有各个灰度级别的像素在图像中出现的次数或概率。
灰度直方图的计算是根据其统计定义进行的。图像的灰度直方图是一个离散函数,它表示图像每一灰度级与该灰度级出现的频率的对应关系。假设一幅图像的像素总数为 N,灰度级总数为 L,其中灰度级与该灰度级出现的频率为 Ng,则这幅数字图像的灰度直方图横坐标即为灰度 g(0 ≤ g ≤ L-1),纵坐标则为灰度值出现的次数 Ng。实际上,用像素总数 N 去除以各个灰度值出现的次数 Ng 即得到各个灰度级出现的频率 Pg = Ng/N = Ng /∑Ng ,从而得到归一化的灰度直方图,其纵坐标为概率 Pg 。
Matlab 中的 imhist 函数可以进行图像的灰度直方图运算,调用语法如下:
imhist(I)
imhist(I,n)
[counts,x] = imhist(...)
参数说明
返回值
若调用时不接收这个函数的返回值,则直接显示直方图;在得到这些返回数据之后,也可以使用 stem(x,counts) 来手动绘制直方图。
一般直方图
灰度直方图的生成与显示:
I = imread('pout.jpeg'); %读取图像 pout.jpeg
figure; %打开一个新窗口
imshow(I);title('Source'); %显示原图像
figure; %打开一个新窗口
imhist(I);title('Histogram'); %显示直方图
因为相近的灰度值所具有的含义往往是相似的,所以常常没有必要在每个灰度级上都进行统计。下面的命令将 0~255 总共 256 个灰度级划分为 64 个长度为 4 的灰度区间,此时纵坐标分别统计每个灰度区间中的像素在图像中出现次数。
归一化直方图
在 imhist 函数的返回值中,counts 保存了落在每个区间的像素的个数,通过计算 counts 与图像中像素点的商可以得到归一化的直方图。
绘制有 32 个灰度区间的归一化直方图程序如下:
figure;
[M,N] = size(I); %计算图像大小
[counts,x] = imhist(I,32); %计算有 32 个小区间的灰度直方图
counts = counts / M / N; %计算归一化灰度直方图各区间的值
stem(x,counts); %绘制归一化直方图
分析图像的灰度直方图往往可以得到很多有用的信息。例如:可以很直观地看出图像的亮度和对比度特性(对比度:灰度图像最大亮度与最小亮度的比值)。如果图像较亮,则直方图的峰值出现在直方图的较右部分;如果图像较暗,则直方图的峰值出现在直方图的较左部分。如果直方图只有中间一小部分非零值,则这张图片的对比度较低;反之,如果直方图的非零值分别很宽而且比较均匀,则图像的对比度较高。
将图像的像素值通过指定的线性函数进行变换,以此增强或减弱图像的灰度。
线性灰度变换函数 f(x) 是一个一维线性函数:
D B = f ( D A ) = f A D A + f B D_B=f(D_A)=f_AD_A+f_B DB=f(DA)=fADA+fB
式中:参数 fA 为线性函数的斜率;fB 为线性函数在 y 轴的截距;DA 表示输入图像的灰度;DB 表示输出图像的灰度。
% 灰度的线性变换
% 无需专门的函数
% 增加对比度、减小对比度、线性平移增加亮度和反相显示 4 种线性变换
I = imread('pout.jpeg'); % 读入原图像
I = im2double(I); % 转换数据类型为 double
[M,N] = size(I); % 计算图像面积
figure(1); % 打开新窗口
imshow(I); % 显示原图像
title('原图像');
figure(2);
[H,x] = imhist(I,64); % 计算 64 个小区间的灰度直方图
stem(x,(H/M/N),'.'); % 显示原图像的直方图
title('原图像');
% 增加对比度
Fa = 2; Fb = -55;
O = Fa .* I + Fb/255;
figure(3);
subplot(2,2,1);
imshow(O);
title('Fa = 2 Fb = -55 增加对比度');
figure(4);
subplot(2,2,1);
[H,x] = imhist(O,64);
stem(x,(H/M/N),'.');
title('Fa = 2 Fb = -55 增加对比度');
% 减少对比度
Fa = 0.5; Fb = -55;
O = Fa .* I + Fb/255;
figure(3);
subplot(2,2,2);
imshow(O);
title('Fa = 0.5 Fb = -55 减少对比度');
figure(4);
subplot(2,2,2);
[H,x] = imhist(O,64);
stem(x,(H/M/N),'.');
title('Fa = 0.5 Fb = -55 减少对比度');
% 线性增加亮度
Fa = 1; Fb = 55;
O = Fa .* I + Fb/255;
figure(3);
subplot(2,2,3);
imshow(O);
title('Fa = 1 Fb = 55 线性平移增加亮度');
figure(4);
subplot(2,2,3);
[H,x] = imhist(O,64);
stem(x,(H/M/N),'.');
title('Fa = 1 Fb = 55 线性平移增加亮度');
% 反相显示
Fa = -1; Fb = 255;
O = Fa .* I + Fb/255;
figure(3);
subplot(2,2,4);
imshow(O);
title('Fa = -1 Fb = 255 反相显示');
figure(4);
subplot(2,2,4);
[H,x] = imhist(O,64);
stem(x,(H/M/N),'.');
title('Fa = -1 Fb = 255 反相显示');
结果:
结论:改变图像的对比度是对直方图的缩放与平移,改变图像的亮度则只是平移直方图在横轴上的位置,而反相则是将直方图水平镜像。
对数变换的一般表达式如下:
t = c l o g ( 1 + s ) t=c \quad log(1+s) t=clog(1+s)
其中 c 为尺度比例常数,s 为源灰度值,t 为变换后的目标灰度值。
由对数函数曲线可知,这种变换可以增强一幅图像中较暗部分的细节,从而可用来扩展被压缩的高值图像中较暗像素,因此对数变换被广泛地应用于频谱图像的显示中。一个典型的应用是傅里叶频谱。
对数变换不需要专门的图像处理函数。下面的例子比较了对傅里叶频谱图像进行对数变换前后的效果:
% 对傅里叶频谱图像进行对数变换
I = imread('pout.jpeg');
F = fft2(im2double(I)); % 计算频谱
F = fftshift(F);
F = abs(F);
T = log(F + 1); % 对数变换
subplot(1,2,1);
imshow(F,[]);
title('未经变换的频谱');
subplot(1,2,2);
imshow(T,[]);
title('对数变换后');
结果:
经过对数灰度处理的图像,其低灰度区域对比度将会增加,暗部细节被增强。
伽玛变换的一般表达式:
y = ( x + e s p ) γ y=(x+esp)^\gamma y=(x+esp)γ
式中:x 与 y 的取值范围是 [0,1];esp 为补偿系数;γ 则为伽玛系数。
与对数变换不同,伽玛变换可以根据 γ 的不同取值选择性增强低灰度区域的对比度或是高灰度区域的对比度。
γ 是图像灰度校正中非常重要的一个参数,其取值决定了输入图像和输出图像之间的灰度映射方式,即决定了是增强灰度值(阴影区域)还是增强高灰度(高亮区域)。
在进行变换时,我们通常将 0~255 的灰度动态范围首先变换到 0~1 的动态范围,执行伽玛变换后再恢复原动态范围。
Matlab 中为我们提供了实现灰度变换的基本工具 imadjust,其调用方式如下:
J = imadjust(I,[low_in high_in],[low_out high_out],gamma);
该函数将输入图像 I 中从 low_in 至 high_in 之间的映射到输出图像 J 的 low_out 和 high_out 之间的值,其余的值将被裁掉。
参数说明:
[low_in high_in] 和 [low_out high_out]:确定源灰度范围到目标灰度范围的映射,需要按照 double 类型给定,即取值范围在 0~1 之间;
空([])相当于默认值([0 1])。若 high_out 小于 low_out,则输出图像 J 的亮度将会反转。
参数 gamma 指定了变换曲线的形状,其默认值为 1,表示线性映射。若 gamma < 1,则映射被加权至最高的输出值;若 gamma > 1,则映射被加权至最低的输出值。
% 当 gamma 分别取不同值时的伽玛变换效果
I = imread('pout.jpeg');
% Gamma 取 0.75
subplot(2,3,1);
imshow(imadjust(I,[],[],0.75));
title('Gamma 0.75');
% Gamma 取 1
subplot(2,3,2);
imshow(imadjust(I,[],[],1));
title('Gamma 1');
% Gamma 取 1.5
subplot(2,3,3);
imshow(imadjust(I,[],[],1.5));
title('Gamma 1.5');
% Gamma 取 0.75 的灰度直方图
subplot(2,3,4);
imhist(imadjust(I,[],[],0.75));
title('Gamma 0.75');
% Gamma 取 1 的灰度直方图
subplot(2,3,5);
imhist(imadjust(I,[],[],1));
title('Gamma 1');
% Gamma 取 1.5 的灰度直方图
subplot(2,3,6);
imhist(imadjust(I,[],[],1.5));
title('Gamma 1.5');
结果:
灰度阈值变换可以将一幅灰度图像转换成黑白的二值图像。
灰度阈值变换的函数表达式如下:
f ( x ) = { 0 x < T 255 x ≥ T f(x)=\begin{cases}0 & x < T \\ 255 &x ≥ T \end{cases} f(x)={ 0255x<Tx≥T
Matlab 中和阈值变换有关的函数主要有两个——im2bw 和 graythresh。
函数 im2bw 可用于实现阈值变换,调用语法如下:
BW = im2bw(I,level);
参数说明:
函数 graythresh 可以自适应地确定变换所用的 “最优” 阈值,调用方式如下:
thresh = graythresh(I)
下面的程序显示了如何利用 graythresh 函数获得的阈值和自行设定阈值进行阈值变换:
% 阈值变换
I = imread('pout.jpeg');
thresh = graythresh(I) % 自适应确定阈值
thresh =
0.4706
bw1 = im2bw(I,thresh); % 二值化
bw2 = im2bw(I,130/255); % 以 130 为阈值实现二值化,注意将此阈值转换至 [0,1] 之间
subplot(1,3,1);imshow(I);title('原图像');
subplot(1,3,2);imshow(bw1);title('自动选择阈值');
subplot(1,3,3);imshow(bw2);title('阈值 130');
利用分段线性变换函数来增强图像对比度的方法实际是增强原图各部分的反差,即增强输入图像中感兴趣的灰度区域,相对抑制那些不感兴趣的灰度区域。分段线性函数的主要优势在于它的形式可任意给出,而缺点是需要更多的用户输入。
分段线性变换的函数形式如下:
f ( x ) = { y 1 x 1 x x < x 1 y 2 − y 1 x 2 − x 1 ( x − x 1 ) + y 1 x 1 ≤ x ≤ x 2 255 − y 2 255 − x 2 ( x − x 2 ) + y 2 x > x 2 f(x)=\begin{cases} \frac{y_1}{x_1}x & x < x_1 \\ \frac{y_2 - y_1}{x_2 - x_1}(x-x_1)+y_1 & x_1 \leq x \leq x_2 \\ \frac{255-y_2}{255-x_2}(x-x_2)+y_2 & x > x_2 \end{cases} f(x)=⎩⎪⎨⎪⎧x1y1xx2−x1y2−y1(x−x1)+y1255−x2255−y2(x−x2)+y2x<x1x1≤x≤x2x>x2
直方图均衡化又称为灰度均衡化,是指通过某种灰度映射使输入图像转换为在每一灰度级上都有近似相同的像素点数的输出图像(输出的直方图是均匀的)。
灰度均衡的转换公式:
D B = f ( D A ) = D m a x ∫ 0 D A p D A ( μ ) d μ D_B=f(D_A)=D_{max}\int_{0}^{D_A}p_{D_A}(\mu)d\mu DB=f(DA)=Dmax∫0DApDA(μ)dμ
式中:DB 为转换后的灰度值;DA 为转换前的灰度值。
而对于离散灰度值,相应的转换公式为:
D B = f ( D A ) = D m a x A 0 ∑ i = 0 D A H i D_B=f(D_A)=\frac{D_{max}}{A_0}\sum_{i=0}^{D_A}H_{i} DB=f(DA)=A0Dmaxi=0∑DAHi
式中:Hi 为第 i 级灰度的像素个数;A0 为图像的面积,即像素总数。
Matlab 图像处理工具提供了用于直方图均衡化的函数 histeq,调用语法如下:
[J,T] = histeq(I)
参数说明:
图像易受光照、视角、方位、噪声等的影响。在这些因素的作用下,同一类图像的不同变形体之间的差距有时大于该类图像与另一类图像之间的差距,这就给图像识别、分类带来了困扰。图像归一化就是将图像转换成唯一的标准形式以抵抗各种变换,从而可消除同类图像不同变体之间的外观差异。
当图像归一化用于消除灰度因素(光照等)造成的图像外观变化时,称为(图像)灰度归一化。
% 读入图片,然后对其进行增加对比度、减小对比度、线性增加亮度和线性减少亮度的处理
% 接着又分别对这 4 幅图像进行了直方图均衡化处理并显示处理前后的直方图
I = imread('pout.jpeg');
I = im2double(I);
% 对于对比度较大的图像
I1 = 2 * I - 55/255;
subplot(4,4,1);
imshow(I1);
subplot(4,4,2);
imhist(I1);
subplot(4,4,3);
imshow(histeq(I1));
subplot(4,4,4);
imhist(histeq(I1));
% 对于对比度变小的图像
I2 = 0.5 * I + 55/255;
subplot(4,4,5);
imshow(I2);
subplot(4,4,6);
imhist(I2);
subplot(4,4,7);
imshow(histeq(I2));
subplot(4,4,8);
imhist(histeq(I2));
% 对于线性增加亮度的图像
I3 = I + 55/255;
subplot(4,4,9);
imshow(I3);
subplot(4,4,10);
imhist(I3);
subplot(4,4,11);
imshow(histeq(I3));
subplot(4,4,12);
imhist(histeq(I3));
% 对于线性减小亮度的图像
I4 = I + 55/255;
subplot(4,4,13);
imshow(I4);
subplot(4,4,14);
imhist(I4);
subplot(4,4,15);
imshow(histeq(I4));
subplot(4,4,16);
imhist(histeq(I4));
直方图均衡化可以自动确定灰度变换函数,从而获得具有均匀直方图的输出图像。它主要用于增强动态范围偏小的图像对比度,丰富图像的灰度级。
但是有时候希望可以对变换过程加以控制,如能够人为修正直方图的形状,或者说是获得具有指定直方图的输出图像。这样就可以有选择地增强某个范围内的对比度或使图像灰度值满足某种特定的分布。称为直方图规定化,或直方图匹配。
直方图规定化是在运用均衡化原理的基础上,通过建立原始图像和期望图像之间的关系,使原始图像的直方图匹配特定的形状,从而弥补直方图不具备交互作用的特性。
其匹配原理是先对原始的图像均衡化:
s = f ( r ) = ∫ 0 r p r ( μ ) d μ s=f(r)=\int_0^rp_r(\mu)d\mu s=f(r)=∫0rpr(μ)dμ
同时对待匹配直方图的图像进行均衡化处理:
v = g ( z ) = ∫ 0 z p z ( λ ) d λ V v=g(z)=\int_0^zp_z(\lambda)d\lambda V v=g(z)=∫0zpz(λ)dλV
由于都是均衡化,故可令 s = v,则:
v = g − 1 ( s ) = g − 1 ( f ( r ) ) v=g^{-1}(s)=g^{-1}(f(r)) v=g−1(s)=g−1(f(r))
于是,我们可以按照如下的步骤由输入图像得到一个具有规定概率密度函数(PDF)的图像:
histeq 函数不仅可以用于直方图均衡化,也可以用于直方图规定化,此时需要提供可选参数 hgram:
[J,T] = histeq(I,hgram)
下面的例子实现了从图像 I 到图像 I1 和 I2 的直方图匹配:
% 实现了从图像 I 到图像 I1 和 I2 的直方图匹配
I = imread('pout.jpeg'); % 读取原图像
I1 = imread('coins.jpg'); % 读入要匹配直方图的图像
I2 = imread('test.jpeg'); % 读入要匹配直方图的图像
% 计算直方图
[hgram1,x] = imhist(I1);
[hgram2,x] = imhist(I2);
% 执行直方图均衡化
J1 = histeq(I,hgram1);
J2 = histeq(I,hgram2);
% 绘图
subplot(2,3,1);
imshow(I);title('原图');
subplot(2,3,2);
imshow(I1);title('标准图1');
subplot(2,3,3);
imshow(I2);title('标准图2');
subplot(2,3,5);
imshow(J1);title('规划到1');
subplot(2,3,6);
imshow(J2);title('规划到2');
% 绘画直方图
figure;
subplot(2,3,1);
imhist(I); title('原图');
subplot(2,3,2);
imhist(I1); title('标准图1');
subplot(2,3,3);
imhist(I2);title('标准图2');
subplot(2,3,5);
imhist(J1);title('规划到1');
subplot(2,3,6);
imhist(J2);title('规划到2');
直方图规定化本质上一种拟合过程,因此变换得到的直方图与标准图像的直方图并不会完全一致。然而即使只是相似的拟合,仍然使规定化的图像在亮度与对比度上具有类似标准图像的特性,这正是直方图规定化的目的所在。