wake-up-neo.com

Histogrammausgleich funktioniert nicht bei Farbbildern - OpenCV

Ich versuche, eine Histogrammanpassung mit OpenCV mit der folgenden Funktion durchzuführen

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

Aber wenn ich das Ergebnis bekomme, scheint es keinen Unterschied bei der Eingabe und Ausgabe zu geben. Was mache ich falsch?

Entschuldigung für die schlechte Bildqualität, "Vorverarbeitet" (links) ist histogrammartig abgeglichen, Sie können dasselbe sehen wie die Eingabe (rechts).

enter image description here

Was hat verpasst?

18
user349026

Der Histogrammausgleich ist ein nichtlinearer Prozess. Die Kanalaufteilung und -ausgleichung jedes Kanals ist nicht der richtige Weg zum Kontrastausgleich. Bei der Entzerrung werden Intensity - Werte des Bildes und nicht die Farbkomponenten verwendet. Für ein einfaches RGB-Farbbild sollte HE daher nicht für jeden Kanal einzeln angewendet werden. Sie sollte vielmehr so ​​angewendet werden, dass Intensitätswerte ausgeglichen werden, ohne dass die Farbbalance des Bildes beeinträchtigt wird. Der erste Schritt besteht darin, den Farbraum des Bildes von RGB in einen der Farbräume umzuwandeln, der Intensitätswerte von Farbkomponenten trennt. Einige davon sind:

Konvertieren Sie das Bild von RGB in einen der oben genannten Farbräume. YCbCr wird bevorzugt, da es für digitale Bilder konzipiert ist. Führen Sie HE der Intensitätsebene Y durch. Konvertieren Sie das Bild zurück in RGB.

In Ihrer derzeitigen Situation beobachten Sie keine signifikante Veränderung, da das Bild nur zwei auffällige Farben enthält. Wenn das Bild viele Farben enthält, führt die Aufteilungsmethode zu einem Farbungleichgewicht.

Betrachten Sie als Beispiel die folgenden Bilder:

Eingabebild

 Input Image

Intensitätsbildausgleich

 Intensity Equalized

Einzelkanalausgleich

(Beachten Sie die falschen Farben)

 Split Equalized

Hier ist der OpenCV-Code für die Histogrammanpassung eines Farbbildes unter Verwendung des YCbCr -Farbraums.

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

Und die Python-Version @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)

Dies führt jedoch zu Rauschen im Bild (z. B. das linke Bild unten)  enter image description here

7
Steven Du

Ich habe einen Histogrammausgleich für das BGRA-Bild implementiert. Ich denke, diese Funktion ist nützlich für Ihr Ziel (aber Sie sollten den Alphakanal ignorieren).

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