在本教程中,您将学习使用OpenCV实现直方图均衡化和自适应直方图均衡化(CLAHE)。
直方图均衡化是一种基本的图像处理技术,通过更新图像直方图的像素强度分布来调整图像的全局对比度。这样做可以使低对比度的区域在输出图像中获得更高的对比度。
本质上,直方图均衡化的工作原理是:
- 1.计算图像像素强度的直方图
- 2.均匀展开并分布最频繁的像素值(即直方图中计数最大的像素值)
- 3.给出累积分布函数(CDF)的线性趋势
应用直方图均衡化的结果是得到一幅全局对比度更高的图像。
我们可以进一步改进直方图均衡化,采用一种称为对比度有限自适应直方图均衡化(CLAHE)的算法,从而获得更高质量的输出图像。
除了摄影师使用直方图均衡化来校正曝光不足/过曝光的图像外,直方图均衡化使用最广泛的是在医疗领域。
你通常会看到直方图均衡化应用于x光扫描和CT扫描,以提高x光片的对比度。这样做可以帮助医生和放射科医生更好地解释扫描结果,做出准确的诊断。
在本教程结束时,您将能够成功地使用OpenCV将基本直方图均衡化和自适应直方图均衡化应用到图像。
1.OpenCV直方图均衡化和自适应直方图均衡化(CLAHE)在本教程的第一部分,我们将讨论什么是直方图均衡化,以及如何使用OpenCV应用直方图均衡化。
代码地址:
链接:https://pan.baidu.com/s/19V6s7Ten6K9FfBpJTbZhAQ 提取码:123a
我们将实现两个Python脚本:
- simple_equalization.py:使用OpenCV的cv2.equalizeHist()函数执行基本直方图均衡。
- adaptive_equalization.py:使用OpenCV的cv2.createCLAHE()方法执行自适应直方图均衡化。
直方图均衡化是一种基本的图像处理技术,可以提高图像的整体对比度。
应用直方图均衡化首先计算输入灰度/单通道图像中像素强度的直方图:
左
:
我
们
的
原
始
输
入
灰
度
图
像
。
右
:
计
算
灰
度
图
像
的
直
方
图
。
左:我们的原始输入灰度图像。右:计算灰度图像的直方图。
左:我们的原始输入灰度图像。右:计算灰度图像的直方图。
请注意,我们的直方图有许多峰值,这表明有很多像素被归入到这些各自的bin中。使用直方图均衡化,我们的目标是将这些像素分散到没有太多像素的bin中。
从数学上来说,这意味着我们试图将线性趋势应用到累积分布函数(CDF)中:
直
方
图
均
衡
化
目
标
使
输
出
图
像
具
有
线
性
C
D
F
直方图均衡化目标使输出图像具有线性CDF
直方图均衡化目标使输出图像具有线性CDF
左
:
应
用
直
方
图
均
衡
化
之
前
的
原
始
输
入
图
像
。
右
:
应
用
直
方
图
均
衡
化
后
的
输
出
图
像
。
左:应用直方图均衡化之前的原始输入图像。右:应用直方图均衡化后的输出图像。
左:应用直方图均衡化之前的原始输入图像。右:应用直方图均衡化后的输出图像。
注意输入图像的对比度是如何显著提高的,但代价是也提高了输入图像中的噪声的对比度。
这就提出了一个问题:是否有可能在不增加噪声的同时提高图像对比度?
答案是“是的”,你只需要应用自适应直方图均衡化。
通过自适应直方图均衡化,我们将输入图像划分为M × N网格。然后我们对网格中的每个单元进行均衡处理,从而获得更高质量的输出图像:
左
:
基
本
直
方
图
均
衡
。
右
:
自
适
应
直
方
图
均
衡
化
左:基本直方图均衡。右:自适应直方图均衡化
左:基本直方图均衡。右:自适应直方图均衡化
缺点是,自适应直方图均衡化的计算复杂度更高(但考虑到现代硬件,这两种实现仍然相当快)。
OpenCV 包括通过以下两个函数实现基本直方图均衡和自适应直方图均衡:
- cv2.equalizeHist
- cv2.createCLAHE
应用cv2.equalizeHist()函数非常简单,只需将图像转换为灰度,然后调用cv2.equalizeHist即可:
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) equalized = cv2.equalizeHist(gray)
实现自适应直方图均衡化要求:
- 1.将输入图像转换为灰度/从中提取单个通道
- 2.使用cv2.createCLAHE实例化CLAHE算法
- 3.在CLAHE对象上调用.apply()方法来应用直方图均衡化
这比听起来容易得多,只需要几行代码:
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8)) equalized = clahe.apply(gray)
注意,我们为cv2.createCLAHE提供了两个参数:
- clipLimit:这是对比度限制的阈值
- tileGridSize:将输入图像划分为M × N块,然后对每个局部块应用直方图均衡化
在我们使用OpenCV实现直方图均衡化之前,让我们先回顾一下我们的项目目录结构。
# 用法 # python simple_equalization.py --image images/moon.png # 导入必要的库 import argparse import cv2 # 构造参数解析器并解析参数 ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", type=str, required=True, help="Path to the input image") args = vars(ap.parse_args()) # 从磁盘加载输入图像并将其转换为灰度 print("[INFO] Loading input image...") image = cv2.imread(args["image"]) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 运用直方图均衡化 print("[INFO] Performing histogram equalization...") equalized = cv2.equalizeHist(gray) # 显示原始灰度图像和均衡后的图像 cv2.imshow("Input", gray) cv2.imshow("Histogram Equalization", equalized) cv2.waitKey(0)5.2代码解析
首先导入我们需要的 Python 包,解析我们的命令行参数。这里我们只需要一个参数–image,它是磁盘上输入图像的路径,我们希望在这里应用直方图均衡化。
解析完命令行参数后,我们可以继续下一步:从磁盘加载图像,将图像从RGB转换为灰度。使用cv2.equalizeHist执行基本的直方图均衡化。我们必须传入的唯一必需参数是灰度/单通道图像。
注:使用OpenCV进行直方图均衡化时,必须提供灰度/单通道图像。如果我们试图传递一个多通道图像,OpenCV将抛出一个错误。要在多通道图像上执行直方图均衡化,您需要(1)将图像分割成各自的通道,(2)均衡每个通道,(3)合并通道。
5.3 使用OpenCV实现自适应直方图均衡# 用法 # python adaptive_equalization.py --image images/boston.png # 导入必要的库 import argparse import cv2 # 构造参数解析器并解析参数 ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", type=str, required=True, help="Path to the input image") ap.add_argument("-c", "--clip", type=float, default=2.0, help="Threshold for contrast limiting") ap.add_argument("-t", "--tile", type=int, default=8, help="Tile grid size -- divides image into tile x tile cells") args = vars(ap.parse_args()) # 从磁盘加载输入图像并将其转换为灰度 print("[INFO] Loading input image...") image = cv2.imread(args["image"]) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 应用CLAHE (Contrast Limited Adaptive Histogram Equalization) print("[INFO] Applying CLAHE...") clahe = cv2.createCLAHE(clipLimit=args["clip"], tileGridSize=(args["tile"], args["tile"])) equalized = clahe.apply(gray) # 显示原始灰度图像和CLAHE输出图像 cv2.imshow("Input", gray) cv2.imshow("CLAHE", equalized) cv2.waitKey(0)
自适应直方图均衡化比简单直方图均衡化的计算代价高一些,但可以产生更好的结果。但是不要相信我的话——你应该自己看看结果。
我们有三个命令行参数,其中一个是必需的,二个是可选的(但在使用CLHE时很有用):
- --image:磁盘上输入图像的路径,我们希望在其中应用直方图均衡化。
- --clip:对比度限制的阈值。您通常希望将此值保留在 2-5 的范围内。如果您将该值设置得太大,那么实际上您所做的是最大化局部对比度,这反过来又会最大化噪声(这与您想要的相反),尽量保持该值尽可能低。
- --tile:CLAHE 的网格大小。从概念上讲,我们在这里所做的是将输入图像划分为 tile x tile 单元格,然后对每个单元格应用直方图均衡(使用 CLAHE 提供的额外功能)。
从磁盘加载输入图像并将其转换为灰度,就像我们对基本直方图均衡化所做的那样。通过cv2.createCLAHE()函数初始化CLHE对象。这里,我们提供了clipLimit和tileGridSize,它们是通过命令行参数提供的。
调用.apply()方法将自适应直方图均衡化应用于灰度图像。
6.直方图均衡化的建议在构建自己的图像处理管道并发现应该应用直方图均衡化时,我建议从使用 cv2.equalizeHist 的简单直方图均衡化开始。但是如果你发现结果很差,反而增加了输入图像的噪声,那么你应该尝试通过 cv2.createCLAHE 使用自适应直方图均衡化。
参考目录https://www.pyimagesearch.com/2021/02/01/opencv-histogram-equalization-and-adaptive-histogram-equalization-clahe/