web-dev-qa-db-fra.com

L'égalisation d'histogramme ne fonctionne pas sur l'image couleur - OpenCV

J'essaie d'effectuer une égalisation d'histogramme à l'aide d'OpenCV à l'aide de la fonction suivante

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

Mais quand j'obtiens le résultat, il ne semble pas y avoir de différence entre les images d'entrée et de sortie, que fais-je de travers?

Désolé pour la mauvaise qualité d'image, "Prétraité" (à gauche) correspond à l'histogramme égalisé. Vous pouvez voir la même chose que l'entrée (à droite).

enter image description here

Qu'est-ce qui a manqué?

18
user349026

L’égalisation des histogrammes est un processus non linéaire. La division et l’équilibrage des canaux séparément ne sont pas le moyen approprié d’égaliser le contraste. L'égalisation implique les valeurs Intensité de l'image et non les composantes de couleur. Donc, pour une image couleur RVB simple, HE ne doit pas être appliqué individuellement sur chaque canal. Au contraire, il devrait être appliqué de telle sorte que les valeurs d'intensité soient égalisées sans perturber l'équilibre des couleurs de l'image. La première étape consiste donc à convertir l’espace colorimétrique de l’image RVB en un des espaces colorimétriques qui sépare les valeurs d’intensité des composantes chromatiques. Certains d'entre eux sont:

Convertissez l’image RVB en l’un des espaces colorimétriques mentionnés ci-dessus. YCbCr est préférable car il est conçu pour les images numériques. Effectuez HE du plan d'intensité Y. Reconvertissez l'image en RVB.

Dans votre situation actuelle, vous n’observez aucun changement important, car il n’ya que 2 couleurs importantes dans l’image. Lorsqu'il y a beaucoup de couleurs dans l'image, la méthode de division provoque un déséquilibre des couleurs.

A titre d'exemple, considérons les images suivantes:

Image d'entrée

 Input Image

Intensité Image Egalisation

 Intensity Equalized

Egalisation individuelle des canaux

(Remarquez les fausses couleurs)

 Split Equalized

Voici le code OpenCV pour l’égalisation par histogramme d’une image couleur en utilisant l’espace colorimétrique YCbCr.

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

Et la version 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)

Cependant, cela produira du bruit dans l'image (par exemple, l'image de gauche ci-dessous)  enter image description here

7
Steven Du

J'ai mis en œuvre une égalisation d'histogramme pour l'image BGRA. Je pense que cette fonction est utile pour votre objectif (mais vous devriez ignorer le canal 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
Radioga