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

时间:2022-11-02 21:18:58

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

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

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

What did miss?

错过了什么?

3 个解决方案

#1


62  

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 Intensity values 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. YCbCr is preferred as it is designed for digital images. 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.

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

As an example, consider the following images:

例如,请考虑以下图像:

Input Image

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

Intensity Image Equalization

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

Individual Channel Equalization

(Notice the false colors)

(注意假色)

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

Here is the OpenCV code for histogram equalization of color image using YCbCr color 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();
}

#2


6  

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) 直方图均衡不适用于彩色图像 -  OpenCV

#3


0  

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;
}

#1


62  

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 Intensity values 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. YCbCr is preferred as it is designed for digital images. 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.

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

As an example, consider the following images:

例如,请考虑以下图像:

Input Image

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

Intensity Image Equalization

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

Individual Channel Equalization

(Notice the false colors)

(注意假色)

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

Here is the OpenCV code for histogram equalization of color image using YCbCr color 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();
}

#2


6  

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) 直方图均衡不适用于彩色图像 -  OpenCV

#3


0  

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;
}