在前面的如下几篇文章中:
老猿分别介绍了数字图像直方图处理相关的原理和概念以及应用案例,并提供了全局直方图均衡处理的OpenCV-Python的实现算法以及支持函数,但老猿并没有找到局部直方图处理、使用直方图统计信息单独的OpenCV函数。与此相关的一个OpenCV概念就是CLAHE(Contrast Limited Adaptive Histogram Equalization,对比度受限的自适应直方图均衡),这个概念老猿认为涵盖了局部直方图均衡处理和基于直方图统计信息进行图像增强的部分内容,下面就来介绍与此相关的知识。
全局直方图均衡,考虑的是图像的整体对比度,正如局部直方图处理介绍的那样,对大多数图像来说这并不是个好主意,当图像中同时存在亮区域范围和暗区域范围灰度值变化比较大的情况时,全局直方图的效果并不好。下面的一张书房图像除了雕像外整体偏暗,经全局直方图均衡后虽然整体对比度得到了改善,但雕像由于亮度过高在均衡后却反而丢失了大多数的信息。
为了解决这个问题,使用了自适应直方图均衡( 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 )。
老猿注:
关于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)
查看下面的结果,并将其与上面的结果进行比较,尤其是雕像区域:
下面的代码加载两个经典直方图均衡的案例图像,使用不同的clipLimit值进行处理,看最终的处理效果。
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)中的介绍。
从上述图像结果可以看到:
1、对比度受限的自适应直方图均衡与全局直方图相比,对于暗区域的改善效果更好;
2、clipLimit值越大,暗区域的改善效果越明显,但亮区域反而变模糊了。
本文介绍了OpenCV-Python对比度受限的自适应直方图均衡CLAHE相关知识,可以看到CLAHE比全局直方图均衡对明暗分布不均匀的图像的改善效果更好,而进行CLAHE处理时,clipLimit值越大,对暗区域的改善效果越明显,但亮区域反而会起到反作用。
如对文章内容存在疑问,可在博客评论区留言,或关注博客左边的:老猿Python 微信公号发消息咨询。
如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!
前两个专栏都适合有一定Python基础但无相关知识的小白读者学习,第三个专栏请大家结合《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的学习使用。
对于缺乏Python基础的同仁,可以通过老猿的免费专栏《https://blog.csdn.net/laoyuanpython/category_9831699.html 专栏:Python基础教程目录)从零开始学习Python。
如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。