web-dev-qa-db-ja.com

ヒストグラムの等化がカラー画像で機能しない-OpenCV

次の関数を使用して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();
}

しかし、結果を取得したとき、入力画像と出力画像に違いがないようですが、何が問題なのですか?

画質が悪いため申し訳ありません。「前処理」(左)はヒストグラム均等化されています。入力(右)と同じように見えます。

enter image description here

何を逃したのですか?

22
user349026

ヒストグラム均等化は非線形プロセスです。チャンネルを分割して各チャンネルを個別にイコライズすることは、コントラストをイコライズするための適切な方法ではありません。等化には、色成分ではなく画像のIntensity値が含まれます。したがって、単純なRGBカラー画像の場合、HEを各チャネルに個別に適用しないでください。むしろ、画像の色バランスを乱すことなく強度値が等しくなるように適用する必要があります。したがって、最初のステップは、画像の色空間をRGBから、強度値を色成分から分離する色空間の1つに変換することです。これらのいくつかは:

画像をRGBから上記の色空間のいずれかに変換します。 YCbCrは、digital画像用に設計されているため、推奨されます。強度平面YのHEを実行します。画像をRGBに変換します。

現在の状況では、画像に目立つ色が2つしかないため、大きな変化は見られません。画像に多くの色がある場合、分割方法は色の不均衡を引き起こします。

例として、次の画像を考えてみます。

入力画像

Input Image

強度画像均等化

Intensity Equalized

個別チャネルのイコライゼーション

(偽色に注意してください)

Split Equalized

これは、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();
}
75
sgarizvi

そして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)

ただし、これにより画像にノイズが発生します(たとえば、下の左側の画像) enter image description here

10
Steven Du

BGRA画像のヒストグラム均等化を実装​​しました。この機能はあなたの目標に役立つと思います(ただし、アルファチャネルは無視してください)。

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