zoukankan      html  css  js  c++  java
  • S0.6 直方图均衡化

    S0.6 直方图均衡化


    • 直方图均衡化能提高图像的质量

    累积直方图

    这是后面均衡化所要知道的先验知识。

    如果说直方图统计的是等于像素值的数量,那么累积直方图统计的就是小于等于像素值的数量

    均衡化步骤

    我们均衡化的目标就是把灰度直方图变得平坦,那么什么是最平坦的直方图呢?当然就是下图这样:

    4X4的图像,每个像素有4个,按概率论的角度来讲,这是均匀分布。

    我们一般用和概率相关的直方图来表示,像这样:

    我们希望直方图都像均匀分布的直方图那样,可以换种思路:只要任何直方图的累积直方图像均匀分布的累积直方图那样(即阶梯型),我们同样可以使直方图均匀分布。

    假设我们有如下直方图:

    首先,我们说明灰度直方图均衡化可能会发生的事:

    1. 相邻的两个像素可能会合并为一个,其后所有的像素值向前移一格。如图:

    图1的像素值0和1由于太小而合并,小的具体判断标准是少于累积灰度直方图的(frac{k}{N}),N为原像素种类,这里为8(其实可以取更大的任何值),k为第几个柱子,这里是第1个,具体看例子。

    1. 可能会空出一个像素区域。

    当某一个像素的数量太大时,(例如图中的像素值6),它的前面往往会空出一个像素区域,以平衡该区域。(在直方图中我们假设不做分离,把像素值当做一个整体,不把同一像素值的数量分为两份,但可以合并不同像素值的数量)

    例子

    实际操作我们是看累积直方图,一个一个柱子分析并建立像素映射关系表。

    第一个柱子为像素值0,它的值为0.02,小于(frac{1}{8})=0.125,大于(frac{0}{8})=0,于是把它映射到0。(需要说明的是,本例子像素值正好是0,1,2,3……,要是像素值不是这样,读者可以想想)

    第二个柱子为像素值1,它的值为0.06,小于(frac{1}{8})=0.125,大于(frac{0}{8})=0.125,于是把它映射到0。

    第三个柱子为像素值2,它的值为0.16,小于(frac{2}{8})=0.25,大于(frac{1}{8})=0.125,于是把它映射到1。

    第四个柱子为像素值3,它的值为0.28,小于(frac{3}{8})=0.375,大于(frac{2}{8})=0.25,于是把它映射到2。

    第五个柱子为像素值4,它的值为0.42,小于(frac{4}{8})=0.5,大于(frac{3}{8})=0.375,于是把它映射到3。

    第六个柱子为像素值5,它的值为0.62,小于(frac{5}{8})=0.625,大于(frac{4}{8})=0.5,于是把它映射到4。

    第七个柱子为像素值6,它的值为0.84,小于(frac{7}{8})=0.875,大于(frac{6}{8})=0.75,于是把它映射到6。

    第八个柱子为像素值7,它的值为1,等于(frac{8}{8})=1,于是把它映射到7。

    映射表f->g如下:

    f 0 1 2 3 4 5 6 7
    g 0 0 1 2 3 4 6 7

    我们根据映射关系得到新的均衡化直方图:(横坐标变成g)

    我想你应该已经懂了-。-

    算法代码演示

    我们统计图片0-255的灰度,然后均衡化这个灰度图。

    from cv2 import *
    import numpy as np
    import matplotlib.pyplot as plt
    
    src = imread(r"images/favorite/Lena.jpg",0)
    dst = src.copy()
    hist_array = [0 for i in range(256)]
    
    for i in range(src.shape[0]):
        for j in range(src.shape[1]):
            hist_array[src[i,j]] += 1
    
    
    hist_sum_array = [hist_array[i] for i in range(256)]
    
    for i in range(1, len(hist_array)):
        hist_sum_array[i] += hist_sum_array[i-1]
    
    print(hist_array)
    # print(hist_sum_array)
    
    plt.figure()
    plt.subplot(2,2,3)
    
    width = 0.35
    index = np.arange(0, 256, 1)
    
    plt.bar(index, hist_array, width, color = "#87CEFA")
    
    plt.xlabel("f")
    plt.ylabel("c(f)")
    plt.xticks(np.arange(0, 300, 60))
    plt.yticks(np.arange(0, 1000, 100))
    
    plt.subplot(2,2,4)
    
    k = 0
    eta = 1.0
    map = [i for i in range(256)]
    
    for i in range(256):
        while hist_sum_array[i]/256 - k*eta > 0:
            k+=1
        map[i] = k
        if map[i] == 256:
            map[i] = 255
    print(map)
    
    
    for k in range(256):
        # print(dst[0])
        # print(k,"->",map[k])
        for i in range(dst.shape[0]):
            for j in range(dst.shape[1]):
                if(src[i,j] == k):
                    dst[i,j] = map[k]
    
    # for i in range(dst.shape[0]):
    #     print(dst[i])
    
    hist_array = [0 for i in range(256)]
    for i in range(dst.shape[0]):
        for j in range(dst.shape[1]):
            hist_array[dst[i,j]] += 1
    print(hist_array)
    
    plt.bar(index, hist_array, width, color="#87CEFA")
    plt.xlabel("g")
    plt.ylabel("c(g)")
    plt.xticks(np.arange(0, 300, 60))
    plt.yticks(np.arange(0, 1000, 100))
    
    plt.subplot(221), plt.imshow(src,'gray'), plt.title('Origin')
    plt.subplot(222), plt.imshow(dst,'gray'), plt.title('Equalize')
    
    plt.show()
    

    OpenCV函数实现

    参考https://blog.csdn.net/yjp19871013/article/details/78232726

    OpenCV均衡方法有两种,第一种(全局直方图均衡化)属于本文提到的方法,即使某一像素过大也不会把它减少,第二种(限制对比度的自适应直方图均衡化)方法会把过大像素减少。

    from cv2 import *
    import matplotlib.pyplot as plt
    
    src = imread(r"images/favorite/Lena.jpg",0)
    hist = calcHist([src], [0], None, [256], [0,256])
    
    
    equ_src = equalizeHist(src)
    equ_hist = calcHist([equ_src], [0], None, [256], [0,256])
    
    
    clahe = createCLAHE(clipLimit=3.0)
    clahe_src = clahe.apply(src)
    clahe_hist = calcHist(clahe_src, [0], None, [256], [0, 256])
    
    
    plt.subplot(231), plt.imshow(src,'gray'), plt.title('Origin')
    plt.subplot(232), plt.imshow(equ_src,'gray'), plt.title('Equalize')
    plt.subplot(233), plt.imshow(clahe_src,'gray'), plt.title('Clahe')
    
    plt.subplot(234)
    plt.hist(hist.flatten(), 256, [0, 256], color='b')
    plt.title('Origin Hist')
    
    plt.subplot(235)
    plt.hist(equ_hist.flatten(), 256, [0, 256], color='b')
    plt.title('Equalize Hist')
    
    plt.subplot(236)
    plt.hist(clahe_hist.flatten(), 256, [0, 256], color='b')
    plt.title('Equalize Hist')
    plt.show()
    
    
    

  • 相关阅读:
    NanoProfiler
    NanoProfiler
    Open Source Cassandra Gitbook for Developer
    Android Fragment使用(四) Toolbar使用及Fragment中的Toolbar处理
    Android Fragment使用(三) Activity, Fragment, WebView的状态保存和恢复
    Android Fragment使用(二) 嵌套Fragments (Nested Fragments) 的使用及常见错误
    Android Fragment使用(一) 基础篇 温故知新
    Set up Github Pages with Hexo, migrating from Jekyll
    EventBus源码解析 源码阅读记录
    Android M Permission 运行时权限 学习笔记
  • 原文地址:https://www.cnblogs.com/juicebox/p/9775883.html
Copyright © 2011-2022 走看看