OpenCV-Python对比度受限的自适应直方图均衡CLAHE知识介绍

一、引言

在前面的如下几篇文章中:

  1. 《数字图像处理》第三章学习总结感悟2-1:直方图均衡处理
  2. 数字图像处理:局部直方图处理(Local Histogram Processing)
  3. 数字图像处理:使用直方图统计进行图像增强
  4. OpenCV-Python图像直方图计算详解、示例及图形呈现
  5. 数字图像处理:OpenCV-Python中的直方图均衡知识介绍及函数equalizeHist详解

老猿分别介绍了数字图像直方图处理相关的原理和概念以及应用案例,并提供了全局直方图均衡处理的OpenCV-Python的实现算法以及支持函数,但老猿并没有找到局部直方图处理、使用直方图统计信息单独的OpenCV函数。与此相关的一个OpenCV概念就是CLAHE(Contrast Limited Adaptive Histogram Equalization,对比度受限的自适应直方图均衡),这个概念老猿认为涵盖了局部直方图均衡处理和基于直方图统计信息进行图像增强的部分内容,下面就来介绍与此相关的知识。

二、CLAHE概念

全局直方图均衡,考虑的是图像的整体对比度,正如局部直方图处理介绍的那样,对大多数图像来说这并不是个好主意,当图像中同时存在亮区域范围和暗区域范围灰度值变化比较大的情况时,全局直方图的效果并不好。下面的一张书房图像除了雕像外整体偏暗,经全局直方图均衡后虽然整体对比度得到了改善,但雕像由于亮度过高在均衡后却反而丢失了大多数的信息。

在这里插入图片描述
为了解决这个问题,使用了自适应直方图均衡( Adaptive Histogram Equalization)。CLAHE,对比度受限的自适应直方图均衡,英文全称Contrast Limited Adaptive Histogram Equalization。OpenCV推出CLAHE,就是在结合局部的对比度统计信息进行限定来实现局部直方图均衡。

在这种情况下,图像被分成称为“tiles”(瓷砖、地砖、小方地毯、片状材料、块状材料)的小块,在OpenCV中,tileSize默认为8x8 。然后对分开的子图像逐一进行直方图均衡。这样在这些较小的子图像区域中,直方图将限制在一个较小的区域中(除非存在噪声)。

老猿注:tiles才开始以为是分块的每块的行列像素多少,后来仔细研究算法才发现这是图像被分成了横向和纵向各多少块,如8×8就是整个图像被划分为8纵8横共64块。不过根据看到的算法而言,图像的像素的行数和列数必须能分别整除tiles的纵向和横向块数,如果不能整除的怎么处理尚未弄明白。

如果图像中有噪音,噪音将被放大(amplified)。为了避免这种情况,应用了对比度限制(contrast limiting)。如果任何直方图bin超出指定的对比度限制(在OpenCV中默认为40),则在应用直方图均衡之前,将这些像素裁剪(clipped )并均匀地分布(distributed uniformly)到其他bin。均衡后,要消除图块边界中的伪影(artifacts),则需要应用双线性插值(bilinear interpolation )。

老猿注

  1. 对比度限制这个参数是用每块子图像直方图的每个bins的像素数和整图像素按所有灰度平均数的比值来限制的;
  2. 裁剪则是将每块图像直方图中超过对比度限制bins多出的灰度像素数去除超出部分,然后将所有bins超出的像素数累加后平均分配到所有bins;
  3. 关于具体算法将在老猿近期研究清楚后的后续算法及模拟实现的博文中介绍。

三、OpenCV中的CLAHE支持

