Normalisation locale dans OpenCV

J’essaie d’implémenter dans OpenCV un algorithme de normalisation local pour réduire la différence d’éclairage dans une image. J’ai trouvé une fonction MATLAB et je l’ai implémentée dans OpenCV. Cependant, le résultat obtenu est différent de celui donné par la fonction MATLAB.

Ceci est mon code:

Mat localNorm(Mat image, float sigma1, float sigma2) { Mat floatGray, blurred1, blurred2, temp1, temp2, res; image.convertTo(floatGray, CV_32FC1); floatGray = floatGray/255.0; int blur1 = 2*ceil(-NormInv(0.05, 0, sigma1))+1; cv::GaussianBlur(floatGray, blurred1, cv::Size(blur1,blur1), sigma1); temp1 = floatGray-blurred1; cv::pow(temp1, 2.0, temp2); int blur2 = 2*ceil(-NormInv(0.05, 0, sigma2))+1; cv::GaussianBlur(temp2, blurred2, cv::Size(blur2,blur2), sigma2); cv::pow(blurred2, 0.5, temp2); floatGray = temp1/temp2; floatGray = 255.0*floatGray; floatGray.convertTo(res, CV_8UC1); return res; } 

La fonction NormInv est l’implémentation C ++ donnée par Euan Dean dans cet article .

Ce qui suit montre le résultat obtenu et le résultat théorique, pour les mêmes valeurs de sigma1 et sigma2 (2.0 et 20.0, respectivement)

http://s9.postimage.org/3xfdf8f8f/Results.jpg

J’ai essayé d’utiliser différentes valeurs pour sigma1 et sigma2 , mais aucune d’entre elles ne semble fonctionner. J’ai aussi essayé de faire blur1=0 et blur2=0 dans la fonction gaussienne mais cela ne fonctionne pas non plus.

Toute aide serait appréciée. Merci d’avance.

vous devez normaliser l’image entre 0 et 255 avant de la convertir en CV_8UC1

Voici ma mise en œuvre (j’utilise sigma1=2 , sigma2=20 ):

 #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" using namespace cv; int main(int argc, char** argv) { Mat img, gray, float_gray, blur, num, den; // Load color image img = cv::imread("lena.png", 1); if( !img.data ) { return -1; } // convert to grayscale cv::cvtColor(img, gray, CV_BGR2GRAY); // convert to floating-point image gray.convertTo(float_gray, CV_32F, 1.0/255.0); // numerator = img - gauss_blur(img) cv::GaussianBlur(float_gray, blur, Size(0,0), 2, 2); num = float_gray - blur; // denominator = sqrt(gauss_blur(img^2)) cv::GaussianBlur(num.mul(num), blur, Size(0,0), 20, 20); cv::pow(blur, 0.5, den); // output = numerator / denominator gray = num / den; // normalize output into [0,1] cv::normalize(gray, gray, 0.0, 1.0, NORM_MINMAX, -1); // Display namedWindow("demo", CV_WINDOW_AUTOSIZE ); imshow("demo", gray); waitKey(0); return 0; } 

Le résultat comme prévu:

image normalisée

Notez que vous pouvez spécifier la taille du kernel sous la forme Size(0,0) . Elle sera calculée à partir des valeurs sigma.

Ceci est l’implémentation Python du même algo ci-dessus:

 import cv2 import numpy as np img = cv2.imread('/home/anmol/Downloads/lena.png') gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) float_gray = gray.astype(np.float32) / 255.0 blur = cv2.GaussianBlur(float_gray, (0, 0), sigmaX=2, sigmaY=2) num = float_gray - blur blur = cv2.GaussianBlur(num*num, (0, 0), sigmaX=20, sigmaY=20) den = cv2.pow(blur, 0.5) gray = num / den gray = cv2.normalize(gray, dst=gray, alpha=0.0, beta=1.0, norm_type=cv2.NORM_MINMAX) cv2.imwrite("./debug.png", gray * 255) 

Dehors:

entrez la description de l'image ici