J'essaie d'effectuer une égalisation d'histogramme à l'aide d'OpenCV à l'aide de la fonction suivante
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();
}
Mais quand j'obtiens le résultat, il ne semble pas y avoir de différence entre les images d'entrée et de sortie, que fais-je de travers?
Désolé pour la mauvaise qualité d'image, "Prétraité" (à gauche) correspond à l'histogramme égalisé. Vous pouvez voir la même chose que l'entrée (à droite).
Qu'est-ce qui a manqué?
L’égalisation des histogrammes est un processus non linéaire. La division et l’équilibrage des canaux séparément ne sont pas le moyen approprié d’égaliser le contraste. L'égalisation implique les valeurs Intensité de l'image et non les composantes de couleur. Donc, pour une image couleur RVB simple, HE ne doit pas être appliqué individuellement sur chaque canal. Au contraire, il devrait être appliqué de telle sorte que les valeurs d'intensité soient égalisées sans perturber l'équilibre des couleurs de l'image. La première étape consiste donc à convertir l’espace colorimétrique de l’image RVB en un des espaces colorimétriques qui sépare les valeurs d’intensité des composantes chromatiques. Certains d'entre eux sont:
Convertissez l’image RVB en l’un des espaces colorimétriques mentionnés ci-dessus. YCbCr est préférable car il est conçu pour les images numériques. Effectuez HE du plan d'intensité Y. Reconvertissez l'image en RVB.
Dans votre situation actuelle, vous n’observez aucun changement important, car il n’ya que 2 couleurs importantes dans l’image. Lorsqu'il y a beaucoup de couleurs dans l'image, la méthode de division provoque un déséquilibre des couleurs.
A titre d'exemple, considérons les images suivantes:
(Remarquez les fausses couleurs)
Voici le code OpenCV pour l’égalisation par histogramme d’une image couleur en utilisant l’espace colorimétrique 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();
}
Et la version 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 img
fname='./your.jpg'
img=cv2.imread(fname)
cv2.imshow('img', img)
img2=hisEqulColor(img)
cv2.imshow('img2',img2)
J'ai mis en œuvre une égalisation d'histogramme pour l'image BGRA. Je pense que cette fonction est utile pour votre objectif (mais vous devriez ignorer le canal alpha).
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;
}