29

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

しかし、結果を取得すると、入力画像と出力画像に違いがないように見えますが、何が間違っているのでしょうか?

画質が悪いのは残念ですが、「Preprocessed」(左) はヒストグラムを均等化したもので、入力 (右) と同じであることがわかります。

ここに画像の説明を入力

何が逃したのですか?

4

3 に答える 3

94

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

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

現在の状況では、画像に目立つ色が 2 つしかないため、大きな変化は見られません。画像に多くの色がある場合、分割方法によって色のバランスが崩れます。

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

入力画像

入力画像

強度画像等化

強度イコライズ

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

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

スプリットイコライズ

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();
}
于 2013-02-21T18:36:52.510 に答える
1

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;
}
于 2016-07-26T09:17:01.047 に答える