直方图均衡化

变换函数

一幅给定的图像的灰度级 r 分布在 [0,1] <script id="MathJax-Element-28" type="math/tex">[0,1]</script>范围内。可以对任一个 r 值进行如下变换:

s=T(r)       r[0,1]
<script id="MathJax-Element-29" type="math/tex; mode=display">s=T(r)~~~~~~~r\in[0,1]</script>使得每个原始图像的像素灰度值 r 都对应产生一个 s 值。

变换函数 T(r) <script id="MathJax-Element-30" type="math/tex">T(r)</script>要求满足下列条件:

1. T(r) <script id="MathJax-Element-31" type="math/tex"> T(r)</script>单调递增;
2. 对于 r[0,1] <script id="MathJax-Element-32" type="math/tex">r\in[0,1]</script>,有 T(r)[0,1] <script id="MathJax-Element-33" type="math/tex">T(r)\in[0,1]</script>。

反变换函数

当 T 严格单调时,从 s 到 r 的反变换可用式下表示

r=T1(s)       s[0,1]
<script id="MathJax-Element-34" type="math/tex; mode=display">r=T^{-1}(s)~~~~~~~s\in[0,1]</script>

可得反变换函数 T1(s) <script id="MathJax-Element-35" type="math/tex">T^{-1}(s)</script>满足下列条件:

1. T1(s) <script id="MathJax-Element-36" type="math/tex">T^{-1}(s)</script>单调递增;
2. 对于 s[0,1] <script id="MathJax-Element-37" type="math/tex">s\in[0,1]</script>,有 T1(s)[0,1] <script id="MathJax-Element-38" type="math/tex">T^{-1}(s)\in[0,1]</script>。


概率密度函数

一副图像的灰度级可被视为区间 [0,1] <script id="MathJax-Element-39" type="math/tex">[0,1]</script>的随机变量
pr(r) <script id="MathJax-Element-40" type="math/tex">p_r(r)</script>和 ps(s) <script id="MathJax-Element-41" type="math/tex">p_s(s)</script>分别代表随机变量 r 和 s 的概率密度函数

已知 pr(r) <script id="MathJax-Element-42" type="math/tex">p_r(r)</script>和 s=T(r) <script id="MathJax-Element-43" type="math/tex">s=T(r)</script>,求 ps(s) <script id="MathJax-Element-44" type="math/tex">p_s(s)</script>。
即求随机变量的函数的概率密度。

在概统里面的方法一般是:
1. 分布函数法。先求分布函数再求导。
2. 特别的,当函数 T <script id="MathJax-Element-45" type="math/tex">T</script>严格单调,有结论如下:

ps(s)=pr(r)|dT1(s)ds|=pr(r)|drds|     ()
<script id="MathJax-Element-46" type="math/tex; mode=display">p_s(s)=p_r(r)|{dT^{-1}(s)\over ds}|=p_r(r)|{dr\over ds}|~~~~~(*)</script>

具体的推导过程可以去翻翻概统书。
下面提供错误的推导

pr(r)=pr(T1(s))ps(s)
<script id="MathJax-Element-47" type="math/tex; mode=display">p_r(r)=p_r(T^{-1}(s))\triangleq p_s(s)</script>即
ps()=pr(T1())
<script id="MathJax-Element-48" type="math/tex; mode=display">p_s(·)=p_r(T^{-1}(·))</script>


直方图均衡化

直方图均衡化处理是以累积分布函数变换法为基础的直方图修正法。

连续随机变量

假定变换函数为:

s=T(r)=r0pr(w) dw
<script id="MathJax-Element-49" type="math/tex; mode=display">s=T(r)=\int_0^rp_r(w)~dw</script>对 r 进行求导得:
dsdr=pr(r)
<script id="MathJax-Element-50" type="math/tex; mode=display">{ds\over dr}=p_r(r)</script>代入到 () <script id="MathJax-Element-51" type="math/tex">(*)</script>中,得到
ps(s)=1
<script id="MathJax-Element-52" type="math/tex; mode=display">p_s(s)=1</script>该结果表明在假定的变换函数的作用下,变换后的变量 s 的概率密度是 均匀分布的。

因此,用 r 的分布函数作为变换函数,可产生一幅灰度级分布具有均匀概率密度的图像。其结果扩展了像素取值的动态范围。

离散随机变量

但该结果只对于连续变量而言。在实际中灰度是呈离散形式分布的,不能保证均匀分布。

当灰度级是离散值时,可用频数近似代替概率值,即

pr(rk)=nkn       rk[0,1],k=0,1,...,L1
<script id="MathJax-Element-53" type="math/tex; mode=display">p_r(r_k)={n_k\over n}~~~~~~~r_k\in[0,1],k=0,1,...,L-1</script>变换函数为:
sk=T(rk)=j=0kpr(rj)
<script id="MathJax-Element-54" type="math/tex; mode=display">s_k=T(r_k)=\sum_{j=0}^kp_r(r_j)</script>

因为直方图是近似的概率密度函数,所以用离散灰度级作变换一般得不到完全平坦的结果。由于简并现象的存在,处理后的灰度级总是要减少的,这是像素灰度有限的必然结果。由于上述原因,数字图像的直方图均衡只是近似的。


代码实现

采用256灰阶的Lena图。

  1. 统计每个灰度的概率p
  2. 做累积分布s
  3. 将累积分布作为变换函数T
  4. 转换每个灰度值

github source code

Image HistogramEqualization(Image inImage, int width, int height) {
    Image outImage(width, height);
    int rn[256] = { 0 }, sum = width * height;
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            Pixel p = inImage.getPixel(x, y);
            rn[p.getR()]++; // 统计每个灰度的数量
        }
    }
    double p[256], s[256];
    int T[256];
    for (int i = 0; i < 256; i++)
        p[i] = 1.0 * rn[i] / sum; // 计算每个灰度的概率
    s[0] = p[0];
    for (int i = 1; i < 256; i++) {
        s[i] = p[i] + s[i - 1];  // 做累积分布
        T[i] = (int)(s[i] * 256); // 将累积分布作为变换函数T
    }
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            Pixel p = inImage.getPixel(x, y);
            const int r = T[p.getR()];  // 转换灰度值
            p.set(r, r, r);
            outImage.setPixel(x, y, p);
        }
    }
    return outImage;
}


下面是均衡化后的图像

彩图则对rgb都均衡化处理

void HE(int *rn, int sum, int *rT) {
    double rp[256], rs[256];
    for (int i = 0; i < 256; i++)
        rp[i] = 1.0 * rn[i] / sum;
    rs[0] = rp[0];
    for (int i = 1; i < 256; i++) {
        rs[i] = rp[i] + rs[i - 1];
        rT[i] = (int)(rs[i] * 256);
    }
}
Image HistogramEqualization(Image inImage, int width, int height) {
    Image outImage(width, height);
    int rn[256] = { 0 }, sum = width * height;
    int gn[256] = { 0 };
    int bn[256] = { 0 };
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            Pixel p = inImage.getPixel(x, y);
            rn[p.getR()]++;
            gn[p.getR()]++;
            bn[p.getR()]++;
        }
    }
    // 三者都均衡化处理
    int rT[256], gT[256], bT[256];
    HE(rn, sum, rT);
    HE(gn, sum, gT);
    HE(bn, sum, bT);

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            Pixel p = inImage.getPixel(x, y);
            p.set(rT[p.getR()], gT[p.getG()], bT[p.getB()]);
            outImage.setPixel(x, y, p);
        }
    }
    return outImage;
}


下图为均衡化后

并没有变好吃(¬︿̫̿¬☆)!

©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页