直方图均衡化(histogram equalization)

一. 原理

直方图均衡化是想要将聚集在某一区间内分布的灰度值,变为均匀的在所有区间内分布。

为了达到这一目的,我们需要找出一个函数T,将r(原图像灰度)映射到s(新图像灰度)上。同时,由于不想将图像反转,我们需要保证函数单调不减(若需要逆运算,则要严格单调递增)
图像直方图均衡化算法matlab matlab直方图均衡化原理_图像直方图均衡化算法matlab

图像直方图均衡化算法matlab matlab直方图均衡化原理_直方图均衡化_02为r的概率分布函数,图像直方图均衡化算法matlab matlab直方图均衡化原理_直方图均衡化_03为s的概率分布函数,则两者关系如下
图像直方图均衡化算法matlab matlab直方图均衡化原理_直方图均衡化_04
也就是说,图像直方图均衡化算法matlab matlab直方图均衡化原理_直方图_05这个函数现在要满足条件:

  1. 单调递增
  2. 值域范围为[0,L-1]
  3. 图像直方图均衡化算法matlab matlab直方图均衡化原理_图像直方图均衡化算法matlab_06为一个常函数(表示每一个灰度值的概率都相等)

现在给出一个函数(至于为什么是这个函数,我也不知道啊,哪位看官可以帮忙推导一下QAQ):
图像直方图均衡化算法matlab matlab直方图均衡化原理_直方图_07
我们将逐步证明,以上三点成立

  1. 由于此函数为积分所得,因此函数单调递增
  2. 由于图像直方图均衡化算法matlab matlab直方图均衡化原理_直方图均衡化_08为概率密度函数,因此,积分区间为[0,1],乘以常数,区间为[0,L-1]
  3. 推导过程:
    图像直方图均衡化算法matlab matlab直方图均衡化原理_灰度_09
    图像直方图均衡化算法matlab matlab直方图均衡化原理_图像直方图均衡化算法matlab_10
    此时图像直方图均衡化算法matlab matlab直方图均衡化原理_图像直方图均衡化算法matlab_11为一个均匀密度函数,符合

对于离散值,计数每个不大于r的概率和,就是这个r对应的s
图像直方图均衡化算法matlab matlab直方图均衡化原理_灰度_12

二. 代码

img = imread("14.jpeg");
r = img(:,:,1);
g = img(:,:,2);
b = img(:,:,3);

p = stat(r);
map = cal(p);
img_equa = my_hist_equation(r,map);

% 画图
%原图
subplot(331)
imshow(r);
title('原图');
subplot(332)
imhist(r);
title('原图直方图');

%自己的直方图均衡化图
subplot(334)
imshow(img_equa);
title('my直方图均衡化图');
subplot(335)
imhist(img_equa);
title('my直方图均衡化直方图');
subplot(336)
plot((0:255)/255,map/255);
title('my函数');

%标准的直方图均衡化图
[std_img,T] = histeq(r);
subplot(337)
imshow(std_img);
title('标准直方图均衡化图');
subplot(338)
imhist(std_img);
title('标准直方图均衡化图直方图');
subplot(339)
plot((0:255)/255,T);
title('std函数');

figure
plot((0:255)/255,map/255);
figure
plot((0:255)/255,T);

%计算图像的分布
function p=stat(img)
    [r,c] = size(img);
    p = linspace(0,0,256);
    for i=1:1:r
        for j=1:1:c
            p(img(i,j)+1)= p(img(i,j)+1)+1;
        end
    end
    p = p/(r*c);
end

%计算r与s的对应关系,矩阵坐标为r,值为s(动态规划)
function s=cal(probality)
    s=probality;
    l = length(probality);
    for i=2:l
        s(i) = s(i-1)+s(i);
    end
    s = round(s*255);
end

%将图片根据映射函数,映射
function img_equa=my_hist_equation(img,map)
    [r,c] = size(img);
    img_equa = zeros(r,c);
    for i=1:r
        for j=1:c
            img_equa(i,j) = map(img(i,j)+1);
        end
    end
    img_equa = uint8(img_equa);
end

图像直方图均衡化算法matlab matlab直方图均衡化原理_直方图_13

放大我的映射函数图片为:

图像直方图均衡化算法matlab matlab直方图均衡化原理_直方图均衡化_14

matlab自建的映射函数为:

图像直方图均衡化算法matlab matlab直方图均衡化原理_图像直方图均衡化算法matlab_15

对比两个映射函数可以看出来,自己实现的为比较连续的,而matlab自建的为阶段性的。这也解释了为什么两个直方图均衡化的后的直方图图像不同。因为对于matlab自建的的函数,将多个输入值映射为同一个输出值了。