次の関数を使用して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();
}
しかし、結果を取得したとき、入力画像と出力画像に違いがないようですが、何が問題なのですか?
画質が悪いため申し訳ありません。「前処理」(左)はヒストグラム均等化されています。入力(右)と同じように見えます。
何を逃したのですか?
ヒストグラム均等化は非線形プロセスです。チャンネルを分割して各チャンネルを個別にイコライズすることは、コントラストをイコライズするための適切な方法ではありません。等化には、色成分ではなく画像のIntensity値が含まれます。したがって、単純なRGBカラー画像の場合、HEを各チャネルに個別に適用しないでください。むしろ、画像の色バランスを乱すことなく強度値が等しくなるように適用する必要があります。したがって、最初のステップは、画像の色空間をRGBから、強度値を色成分から分離する色空間の1つに変換することです。これらのいくつかは:
画像をRGBから上記の色空間のいずれかに変換します。 YCbCrは、digital画像用に設計されているため、推奨されます。強度平面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();
}
そして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)
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;
}