31

我需要对彩色图像进行直方图均衡。

首先,我将彩色图像转换为灰色并将其提供给equalizeHist函数:

image = cv2.imread("photo.jpg")
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.equalizeHist(image)
cv2.imshow("equalizeHist", image)
cv2.waitKey(0)

但在此之后,我需要将图像转换回 RGB;我怎样才能做到这一点?

4

9 回答 9

47

来源: https ://www.packtpub.com/packtlib/book/Application-Development/9781785283932/2/ch02lvl1sec26/Enhancing%20the%20contrast%20in%20an%20image

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)

〜编辑:原始链接不再可用,此处实现了类似的想法: Histogram Equalization of a Color image with OpenCV

于 2016-07-11T16:54:40.297 回答
14

输入图像与均衡图像


Python代码

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格式的彩色图像,它不是这样工作的。RGB的每个通道代表相关颜色的强度,而不是整个图像的强度/亮度。因此,在这些颜色通道上运行 HE 不是正确的方法

我们应该首先将图像的亮度与颜色分开,然后在亮度上运行 HE。现在,已经有标准化的色彩空间,分别编码亮度和颜色,如YCbCrHSV等;所以,我们可以在这里使用它们来分离然后重新合并亮度。正确的方法:

将色彩空间从RGB转换为YCbCr >> 在Y通道上运行 HE (此通道代表亮度) >> 将色彩空间转换回RGB


后记

对于HSV颜色空间,HE 应该在V通道上运行。然而,YCbCr的Y通道比HSV的V通道更能代表亮度。因此,使用YCbCr格式会为 HE 生成更正确的结果

HSV 与 YCbCr


后记 2

HE技术太幼稚,经常会产生奇特的颜色和小工件。这是因为它不关心异常值和像素的位置。因此,更常使用诸如限制对比度的自适应 HE、保持亮度的 Bi-HE 等扩展。此外,在后处理阶段执行不同的降噪功能以改善最终输出。

于 2021-03-17T15:58:06.333 回答
11

更通用的方法是将 RGB 值转换到另一个包含发光/强度值(Luv、Lab、HSV、HSL)的空间,仅在强度平面中应用 histeq 并执行逆变换。

于 2017-03-28T07:33:23.067 回答
4

您不必先将图像转换为灰度。您可以使用以下方法。上面建议的解决方案使用了 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)
于 2020-03-14T14:36:49.953 回答
2

颜色转换方法 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)

您可以从这里了解更多信息 - https://www.etutorialspoint.com/index.php/311-python-opencv-histogram-equalization

于 2021-01-07T12:59:43.060 回答
2
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)
于 2020-05-01T03:06:15.917 回答
1

这是一个将彩色图像作为输入并返回直方图均衡图像的函数。

# 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
于 2020-07-19T12:47:12.383 回答
0

如果你想对 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
于 2016-11-17T06:09:52.070 回答
0

我不确定它是否正常工作:

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))
于 2016-09-15T11:21:39.593 回答