I'm trying to implement in OpenCV a local normalization algorithm to reduce the difference of illumination in an image. I have found a MATLAB function, and I have implemented it in OpenCV. However, the result that I get is different from the one given by the MATLAB function.
This is my 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;
}
The function NormInv is the C++ implementation given by Euan Dean in this post.
The following shows the result that I am getting and the theoretical result, for the same values of sigma1 and sigma2 (2.0 and 20.0, respectively)

I have tried using different values for sigma1 and sigma2, but none of them seem to work. I have also tried doing blur1=0 and blur2=0 in the Gaussian function but it doesn't work either.
Any help would be appreciated. Thanks in advance.
you need to normalize the image between 0 and 255 before converting it to CV_8UC1
Here is my implementation (I am using 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;
}
The result as expected:

Note that you can specify the kernel size as Size(0,0) and it will be computed from the sigma values.
This is the Python implementation of the same algo above:
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:

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With