2013-02-14 25 views
5

Sto cercando di implementare in OpenCV un algoritmo di normalizzazione locale per ridurre la differenza di illuminazione in un'immagine. Ho trovato uno MATLAB function e l'ho implementato in OpenCV. Tuttavia, il risultato che ottengo è diverso da quello fornito dalla funzione MATLAB.Normalizzazione locale in OpenCV

Questo è il mio codice:

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 funzione NormInv è l'implementazione C++ data dal Euan Dean in this post.

Il seguente mostra il risultato che sto ottenendo e il risultato teorico, per gli stessi valori di sigma1 e sigma2 (2,0 e 20,0, rispettivamente)

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

Ho provato con valori diversi per sigma1 e sigma2, ma nessuno di loro sembra funzionare. Ho anche provato a fare blur1=0 e blur2=0 nella funzione gaussiana, ma non funziona neanche.

Qualsiasi aiuto sarebbe apprezzato. Grazie in anticipo.

risposta

9

è necessario per normalizzare l'immagine tra 0 e 255 prima di convertirlo in CV_8UC1

+0

Grazie per la risposta, che ha risolto il mio problema. Ho cambiato la riga floatGray = 255.0 * floatGray e usato cv :: normalize (floatGray, res, 0, 255, NORM_MINMAX, CV_8UC1) invece e ora funziona. Pensavo che moltiplicando per 255 si normalizzasse l'immagine, ma mi sbagliavo. Grazie. – stfani

7

Qui è la mia realizzazione (sto usando 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; 
} 

Il risultato come previsto:

normalized_image

Nota che è possibile specificare la dimensione del kernel come Size(0,0) e sarà calcolato dai valori sigma.

+0

Grazie, anche questo è molto utile. Voterò la tua risposta non appena avrò una maggiore reputazione. – stfani

0

Questa è l'implementazione di Python dello stesso algo sopra:

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) 

Outout:

enter image description here

Problemi correlati