我需要对一张彩色图像进行直方图均衡化。
首先将彩色图像转换为灰度图像,并将其提供给equalizeHist
函数:
image = cv2.imread("photo.jpg")
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.equalizeHist(image)
cv2.imshow("equalizeHist", image)
cv2.waitKey(0)
但是在此之后,我需要将图像转换回RGB格式,我该怎么做?
我需要对一张彩色图像进行直方图均衡化。
首先将彩色图像转换为灰度图像,并将其提供给equalizeHist
函数:
image = cv2.imread("photo.jpg")
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.equalizeHist(image)
cv2.imshow("equalizeHist", image)
cv2.waitKey(0)
但是在此之后,我需要将图像转换回RGB格式,我该怎么做?
import cv2
import numpy as np
img = cv2.imread('input.jpg')
img_yuv = cv2.cvtColor(img, cv2.COLOR_BGR2YUV)
# equalize the histogram of the Y channel
img_yuv[:,:,0] = cv2.equalizeHist(img_yuv[:,:,0])
# convert the YUV image back to RGB format
img_output = cv2.cvtColor(img_yuv, cv2.COLOR_YUV2BGR)
cv2.imshow('Color input image', img)
cv2.imshow('Histogram equalized', img_output)
cv2.waitKey(0)
使用OpenCV对彩色图像进行直方图均衡化import cv2
def run_histogram_equalization(image_path):
rgb_img = cv2.imread(image_path)
# convert from RGB color-space to YCrCb
ycrcb_img = cv2.cvtColor(rgb_img, cv2.COLOR_BGR2YCrCb)
# equalize the histogram of the Y channel
ycrcb_img[:, :, 0] = cv2.equalizeHist(ycrcb_img[:, :, 0])
# convert back to RGB color-space from YCrCb
equalized_img = cv2.cvtColor(ycrcb_img, cv2.COLOR_YCrCb2BGR)
cv2.imshow('equalized_img', equalized_img)
cv2.waitKey(0)
直方图均衡化(HE)是一种统计方法,用于在图像处理中扩展强度值。在图像处理中,HE用于改善任何图像的对比度,即使黑暗部分更暗,明亮部分更亮。
对于灰度图像,每个像素由强度值(亮度)表示;因此我们能够将像素值直接提供给HE函数。然而,对于RGB格式的彩色图像,这不是工作方式。 R、G和B的每个通道表示相关颜色的强度,而不是整个图像的强度/亮度。因此,在这些颜色通道上运行HE不是正确的方法。
我们应该首先从颜色中分离出图像的亮度,然后在亮度上运行HE。现在已经有了标准化的颜色空间,可以分别编码亮度和颜色,例如-YCbCr、HSV等;因此,在此处可以使用它们进行分离,然后重新合并亮度。正确的做法:
将颜色空间从RGB转换为YCbCr>>对Y通道运行HE (该通道表示亮度)>>将颜色空间转换回RGB
对于HSV颜色空间,应在V通道上运行HE。然而,YCbCr的Y通道比HSV的V通道更好地代表亮度。因此,使用YCbCr格式产生更正确的HE结果。
HE是一种朴素技术,往往会产生奇特的颜色和小众问题。这是因为它不关心异常值和像素的位置。因此,常用的扩展技术——对比有限自适应HE、保持亮度的双重HE等。此外,在后处理阶段执行不同的降噪函数以改进最终输出。
一种更加通用的方法是将RGB值转换为另一个包含亮度/强度值的空间(Luv、Lab、HSV、HSL),仅在强度平面上应用histeq,然后执行反向转换。
您无需先将图像转换为灰度图像,可以使用下面的方法。上面提出的建议解决方案使用了YUV颜色空间,但我会使用HSV颜色空间来进行此示例。
image = cv2.imread("photo.jpg")
# convert image from RGB to HSV
img_hsv = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)
# Histogram equalisation on the V-channel
img_hsv[:, :, 2] = cv2.equalizeHist(img_hsv[:, :, 2])
# convert image back from HSV to RGB
image = cv2.cvtColor(img_hsv, cv2.COLOR_HSV2RGB)
cv2.imshow("equalizeHist", image)
cv2.waitKey(0)
img_yuv = cv2.cvtColor(image, cv2.COLOR_BGR2YUV)
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(2,2))
img_yuv[:,:,0] = clahe.apply(img_yuv[:,:,0])
img = cv2.cvtColor(img_yuv, cv2.COLOR_YUV2BGR)
cv2.imshow("equalizeHist", img)
cv2.waitKey(0)
颜色转换方法cv2.cvtColor()用于在RGB / BGR和YUV之间转换原始图像。以下是最佳的代码片段 -
# convert it to grayscale
img_yuv = cv2.cvtColor(img,cv2.COLOR_BGR2YUV)
# apply histogram equalization
img_yuv[:,:,0] = cv2.equalizeHist(img_yuv[:,:,0])
hist_eq = cv2.cvtColor(img_yuv, cv2.COLOR_YUV2BGR)
这是一个函数,它可以接受彩色图像作为输入,并返回直方图均衡化后的图像。
# function for color image equalization
def histogram_equalization(img_in):
# segregate color streams
b, g, r = cv2.split(img_in)
h_b, bin_b = np.histogram(b.flatten(), 256, [0, 256])
h_g, bin_g = np.histogram(g.flatten(), 256, [0, 256])
h_r, bin_r = np.histogram(r.flatten(), 256, [0, 256])
# calculate cdf
cdf_b = np.cumsum(h_b)
cdf_g = np.cumsum(h_g)
cdf_r = np.cumsum(h_r)
# mask all pixels with value=0 and replace it with mean of the pixel values
cdf_m_b = np.ma.masked_equal(cdf_b, 0)
cdf_m_b = (cdf_m_b - cdf_m_b.min()) * 255 / (cdf_m_b.max() - cdf_m_b.min())
cdf_final_b = np.ma.filled(cdf_m_b, 0).astype('uint8')
cdf_m_g = np.ma.masked_equal(cdf_g, 0)
cdf_m_g = (cdf_m_g - cdf_m_g.min()) * 255 / (cdf_m_g.max() - cdf_m_g.min())
cdf_final_g = np.ma.filled(cdf_m_g, 0).astype('uint8')
cdf_m_r = np.ma.masked_equal(cdf_r, 0)
cdf_m_r = (cdf_m_r - cdf_m_r.min()) * 255 / (cdf_m_r.max() - cdf_m_r.min())
cdf_final_r = np.ma.filled(cdf_m_r, 0).astype('uint8')
# merge the images in the three channels
img_b = cdf_final_b[b]
img_g = cdf_final_g[g]
img_r = cdf_final_r[r]
img_out = cv2.merge((img_b, img_g, img_r))
# validation
equ_b = cv2.equalizeHist(b)
equ_g = cv2.equalizeHist(g)
equ_r = cv2.equalizeHist(r)
equ = cv2.merge((equ_b, equ_g, equ_r))
# print(equ)
# cv2.imwrite('output_name.png', equ)
return img_out
如果您想均衡化RGB图像,不应该将其转换为灰度图像,而是应该逐个均衡化RGB通道。
所以,我认为这可能是您想要的:
def equalize_hist(img):
for c in xrange(0, 2):
img[:,:,c] = cv2.equalizeHist(img[:,:,c])
cv2.imshow('Histogram equalized', img)
cv2.waitKey(0)
return img
xrange(3)
来迭代索引0、1和2。 - Andy我不确定它是否正常工作:
def histogram_equalize(img):
b, g, r = cv2.split(img)
red = cv2.equalizeHist(r)
green = cv2.equalizeHist(g)
blue = cv2.equalizeHist(b)
return cv2.merge((blue, green, red))
cv2.merge([cv2.equalizeHist(c) for c in cv2.split(img)])
- Andy你不应该将图像转换为灰度。你可以使用彩色图像来处理。但是,OpenCV始终以BGR颜色格式读取图像,而不是RGB格式。
import cv2
# imread needs 2 parameters. path and the flag
img = cv2.imread("photo.jpg", 1)
# convert image from BGR to HSV
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# Histogram equalisation on the V-channel
img_hsv[:, :, 2] = cv2.equalizeHist(img_hsv[:, :, 2])
# now the img_hsv has equalized
# now convert hsv image back from HSV to RGB
imgequalized = cv2.cvtColor(img_hsv, cv2.COLOR_HSV2RGB)
cv2.imshow("original img", img)
cv2.imshow("equalizeHist", imgequalized)
cv2.waitKey(0)