简体   繁体   English

OpenCV Python equalizeHist 彩色图像

[英]OpenCV Python equalizeHist colored image

I need to do a histogram equalization for a colored image.我需要对彩色图像进行直方图均衡。

First I convert the colored image to gray and give it to the equalizeHist function:首先,我将彩色图像转换为灰色并将其提供给equalizeHist function:

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

But after this I need to convert the image back to RGB;但在此之后我需要将图像转换回 RGB; how can i do that?我怎样才能做到这一点?

Source : https://www.packtpub.com/packtlib/book/Application-Development/9781785283932/2/ch02lvl1sec26/Enhancing%20the%20contrast%20in%20an%20image来源: 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)

~edit: original link is no longer available, similar idea is implemented here: Histogram Equalization of a Color image with OpenCV ~编辑:原始链接不再可用,这里实现了类似的想法: Histogram Equalization of a Color image with OpenCV

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

输入图像与均衡图像


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

Explanation解释

Histogram Equalization (HE) is a statistical approach for spreading out intensity values.直方图均衡化 (HE) 是一种用于扩展强度值的统计方法。 In image processing, HE is used for improving the contrast of any image, that is- to make the dark portion darker and the bright portion brighter.在图像处理中,HE用于提高任何图像的对比度,即使暗部更暗,亮部更亮。

For a grey-scale image, each pixel is represented by the intensity value (brightness);对于灰度图像,每个像素由强度值(亮度)表示; that is why we can feed the pixel values directly to the HE function.这就是为什么我们可以将像素值直接提供给 HE 函数的原因。 However, that is not how it works for an RGB -formatted color image.但是,对于RGB格式的彩色图像,这不是它的工作方式。 Each channel of the R , G , and B represents the intensity of the related color, not the intensity/brightness of the image as a whole. RGB 的每个通道代表相关颜色的强度,而不是整个图像的强度/亮度。 And so, running HE on these color channels is NOT the proper way .因此,在这些颜色通道上运行 HE 不是正确的方法

We should first separate the brightness of the image from the color and then run HE on the brightness.我们应该首先将图像的亮度与颜色分开,然后对亮度运行 HE。 Now, there are already standardized colorspaces that encode brightness and color separately, like- YCbCr , HSV , etc.;现在,已经有标准化的色彩空间,分别对亮度和颜色进行编码,如YCbCrHSV等; so, we can use them here for separating and then re-merging the brightness.所以,我们可以在这里使用它们来分离然后重新合并亮度。 The proper way:正确的方法:

Convert the colorspace from RGB to YCbCr >> Run HE on the Y channel (this channel represents brightness) >> Convert back the colorspace to RGB将色彩空间从RGB转换为YCbCr >> 在Y通道上运行 HE(此通道代表亮度)>> 将色彩空间转换回RGB


Postscript后记

For HSV colorspace, HE should be run on the V channel.对于HSV色彩空间,HE 应在V通道上运行。 However, the Y channel of YCbCr is the better representer for brightness than the V channel of HSV .然而, YCbCrY通道比HSVV通道更能代表亮度。 So, using the YCbCr format produces a more correct result for HE .因此,使用YCbCr格式可为 HE 生成更正确的结果

HSV 与 YCbCr


Postscript 2后记2

HE is too a naive technique and often produces peculiar colors and small artifacts. HE技术太天真了,经常会产生奇特的颜色和小工件。 This is because it does not care about outliers and the location of a pixel.这是因为它不关心异常值和像素的位置。 So, extensions like- ‎Contrast Limited Adaptive HE, Brightness preserving Bi-HE, etc. are used more commonly.因此,更常用的是像 - Contrast Limited Adaptive HE、Brightnesskeeping Bi-HE 等扩展。 Also, different noise reduction functions are executed in the post-processing phase for improving the final output.此外,在后处理阶段执行不同的降噪功能以改善最终输出。

You do not have to first convert your image to grayscale.您不必先将图像转换为灰度。 You can use the approach below.您可以使用以下方法。 A suggested solution above used the YUV colour space but I will do this example using the HSV colour space.上面建议的解决方案使用了 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)

The color conversion method cv2.cvtColor() is used to convert the original image in between RGB/BGR and YUV.颜色转换方法 cv2.cvtColor() 用于在 RGB/BGR 和 YUV 之间转换原始图像。 Here is the best coding snippet -这是最好的编码片段 -

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

You can know more on this from here - https://www.etutorialspoint.com/index.php/311-python-opencv-histogram-equalization您可以从这里了解更多信息 - https://www.etutorialspoint.com/index.php/311-python-opencv-histogram-equalization

Here is a function which would take color image as input and will return the histogram equalize image.这是一个将彩色图像作为输入并返回直方图均衡图像的函数。

# 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

i'm not sure that it works properly :我不确定它是否正常工作:

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

If u want to equalizeHist the RGB image, u should not convert to gray instead of equalize RGB channels one by one.如果你想均衡化 RGB 图像,你不应该转换为灰色,而是一个一个均衡化 RGB 通道。

So, i think maybe here is what u want:所以,我想也许这就是你想要的:

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

you should not convert the image in to gray scale.您不应该将图像转换为灰度。 you can do it with the colored image.你可以用彩色图像来做。 but always OpenCV read the image with BGR color format.但总是 OpenCV 读取 BGR 颜色格式的图像。 not in RGB format不是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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM