C++ 直方图均衡不适用于彩色图像 - OpenCV

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15007304/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 18:53:19  来源:igfitidea点击:

Histogram equalization not working on color image - OpenCV

c++opencvimage-processinghistogram

提问by sgarizvi

I am trying to perform a histogram equalization using OpenCV using the following function

我正在尝试使用 OpenCV 使用以下函数执行直方图均衡化

Mat Histogram::Equalization(const Mat& inputImage)
{
    if(inputImage.channels() >= 3)
    {
        vector<Mat> channels;
        split(inputImage,channels);
        Mat B,G,R;

        equalizeHist( channels[0], B );
        equalizeHist( channels[1], G );
        equalizeHist( channels[2], R );
        vector<Mat> combined;
        combined.push_back(B);
        combined.push_back(G);
        combined.push_back(R);
        Mat result;
        merge(combined,result);
        return result;
    }
    return Mat();
}

But when I get the result, there seems to be no difference in input and output image, what am I doing wrong?

但是当我得到结果时,输入和输出图像似乎没有区别,我做错了什么?

Sorry for the bad image quality, "Preprocessed" (left) is histogram equalized, you can see its same as the input (right).

抱歉图像质量不好,“预处理”(左)是直方图均衡,您可以看到它与输入(右)相同。

enter image description here

在此处输入图片说明

What did miss?

错过了什么?

回答by sgarizvi

Histogram equalization is a non-linear process. Channel splitting and equalizing each channel separately is not the proper way for equalization of contrast. Equalization involves Intensityvalues of the image not the color components. So for a simple RGB color image, HE should not be applied individually on each channel. Rather, it should be applied such that intensity values are equalized without disturbing the color balance of the image. So, the first step is to convert the color space of the image from RGB into one of the color spaces which separate intensity values from color components. Some of these are:

直方图均衡化是一个非线性过程。通道拆分和单独均衡每个通道不是均衡对比度的正确方法。均衡涉及图像的强度值而不是颜色分量。因此,对于简单的 RGB 彩色图像,不应在每个通道上单独应用 HE。相反,它应该被应用,以便在不干扰图像色彩平衡的情况下均衡强度值。因此,第一步是将图像的颜色空间从 RGB 转换为将强度值与颜色分量分开的颜色空间之一。其中一些是:

Convert the image from RGB to one of the above mentioned color spaces. YCbCris preferred as it is designed for digitalimages. Perform HE of the intensity plane Y. Convert the image back to RGB.

将图像从 RGB 转换为上述颜色空间之一。YCbCr是首选,因为它是为数字图像设计的。执行强度平面 Y 的 HE。将图像转换回 RGB。

In your current situation, you are not observing any significant change, because there are only 2 prominent colors in the image. When there are lots of colors in the image, the splitting method will cause color imbalance.

在您当前的情况下,您没有观察到任何显着变化,因为图像中只有 2 种突出颜色。当图像中有很多颜色时,分割方法会导致颜色不平衡。

As an example, consider the following images:

例如,请考虑以下图像:

Input Image

输入图像

Input Image

输入图像

Intensity Image Equalization

强度图像均衡

Intensity Equalized

强度均衡

Individual Channel Equalization

独立通道均衡

(Notice the false colors)

(注意假色)

Split Equalized

分割均衡

Here is the OpenCV code for histogram equalization of color image using YCbCrcolor space.

这是使用YCbCr颜色空间对彩色图像进行直方图均衡的 OpenCV 代码。

Mat equalizeIntensity(const Mat& inputImage)
{
    if(inputImage.channels() >= 3)
    {
        Mat ycrcb;

        cvtColor(inputImage,ycrcb,CV_BGR2YCrCb);

        vector<Mat> channels;
        split(ycrcb,channels);

        equalizeHist(channels[0], channels[0]);

        Mat result;
        merge(channels,ycrcb);

        cvtColor(ycrcb,result,CV_YCrCb2BGR);

        return result;
    }
    return Mat();
}

回答by Steven Du

And the python version, @sga:

还有 python 版本,@sga:

import cv2
import os

def hisEqulColor(img):
    ycrcb=cv2.cvtColor(img,cv2.COLOR_BGR2YCR_CB)
    channels=cv2.split(ycrcb)
    print len(channels)
    cv2.equalizeHist(channels[0],channels[0])
    cv2.merge(channels,ycrcb)
    cv2.cvtColor(ycrcb,cv2.COLOR_YCR_CB2BGR,img)
    return img


fname='./your.jpg'
img=cv2.imread(fname)

cv2.imshow('img', img)
img2=hisEqulColor(img)
cv2.imshow('img2',img2)

However this will produce noise in the image (Eg, the left image below) enter image description here

然而,这会在图像中产生噪音(例如,下面的左图) 在此处输入图片说明

回答by Radioga

I implemented a histogram equalization for BGRA image. I think this function is useful for your goal (but you should ignore the alpha channel).

我为 BGRA 图像实现了直方图均衡化。我认为这个函数对你的目标很有用(但你应该忽略 alpha 通道)。

Mat equalizeBGRA(const Mat& img)
{
Mat res(img.size(), img.type());
Mat imgB(img.size(), CV_8UC1);
Mat imgG(img.size(), CV_8UC1);
Mat imgR(img.size(), CV_8UC1);
Vec4b pixel;

if (img.channels() != 4)
{
    cout << "ERROR: image input is not a BGRA image!" << endl;
    return Mat();
}

for (int r = 0; r < img.rows; r++)
{
    for (int c = 0; c < img.cols; c++)
    {
        pixel = img.at<Vec4b>(r, c);
        imgB.at<uchar>(r, c) = pixel[0];
        imgG.at<uchar>(r, c) = pixel[1];
        imgR.at<uchar>(r, c) = pixel[2];
    }
}

equalizeHist(imgB, imgB);
equalizeHist(imgG, imgG);
equalizeHist(imgR, imgR);

for (int r = 0; r < img.rows; r++)
{
    for (int c = 0; c < img.cols; c++)
    {
        pixel = Vec4b(imgB.at<uchar>(r, c), imgG.at<uchar>(r, c), imgR.at<uchar>(r, c), img.at<Vec4b>(r, c)[3]);
        res.at<Vec4b>(r, c) = pixel;
    }
}

return res;
}