ti-enxame.com

Equalização de histograma não funciona em imagem colorida - OpenCV

Estou tentando realizar uma equalização de histograma usando o OpenCV usando a seguinte função

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

Mas quando eu obtenho o resultado, parece não haver diferença na imagem de entrada e saída, o que estou fazendo de errado?

Desculpe pela má qualidade da imagem, "Preprocessed" (à esquerda) é o histograma equalizado, você pode ver o mesmo que a entrada (à direita).

enter image description here

O que faltou?

18
user349026

A equalização do histograma é um processo não linear. A divisão de canais e a equalização de cada canal separadamente não é o caminho adequado para a equalização do contraste. A equalização envolve Intensidade valores da imagem e não os componentes da cor. Portanto, para uma imagem de cor RGB simples, o HE não deve ser aplicado individualmente em cada canal. Pelo contrário, deve ser aplicado de tal forma que os valores de intensidade sejam equalizados sem perturbar o equilíbrio de cores da imagem. Assim, o primeiro passo é converter o espaço de cores da imagem do RGB em um dos espaços de cor que separam os valores de intensidade dos componentes de cor. Alguns destes são:

Converta a imagem do RGB para um dos espaços de cor mencionados acima. YCbCr é o preferido, pois foi projetado para digital images. Execute HE do plano de intensidade Y. Converta a imagem de volta para RGB.

Na sua situação atual, você não está observando nenhuma mudança significativa, porque há apenas duas cores proeminentes na imagem. Quando há muitas cores na imagem, o método de divisão causará desequilíbrio de cores.

Como exemplo, considere as seguintes imagens:

Imagem de Entrada

Input Image

Equalização de Imagem de Intensidade

Intensity Equalized

Equalização de canal individual

(Observe as cores falsas)

Split Equalized

Aqui está o código OpenCV para a equalização do histograma da imagem colorida usando YCbCr espaço de cores.

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();
}
66
sgarizvi

E a versão em 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)

No entanto, isso produzirá ruído na imagem (por exemplo, a imagem à esquerda abaixo)  enter image description here

7
Steven Du

Eu implementei uma equalização de histograma para a imagem BGRA. Eu acho que essa função é útil para o seu objetivo (mas você deve ignorar o canal alfa).

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
Radioga