首页 > 编程笔记 > Python笔记 阅读:4

OpenCV equalizeHist()函数:直方图均衡化(附带实例)

在一线开发中,一般直接使用 equalizeHist() 函数对图像进行直方图均衡化(归一化图像亮度和增强图像对比度),其声明如下:
equalizeHist(src[, dst]) -> dst
其中,参数 src 表示输入图像,即原图像,但需要为8位单通道的图像;dst 表示输出结果,需要和原图像有一样的尺寸和类型。

直方图均衡化有 3 种,分别是灰度图像直方图、彩色图像直方图以及 YUV 直方图均衡化。

灰度图像直方图均衡化的示例如下:
import cv2
import numpy as np

img = cv2.imread("test.jpg", 1)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow("src", gray)

dst = cv2.equalizeHist(gray)
cv2.imshow("dst", dst)

cv2.waitKey(0)
将灰度图像作为参数传进 equalizeHist() 方法即可。运行工程,结果如下图所示。


下面我们使用 OpenCV 提供的均衡化函数 equalizeHist() 实现彩色图像的直方图均衡化。

彩色图像的直方图均衡化和灰度图像略有不同,需要先用 split() 方法将彩色图像的三个通道拆分,然后分别进行均衡化,最后使用 merge() 方法将均衡化后的三个通道合并。

【实例】实现彩色图像的直方图均衡化。
import cv2
import numpy as np

img = cv2.imread("test.jpg", 1)
cv2.imshow("src", img)

# 彩色图像均衡化,需要先分解通道再对每一个通道均衡化
(b, g, r) = cv2.split(img)
bH = cv2.equalizeHist(b)
gH = cv2.equalizeHist(g)
rH = cv2.equalizeHist(r)

# 合并每一个通道
result = cv2.merge((bH, gH, rH))
cv2.imshow("dst", result)
cv2.waitKey(0)
运行工程,结果如下图所示。从结果图片上可以看出,相比原图,直方图均衡化后的图片的对比度和亮度都被增强了不少。


有没有觉得结果图的色彩有点太鲜艳了?直方图均衡化通常是对单通道图像进行的,如果对多通道图像的每个通道分别进行均衡化,可能会出现一些色彩被增强得过分鲜艳的情况。因此,对于多通道彩色图像,经常先将其转换为 YUV 色彩空间,然后只对 Y 通道进行均衡化,此时的效果将更好。

YUV 是一种色彩编码模型,也叫作 YCrCb,其中“Y”表示明亮度(Luminance),“U”和“V”分别表示色度(Chrominance)和浓度(Chroma)。YUV 色彩编码模型,其设计初衷是为了解决彩色电视机与黑白电视机的兼容问题,它利用了人类眼睛的生理特性(对亮度敏感,对色度不敏感),允许降低色度的带宽,从而降低了传输带宽。

YUV 在计算机系统中的应用尤为广泛,利用 YUV 色彩编码模型可以降低图片数据的内存占用,提高数据处理效率。另外,YUV 编码模型的图像数据一般不能直接用于显示,还需要将其转换为RGB(RGBA)编码模型,才能够正常显示图像。YCrCb 色彩空间用亮度 Y,红色 Cr、蓝色 Cb 表示图像。

从 BGR 色彩空间转换为 YCrCb 色彩空间的计算公式为:
Y = 0.299R + 0.587G + 0.114B
Cr = 0.713(R - Y) + delta
Cb = 0.564(B - Y) + delta
其中,delta = 128(8位图像)、delta = 32767(16位图像)、delta = 0.5(单精度图像)。在 cv2.cvtColor 函数中使用 cv2.COLOR_BGR2YCrCb转 换码可将图像从 BGR 色彩空间转换为 YCrCb 色彩空间;使用 cv2.COLOR_YCrCb2BGR 转换码可将图像从 YCrCb 色彩空间转换为 BGR 色彩空间。

YUV 直方图均衡化的例子如下:
import cv2
import numpy as np
#OpenCV默认用BGR格式加载图像,因此需要先将其从BGR转换为YUV
img = cv2.imread("test.jpg", 1) #读取图像
#用cv2.cvtColor函数将图像色彩空间转换为YCrCb
imgYUV = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)#imgYUV存放转换后的结果图像
cv2.imshow("src", img) #显示原图像
channelsYUV = cv2.split(imgYUV) #拆分图像通道
channelsYUV=list(channelsYUV) #更改为列表类型
channelsYUV[0] = cv2.equalizeHist(channelsYUV[0]) #对Y通道进行均衡化
channels = cv2.merge(channelsYUV) #合并图像通道
#转换色彩空间为BGR,这样能够正确显示图像
result = cv2.cvtColor(channels, cv2.COLOR_YCrCb2BGR)
cv2.imshow("dst", result) #显示图像
cv2.waitKey(0)
在上述代码中,首先使用 cvtColor 函数将彩色图像转换到 YUV 颜色空间。然后,使用 cv::split() 函数分离通道,并对 Y 通道进行自适应均衡化处理。最后,使用 merge 函数合并通道,并将图像转换回 BGR 颜色空间。

要均衡 Y 通道,需先分解出通道,然后均衡化,最后合并通道。OpenCV 提供了一个 split 方法,直接传入图片就可以分离通道。

均衡化后,要将均衡化后的三个通道合并为一张彩色图片,这时需要使用 merge 方法。merge 方法将三个通道传入其中作为参数,返回的结果就是合并后的彩色图像值。

运行工程,结果如下图所示:


可以看出,均衡化后的图像的亮度和对比度增强了,但颜色没有变得特别鲜艳。因此只对 Y 通道进行均衡化,效果更好。

相关文章