直方图均衡化

作者: 陨星落云 | 来源:发表于2019-07-24 12:24 被阅读7次

直方图均衡化

想象一下,如果一副图像中的大多是像素点的像素值都集中在一个像素值范围之内会怎样呢?例如,如果一幅图片整体很亮,那所有的像素值应该都会很高。但是一副高质量的图像的像素值分布应该很广泛。所以你应该把它的直方图做一个横向拉伸(如下图),这就是直方图均衡化要做的事情。通常情况下,这种操作会改善图像的对比度。

直方图均衡.jpg

这种方法通常用来增加许多图像的全局对比度,尤其是当图像的有用数据的对比度相当接近的时候。通过这种方法,亮度可以更好地在直方图上分布。这样就可以用于增强局部的对比度而不影响整体的对比度,直方图均衡化通过有效地扩展常用的亮度来实现这种功能。

这种方法对于背景和前景都太亮或者太暗的图像非常有用,这种方法尤其是可以带来X光图像中更好的骨骼结构显示以及曝光过度或者曝光不足照片中更好的细节。这种方法的一个主要优势是它是一个相当直观的技术并且是可逆操作,如果已知均衡化函数,那么就可以恢复原始的直方图,并且计算量也不大。这种方法的一个缺点是它对处理的数据不加选择,它可能会增加背景噪声的对比度并且降低有用信号的对比度。

我们先来看看相应的直方图和累积直方图,然后使用 OpenCV 进行直方图均衡化。

def img_show(name,image):
    """matplotlib图像显示函数
    name:字符串,图像标题
    img:numpy.ndarray,图像
    """
    if len(image.shape) == 3:
        image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
    plt.imshow(image,'gray')
    plt.xticks([])
    plt.yticks([])
    plt.xlabel(name,fontproperties='FangSong',fontsize=12)
    
if __name__=="__main__":

    img = cv2.imread("data/Unequalized.jpg",0)
    hist,bins = np.histogram(img.flatten(),256,[0,256])
    #print(hist)
    
    #查看累积直方图
    cdf = hist.cumsum()
    cdf_normalized = cdf*hist.max() / cdf.max()
    #print(cdf_normalized)
    
    #均衡化
    equ = cv2.equalizeHist(img)
    
    hist1,bins1 = np.histogram(equ.flatten(),256,[0,256])
    #print(hist)
    
    #查看均衡化后的累积直方图
    cdf1 = hist1.cumsum()
    cdf_normalized1 = cdf1*hist1.max() / cdf1.max()
    
    #显示图像结果
    plt.figure(figsize=(10,8),dpi=100)
    plt.subplot(221)
    img_show('原图',img)
    plt.subplot(222)
    img_show('均衡化后',equ)
    plt.subplot(223)
    plt.plot(cdf_normalized,color='b')
    plt.hist(img.flatten(),256,[0,256],color='r')
    plt.xlabel('相应的直方图(红)和累积直方图(蓝)',fontproperties='FangSong',fontsize=15)
    plt.xlim([0,256])
    plt.legend(('cdf','historgram'),loc = 'upper left')
    plt.subplot(224)
    plt.plot(cdf_normalized1,color='b')
    plt.hist(equ.flatten(),256,[0,256],color='r')
    plt.xlabel('均衡化相应的直方图(红)和累积直方图(蓝)',fontproperties='FangSong',fontsize=15)
    plt.xlim([0,256])
    plt.legend(('cdf','historgram'),loc = 'upper left')
    plt.show()
直方图均衡化.png

我们可以看出来直方图大部分在灰度值较高的部分,而且分布很集中。而我们希望直方图的分布比较分散,能够涵盖整个 x 轴。所以,我们就需要一个变换函数帮助我们把现在的直方图映射到一个广泛分布的直方图中,这就是直方图均衡化。

**限制对比度自适应性直方图均衡化 CLAHE **

在上边做的直方图均衡化会改变整个图像的对比度,但是在很多情况下,这样做的效果并不好。的确在进行完直方图均衡化之后,图片背景的对比度被改变了。但是你再对比一下两幅图像中雕像的面图,由于太亮我们丢失了很多信息。

直方图均衡化.png

原理:

为了解决这个问题,我们需要使用自适应的直方图均衡化CLAHE (Contrast Limited Adaptive Histogram Equalization)。这种情况下,整幅图像会被分成很多小块,这些小块被称为“tiles”(在 OpenCV 中 tileGridSize默认是 8x8),然后再对每一个小块分别进行直方图均衡化(跟前面类似)。所以在每一个的区域中,直方图会集中在某一个小的区域中(除非有噪声干扰)。如果有噪声的话,噪声会被放大。为了避免这种情况的出现,要使用对比度限制。

CLAHE中,每一个像素邻域都要进行对比度限制,从而得到对应的变换函数,被用来降低AHE中噪声的增强,这主要是通过限制AHE中的对比度增强来实现的。像素周围邻域噪声的增强主要是由变换函数的斜率造成的,由于像素邻域的噪声与邻域的CDF成正比,因此也与邻域直方图在该中心像素位置的值成正比,CLAHE之所以能够限制对比度,是因为它在计算邻域的CDF之前在指定阈值处对直方图进行了修剪,如下图所示,这一做法不仅限制了CDF的斜率,也限制了变换函数的斜率,其中对直方图进行切割所使用的阈值,被称作修剪限制度(clip limit),这个参数不仅依赖于直方图的归一化,而且依赖于像素邻域的size大小,通常设为3到4之间。

