【问题标题】:OpenCV Python equalizeHist colored imageOpenCV Python equalizeHist 彩色图像
【发布时间】:2015-11-07 00:33:11
【问题描述】:

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

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

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

但在此之后我需要将图像转换回 RGB;我该怎么做?

【问题讨论】:

    标签: python opencv image-processing colors histogram-equalization


    【解决方案1】:

    来源: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

    【讨论】:

    【解决方案2】:


    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 通道上运行。然而,YCbCrY通道比HSVV通道更能代表亮度。因此,使用 YCbCr 格式会为 HE 生成更正确的结果


    后记 2

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

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案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)
        

        【讨论】:

        【解决方案5】:
        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)
        

        【讨论】:

        • 如果您能解释一下您的代码以及您实际在做什么,那就太好了,我的朋友。
        • 正如@eldesgraciado 所提到的,请在您的答案中添加一些解释,Wikipedia URL 不会使其更完整。请解释您为什么包含该参考资料?您的参考与问题有何关系。谢谢!
        【解决方案6】:

        颜色转换方法 cv2.cvtColor() 用于在 RGB/BGR 和 YUV 之间转换原始图像。这里是最好的编码 sn-p -

        # 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

        【讨论】:

          【解决方案7】:

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

          # 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
          

          【讨论】:

            【解决方案8】:

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

            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))
            

            【讨论】:

            • 这是独立均衡 RGB 通道,因此会导致颜色失真。
            【解决方案9】:

            如果你想对 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
            

            【讨论】:

            • 正如另一个答案的评论中提到的,这会扭曲颜色
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-11-16
            • 1970-01-01
            • 1970-01-01
            • 2019-07-21
            • 2019-03-04
            • 2023-03-04
            相关资源
            最近更新 更多