首先我们要了解直方图均衡化的作用和优势,以下介绍来自 喂鸡百科:
这种方法通常用来增加许多图像的全局对比度,尤其是当图像的有用数据的对比度相当接近的时候。通过这种方法,亮度可以更好地在直方图上分布。这样就可以用于增强局部的对比度而不影响整体的对比度,直方图均衡化通过有效地扩展常用的亮度来实现这种功能。
这种方法对于背景和前景都太亮或者太暗的图像非常有用,这种方法尤其是可以带来X光图像中更好的骨骼结构显示以及曝光过度或者曝光不足照片中更好的细节。这种方法的一个主要优势是它是一个相当直观的技术并且是可逆操作,如果已知均衡化函数,那么就可以恢复原始的直方图,并且计算量也不大。这种方法的一个缺点是它对处理的数据不加选择,它可能会增加背景噪声的对比度并且降低有用信号的对比度。
从介绍中我们可以看出,这种方法适用于过暗和过亮的图像,能够得到更好的图像细节,扩大图像的动态范围。
具体的原理性在此不作赘述,下面举例:
对下面的灰度图像进行直方图均衡化处理
该灰度图像的灰度值出现次数如下表所示,为了简化表格,出现次数为0的值已经被省略
累积分布函数(cdf)如下所示,与上一表格类似,为了简化,累积分布函数值为0的灰度值已经被省略
累积分布函数为:
如表格所示,灰度值最小值为52,最大值为154. 通常,直方图均衡化算式如下:
累积分布函数最小值cdfmin在本例中为1, M和N分别代表了图像的长宽像素个数(本例中为8×8=64),而L则是灰度级数(如本例中,图像为8位深度,则灰度级数共有2^8=256级数,这也是最常见的灰度级数).则对于本例的直方图均衡化算式为:
例如,灰度为78的像素的累积分布函数为46,均衡化后,灰度值变化为:
直方图均衡化后,图像的灰度值变化如下表所示:
注意:原最小灰度值52变为了0,而最大灰度值154变为了255
原始的图像如下所示:
变化后的图像如下所示:
所以程序的流程就是:
1.统计每个灰度值的个数
2.找出累积分布函数
3.得到累积分布函数最小值cdfmin
4.根据直方图均衡化算式计算均衡化的灰度值
5.得到均衡化后的图像
下面给出代码:
clc
clear all;
picture=imread('路径'); %读取图像
figure
imshow(picture)
title('原来的图象'); %显示原始图象
after = hist_1(picture);
figure
imshow(after)
title('变化后图象'); %显示原始图象
%%
%函数部分
function hist_img = hist_1(I)
[M, N] = size(I);
size_img = M*N;
c = zeros(1,256);%统计每个每个像素值的个数
b= c;%转化前后的对照表
temp = I(:);
temp = sort(temp);
for i = 1:size_img
c(temp(i)+1) = c(temp(i)+1)+1;
end
a = c;%求和
for i = 2:256
a(i) = c(i) + a(i-1);
end
min_cdf = 10000;
for i = 1:256
if a(i)>0
if a(i) < min_cdf
min_cdf = a(i);
end
end
end
for j = 1:256
if a(j) > 0
b(j) = round(255*(a(j)-min_cdf)/(size_img-min_cdf));
end
end
for i = 1:M
for j = 1:N
I(i,j) = b(I(i,j)+1);
end
end
hist_img = I;
% figure;
% plot(b)
% title('变化前后映射')
end
代码核心是函数。函数的编写规则及流程也就是上面所说的,如果有不明白的,可以在评论里留言,如果程序有什么需要改进的地方,也可以指出,共同进步。
测试图片:
可以看到前后的差距还是很大的
前后的直方图对比:
变化前很集中,变化后很分散,但是也导致了一定程度的失真,图像的灰度值不连续,有利有弊。
代码核心是函数。函数的编写规则及流程也就是上面所说的,如果有不明白的,可以在评论里留言,如果程序有什么需要改进的地方,也可以指出,共同进步。
希望大家能够有所收获!