cliplimit.jpg

对于每个小块来说,如果直方图中的 bin 超过对比度的上限的话,就把其中的像素点均匀分散到其他 bins 中,然后在进行直方图均衡化。最后,为了去除每一个小块之间“人造的”(由于算法造成)边界,再使用双线性差值,与原图做图层滤色混合操作(可选)。

实现:

def img_show(name,image):
    """matplotlib图像显示函数
    name:字符串,图像标题
    img:numpy.ndarray,图像
    """
    if len(image.shape) == 3:
        image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
    plt.imshow(image,'gray')
    plt.xticks([])
    plt.yticks([])
    plt.xlabel(name,fontproperties='FangSong',fontsize=12)
    
if __name__=="__main__":
    img = cv2.imread("data/tsukuba_l.jpg",0)
    hist,bins = np.histogram(img.flatten(),256,[0,256])
    #print(hist)
    
    #查看累积直方图
    cdf = hist.cumsum()
    cdf_normalized = cdf*hist.max() / cdf.max()
    #print(cdf_normalized)
    
    #均衡化
    clahe = cv2.createCLAHE(clipLimit =2.0,tileGridSize=(8,8))
    equ = clahe.apply(img)
    
    hist1,bins1 = np.histogram(equ.flatten(),256,[0,256])
    #print(hist)
    
    #查看均衡化后的累积直方图
    cdf1 = hist1.cumsum()
    cdf_normalized1 = cdf1*hist1.max() / cdf1.max()
    
    #显示图像结果
    plt.figure(figsize=(10,8),dpi=100)
    plt.subplot(221)
    img_show('原图',img)
    plt.subplot(222)
    img_show('自适应均衡化',equ)
    plt.subplot(223)
    plt.plot(cdf_normalized,color='b')
    plt.hist(img.flatten(),256,[0,256],color='r')
    plt.xlabel('相应的直方图(红)和累积直方图(蓝)',fontproperties='FangSong',fontsize=15)
    plt.xlim([0,256])
    plt.legend(('cdf','historgram'),loc = 'upper left')
    plt.subplot(224)
    plt.plot(cdf_normalized1,color='b')
    plt.hist(equ.flatten(),256,[0,256],color='r')
    plt.xlabel('自适应均衡化直方图',fontproperties='FangSong',fontsize=15)
    plt.xlim([0,256])
    plt.legend(('cdf','historgram'),loc = 'upper left')
    plt.show()
    
自适应均衡化.png

参考文献:
网址:直方图均衡化
Adaptive_histogram_equalization
书籍:《数字图像处理》《OpenCV-Python 中文教程》

相关文章

  • 47. 直方图均衡化

    本文解释灰度直方图均衡化、彩色直方图均衡化和YUV均衡化效果 灰度直方图均衡化 效果如下: 彩色直方图均衡化 效果...

  • Metal图像处理——直方图均衡化

    Metal图像处理——直方图均衡化 Metal图像处理——直方图均衡化

  • 直方图匹配

    之前我们介绍过直方图均衡化。直方图匹配的核心思想就是在应用直方图的均衡化。 和之前直方图均衡化一样,直方图的匹配本...

  • 四、OpenCV+TensorFlow 入门人工智能图像美化处理

    彩色图片直方图 灰度直方图源码 彩色直方图源码 直方图均衡化 1.灰度 1.1灰度直方图均衡化源码 2.彩色 2....

  • OpenCV-Python学习(十一):直方图

    目录: 1.绘制直方图1)一维直方图2)2D直方图 2.直方图均衡化1)全局直方图均衡化2)CLAHE(限制对比度...

  • 直方图均衡化—理论篇

    直方图均衡化--理论篇 直方图均衡化是数字图像处理中,最基本的一种处理。直方图均衡计算简单,并且适合快速的硬件实现...

  • 低亮度图片增强方法:直方图均衡化

    直方图均衡化(HE) 直方图均衡化是最简单、最方便的低亮度图片增强的算法。 HE通过拉伸图片直方图的分布,使得图片...

  • 灰度直方图和均衡化

    目的: 得到原图的灰度直方图 使原图均衡化 得到均衡化图的灰度直方图 什么是灰度直方图: 图像中所有的像素一句像素...

  • 10、直方图应用

    直方图均衡化,实际上是调整图像的对比度,是图像增强的一种手段 (注:直方图均衡化都是基于灰度图像) 全局均衡化 局...

  • 直方图均衡化

    直方图均衡化的介绍 直方图均衡化是一种简单有效的图像增强技术,通过改变图像的直方图来改变图像中各像素的灰度,主要用...

网友评论

    本文标题:直方图均衡化

    本文链接:https://www.haomeiwen.com/subject/kmfxrctx.html