2013-02-14 17 views
5

Ich versuche in OpenCV einen lokalen Normalisierungsalgorithmus zu implementieren, um den Unterschied der Beleuchtung in einem Bild zu reduzieren. Ich habe eine MATLAB function gefunden, und ich habe es in OpenCV implementiert. Das Ergebnis, das ich erhalte, unterscheidet sich jedoch von dem Ergebnis der MATLAB-Funktion.Lokale Normalisierung in OpenCV

Dies ist mein 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; 
} 

Die Funktion NormInv ist die C++ Implementierung von Euan Dean in this post gegeben.

Die folgende Abbildung zeigt das Ergebnis, das ich erhalte und das theoretische Ergebnis für die gleichen Werte von sigma1 und sigma2 (2,0 und 20,0 beziehungsweise)

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

habe ich versucht, verschiedene Werte für sigma1 mit und sigma2, aber keiner von ihnen scheint zu funktionieren. Ich habe auch versucht, blur1=0 und blur2=0 in der Gaussian-Funktion zu tun, aber es funktioniert auch nicht.

Jede Hilfe wäre willkommen. Danke im Voraus.

Antwort

9

Sie müssen das Bild zwischen 0 und 255 vor dem Konvertieren es normalisieren CV_8UC1

+0

Vielen Dank für Ihre Antwort, die mein Problem gelöst. Ich habe die Zeile floatGray = 255.0 * floatGray geändert und stattdessen cv :: normalize (floatGray, res, 0, 255, NORM_MINMAX, CV_8UC1) benutzt und jetzt funktioniert es. Ich dachte, dass die Multiplikation mit 255 das Bild normalisieren würde, aber ich lag falsch. Vielen Dank. – stfani

7

ist hier meine Implementierung (ich benutze 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; 
} 

das Ergebnis als erwartet:

normalized_image

Beachten Sie, dass Sie die Kernelgröße alsangeben könnenund es wird aus den Sigma-Werten berechnet.

+0

Danke, das ist auch sehr hilfreich. Ich stimme deine Antwort ab, sobald ich einen höheren Ruf habe. – stfani

0

Dies ist die Python-Implementierung des gleichen algo oben:

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