Я пытаюсь выполнить выравнивание гистограммы с помощью 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();
}
Но когда я получаю результат, кажется, нет никакой разницы во входном и выходном изображении, что я делаю неправильно?
Извините за плохое качество изображения, «Предварительная обработка» (слева) выровнена по гистограмме, вы можете видеть ее так же, как и ввод (справа).
Что пропустил?
Выравнивание гистограммы является нелинейным процессом. Разделение каналов и выравнивание каждого канала в отдельности не является подходящим способом для выравнивания контраста. Выравнивание включает интенсивность Значения изображения не цветовые составляющие. Таким образом, для простого цветного изображения RGB HE не следует применять отдельно для каждого канала. Скорее, его следует применять таким образом, чтобы значения интенсивности были выровнены, не нарушая цветовой баланс изображения. Итак, первым шагом является преобразование цветового пространства изображения из RGB в одно из цветовых пространств, которое отделяет значения интенсивности от цветовых компонентов. Вот некоторые из них:
Преобразуйте изображение из RGB в одно из вышеупомянутых цветовых пространств. YCbCr является предпочтительным, так как он предназначен для цифровой изображений. Выполните HE плоскости интенсивности Y. Конвертируйте изображение обратно в RGB.
В вашей текущей ситуации вы не наблюдаете каких-либо существенных изменений, поскольку на изображении присутствуют только два заметных цвета. Если на изображении много цветов, метод разделения вызовет дисбаланс цветов.
В качестве примера рассмотрим следующие изображения:
(Обратите внимание на ложные цвета)
Вот код OpenCV для выравнивания гистограммы цветного изображения с использованием 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();
}
И версия 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 imgfname='./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;
}