关于OpenCV中的CLAHE的支持,请参考《OpenCV-Python自适应直方图均衡类CLAHE及方法详解 》(链接:https://blog.csdn.net/LaoYuanPython/article/details/120850922)的介绍。

下面的代码片段显示了如何在OpenCV中应用CLAHE以及其效果:

import numpy as np
import cv2 as cv
img = cv.imread('tsukuba_l.png',0)
# create a CLAHE object (Arguments are optional).
clahe = cv.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
cl1 = clahe.apply(img)
cv.imwrite('clahe_2.jpg',cl1)

查看下面的结果,并将其与上面的结果进行比较,尤其是雕像区域:
在这里插入图片描述

四、CLAHE的测试

下面的代码加载两个经典直方图均衡的案例图像,使用不同的clipLimit值进行处理,看最终的处理效果。

4.1、测试源代码

from opencvPublic import preparePreviewImg,previewImgList,readImgFile
import cv2
def testLocalHistEqu():
    img1 = readImgFile(r'f:\pic\valley.png', True)
    img2 = readImgFile(r'f:\pic\火星卫星.JPG', True)
    imgEqu1G = cv2.equalizeHist(img1)
    imgEqu2G = cv2.equalizeHist(img2)


    clahe = cv2.createCLAHE(clipLimit=4, tileGridSize=(8, 8))

    imgEqu1A4 = clahe.apply(img1)
    imgEqu2A4 = clahe.apply(img2)
    clahe.setClipLimit(40)
    imgEqu1A40 = clahe.apply(img1)
    imgEqu2A40 = clahe.apply(img2)
    clahe.setClipLimit(100)
    imgEqu1A100 = clahe.apply(img1)
    imgEqu2A100 = clahe.apply(img2)

    preparePreviewImg('输入图像:山谷', img1, fontSize=38, color=(255, 0, 0))
    preparePreviewImg('全均衡效果', imgEqu1G, fontSize=38, color=(255, 0, 0))
    preparePreviewImg('自适应均衡效果:CL=4', imgEqu1A4, fontSize=38, color=(255, 0, 0))
    preparePreviewImg('自适应均衡效果:CL=40', imgEqu1A40, fontSize=38, color=(255, 0, 0))
    preparePreviewImg('自适应均衡效果:CL=100', imgEqu1A100, fontSize=38, color=(255, 0, 0))
    preparePreviewImg('https://blog.csdn.net/LaoYuanPython', None, fontSize=38, color=(255, 0, 0))
    preparePreviewImg('输入图像:火星卫星', img2, fontSize=38, color=(255, 0, 0))
    preparePreviewImg('全均衡效果', imgEqu2G, fontSize=38, color=(255, 0, 0))
    preparePreviewImg('https://blog.csdn.net/LaoYuanPython', None, fontSize=38, color=(255, 0, 0))
    preparePreviewImg('自适应均衡效果:CL=4', imgEqu2A4, fontSize=38, color=(255, 0, 0))
    preparePreviewImg('自适应均衡效果:CL=40', imgEqu2A40, fontSize=38, color=(255, 0, 0))
    preparePreviewImg('https://blog.csdn.net/LaoYuanPython', None, fontSize=38, color=(255, 0, 0))
    preparePreviewImg('自适应均衡效果:CL=100', imgEqu2A100, fontSize=38, color=(255, 0, 0))
    previewImgList()
    print('\033[31m老猿Python网址:\033[34mhttps://blog.csdn.net/LaoYuanPython\033[0m,同名微信公众号:\033[34m老猿Python')

testLocalHistEqu()

以上代码中,opencvPublic是老猿常用的图像处理自定义方法的公用模块,本文使用的自定义公用模块函数preparePreviewImg,previewImgList,readImgFile,cmpMatrix,print2DMatrix,其功能请参考《 OpenCV-Python图形图像处理:自用的一些工具函数功能及调用语法介绍》(https://blog.csdn.net/LaoYuanPython/article/details/111351901)中的介绍。

4.2、输出图像

在这里插入图片描述
从上述图像结果可以看到:
1、对比度受限的自适应直方图均衡与全局直方图相比,对于暗区域的改善效果更好;
2、clipLimit值越大,暗区域的改善效果越明显,但亮区域反而变模糊了。

五、小结

本文介绍了OpenCV-Python对比度受限的自适应直方图均衡CLAHE相关知识,可以看到CLAHE比全局直方图均衡对明暗分布不均匀的图像的改善效果更好,而进行CLAHE处理时,clipLimit值越大,对暗区域的改善效果越明显,但亮区域反而会起到反作用。

如对文章内容存在疑问,可在博客评论区留言,或关注:老猿Python 微信公号发消息咨询。

更多图像直方图处理的内容请参考《《数字图像处理》第三章学习总结感悟2:直方图处理》的介绍。

更多图像处理的内容请参考专栏《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》、《https://blog.csdn.net/laoyuanpython/category_10581071.html OpenCV-Python初学者疑难问题集》及《图像处理基础知识》的介绍。

写博不易,敬请支持:

如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!

关于老猿的付费专栏

  1. 付费专栏《https://blog.csdn.net/laoyuanpython/category_9607725.html 使用PyQt开发图形界面Python应用》专门介绍基于Python的PyQt图形界面开发基础教程,对应文章目录为《 https://blog.csdn.net/LaoYuanPython/article/details/107580932 使用PyQt开发图形界面Python应用专栏目录》;
  2. 付费专栏《https://blog.csdn.net/laoyuanpython/category_10232926.html moviepy音视频开发专栏 )详细介绍moviepy音视频剪辑合成处理的类相关方法及使用相关方法进行相关剪辑合成场景的处理,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/107574583 moviepy音视频开发专栏文章目录》;
  3. 付费专栏《https://blog.csdn.net/laoyuanpython/category_10581071.html OpenCV-Python初学者疑难问题集》为《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的伴生专栏,是笔者对OpenCV-Python图形图像处理学习中遇到的一些问题个人感悟的整合,相关资料基本上都是老猿反复研究的成果,有助于OpenCV-Python初学者比较深入地理解OpenCV,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/109713407 OpenCV-Python初学者疑难问题集专栏目录
  4. 付费专栏《https://blog.csdn.net/laoyuanpython/category_10762553.html Python爬虫入门 》站在一个互联网前端开发小白的角度介绍爬虫开发应知应会内容,包括爬虫入门的基础知识,以及爬取CSDN文章信息、博主信息、给文章点赞、评论等实战内容。

前两个专栏都适合有一定Python基础但无相关知识的小白读者学习,第三个专栏请大家结合《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的学习使用。

对于缺乏Python基础的同仁,可以通过老猿的免费专栏《https://blog.csdn.net/laoyuanpython/category_9831699.html 专栏:Python基础教程目录)从零开始学习Python。

如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。

老猿Python,跟老猿学Python!

☞ ░ 前往老猿Python博文目录 https://blog.csdn.net/LaoYuanPython

猜你喜欢

转载自blog.csdn.net/LaoYuanPython/article/details/120711421