灰度图像的灰度级范围是0到255,如果一张图片的灰度集中在较低的灰度级范围,则图片整体会看起来偏暗,可以利用直方图均衡化进行变换。
直方图均衡化:顾名思义就是把上述原图的直方图通过某种变换,使其较为均匀的分布到0-255范围内,理解为拉开间距。
均衡化的原理是:通过计算利用灰度级的cdf(累积分布函数),将原来的灰度级映射到新的灰度级。
举个简单的例子,假设灰度范围不是0-255,而是0到9十个灰度,原图有100个像素,有10个像素的灰度是0,有20个像素的灰度是1,有30个像素的灰度是2,有40个像素的灰度是3。那么归一化的累积分布函数
那么可以计算得到映射函数
取整。下列表格按向下取整计算:
则映射完之后,原本灰度是0的像素还是0,原本灰度是3的像素变成了灰度为9。均衡化之后,原来图像的灰度是0123,映射后灰度是0259,间距就拉大了,就显得均衡了。
原灰度 0 1 2 3 4 5 6 7 8 9 像素个数 10 20 30 40 0 0 0 0 0 0 归一化CDF 0.1 0.3 0.6 1.0 1.0 1.0 1.0 1.0 1.0 1.0 映射函数 0 2 5 9 9 9 9 9 9 9
说完简单例子,看看对上面图片实际进行直方图均衡后的效果:
matlab代码:
close all;
clear all;
clc;
img = imread('1.jpg'); %读取图片
img = rgb2gray(img); %转为灰度图
figure
imshow(img);title('原图');
hist_img = hist(img);
figure
imshow(hist_img);title('变化后图象'); %显示原始图象
function hist_img = hist(img)
[counts, ~] = imhist(img); %获取原图直方图
figure
bar(counts);
title('原图直方图');
xlabel('灰度值');
ylabel('Frequency');
cdf = cumsum(counts)/numel(img); %累积分布函数,长度为256的数组
map = uint8(255 * cdf); % 映射函数,长度是256的数组,范围是0-255(灰度范围)
% 应用映射函数,对原始图像进行直方图均衡化
hist_img = map(img + 1); % 灰度级是0-255,数组map索引是1-256,所以+1。映射过程:例如原本灰度级是100的,则映射到map的第101个值
[counts_after, ~] = imhist(hist_img); %获取原图直方图
figure
bar(counts_after);
title('直方图均衡化后 直方图');
xlabel('灰度值');
ylabel('Frequency');
end