直方图均衡就是将原始图像的灰度直方图从比较集中的某个灰度区间变成在全部灰度范围内的均匀分布。直方图均衡使用累计分布函数的方法。
对于输入图像的每一个值为r的像素,其输出为 s = T(r),0 ≤ r ≤ L - 1,其中,L为图像的灰度级别,T(r)为单调递增函数。
课本里面T(r)的定义如下:
该公式的右边是r的累计分布函数(CDF)。p(r)为随机变量r的概率密度函数(pdf)。由该式子可以进行直方图的均衡化,证明略。
matlab代码如下:
1. 均衡函数代码如下:
将直方图均衡化作为一个函数,输入为需要均衡化的灰度图像,灰度级别为256(若为彩色图像,需要分别对每个通道进行计算,此函数仅处理灰度图像),输出为均衡后的图像,以及用到的变换向量。注意要讲该函数作为一个单独的.m的文件,文件名与函数名相同,即 equilibrium.m。调用时直接通过[image_out, tran] = equilibrium(image_int);即可,若不想要知道变换矩阵,可以直接通过image_out = equilibrium(image_int);调用(因为图像在第一个返回值)。
function [image_out, trans] = equilibrium(image_in)
% 直方图均衡函数
% 输入为 要均衡的灰度图,灰度级别为256
% 输出为均衡后的灰度图
% 灰度级
Level = 256;
image_hist= imhist(image_in); %输入图像的直方图,求pdf
[m, n] = size(image_in);
image_temp = image_in;
% 公式 s = T(r) = (L - 1) * cdf
% 在计算的时候,(L - 1)* 每一个灰度级别的累计 / (m * n)
% trans 为变换函数,即T(r)
accumulate = zeros(Level, 1);
trans = zeros(Level, 1, 'uint8');
accumulate(1) = image_hist(1);
for i = 2 : Level
accumulate(i) = accumulate(i - 1) + image_hist(i);
end
accumulate = accumulate * (Level - 1);
for i = 1 : 256
trans(i) = uint8(round((accumulate(i)) / (m * n)));
end
% 根据trans转化
for x = 1 : m
for y = 1 : n
% 注意trans的下标,应该将image(x,y)转为int型,否则当其为255时,后面的加1可能有问题。
image_temp(x, y) = trans(uint32(image_in(x, y)) + 1);
end
end
image_out = image_temp;
end
2. 测试代码如下:
close all;
clear all;
clc;
image = imread('a.tif');
image2 = imread('b.tif');
image_eq1 = equilibrium(image);
image_eq2 = equilibrium(image2);
subplot(2, 3, 1), imshow(image), title('原图像1');
subplot(2, 3, 2), imshow(image_eq1), title('图像1均衡后');
subplot(2, 3, 3), imshow(histeq(image, 256)), title('图像1调用histeq的结果');
subplot(2, 3, 4), imshow(image2), title('原图像2');
subplot(2, 3, 5), imshow(image_eq2), title('图像2均衡后');
subplot(2, 3, 6), imshow(histeq(image, 256)), title('图像1调用histeq的结果');
其中,histeq为matlab自带的均衡化图像,J = histeq(I, n); n为均衡后的灰度级别,默认为64。
代码的运行结果如下,可以看到,均衡后的图像,在各个灰度上显得更加的均匀,我们的结果与histeq的结果相差无几。