Ask Your Question

Illumination Normalization not giving expected results

asked 2013-12-31 07:25:27 -0500

Fisher gravatar image

updated 2013-12-31 10:59:51 -0500

berak gravatar image


I am using OpenCV4Android to process my images. I wanted to preform Illumination Normalization which was linked to me with this work:

furthermore I was given COMPLETE IMPLEMENTATION in C++ (OpenCV):

I tried to rewrite this code do Java, but I think there might be mistake somewhere. So, what I get from this alghorithm is close but not good enough. Check the expected results on the PDF above on page for example 12. And this is what i get:

So there is still too much noise between background and face features, but I think it's my fault here. This is my code:

Uri selectedImage = imageReturnedIntent.getData();

BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;      

Bitmap bmp = BitmapFactory.decodeStream(getContentResolver().openInputStream(selectedImage), 
                        null, bmpFactoryOptions);

Mat imageMat = new Mat();
Utils.bitmapToMat(bmp, imageMat);

Mat grayMat = new Mat();
Imgproc.cvtColor(imageMat, grayMat, Imgproc.COLOR_BGR2GRAY);

(...) face detection cascades localize face and writes the region where face is located 
in array, then I create mat with only face in it:

 Mat cleanFaceMatGRAY = new Mat();
cleanFaceMatGRAY = new Mat(faceDetectMatGRAY, facesArray[0]);

//PROCESSING OF MAT WITH FACE (alghorithm from PDF & .cpp file)
Mat I = tan_triggs_preprocessing(cleanFaceMatGRAY);
Core.normalize(I, I,0, 255, Core.NORM_MINMAX, CvType.CV_8UC1);

ivPickedPhoto.setImageBitmap(AppTools.createBitmapFromMat(I, Bitmap.Config.ARGB_8888));

And method with algorithm (as u can see its total copy-paste from .cpp file with edited/rewrited methods to OpenCV4Android):

private Mat tan_triggs_preprocessing(Mat image) {
    float alpha = 0.1f; 
    float tau = 10.0f;
    float gamma = 0.2f; 
    int sigma0 = 1;
    int sigma1 = 2;

    // Convert to floating point:
    Mat X = image;
    X.convertTo(X, CvType.CV_32FC1);
    // Start preprocessing:
    Mat I = new Mat();
    Core.pow(X, gamma, I);
    // Calculate the DOG Image:
        Mat gaussian0 = new Mat();
        Mat gaussian1 = new Mat();
        // Kernel Size:
        int kernel_sz0 = (3*sigma0);
        int kernel_sz1 = (3*sigma1);
        // Make them odd for OpenCV:
        kernel_sz0 += ((kernel_sz0 % 2) == 0) ? 1 : 0;
        kernel_sz1 += ((kernel_sz1 % 2) == 0) ? 1 : 0;
        Size ksize1 = new Size(kernel_sz0,kernel_sz0);
        Size ksize2 = new Size(kernel_sz1,kernel_sz1);
        Imgproc.GaussianBlur(I, gaussian0, ksize1, sigma0, sigma0, Imgproc.BORDER_CONSTANT);
        Imgproc.GaussianBlur(I, gaussian1, ksize2, sigma1, sigma1, Imgproc.BORDER_CONSTANT);
        Core.subtract(gaussian0, gaussian1, I);

        double meanI = 0.0;
            Mat tmp = new Mat();
            Mat abstmp = new Mat();
            Core.absdiff(I, new Scalar(0), abstmp);
            Core.pow(abstmp, alpha, tmp);
            meanI = Core.mean(tmp).val[0];
        Core.divide( Math.pow(meanI, 1.0/alpha), I, I);

        double meanI = 0.0;
            Mat tmp = new Mat(); 
            Mat abstmp = new Mat();
            Mat mintmp = new Mat();
            Core.absdiff(I, new Scalar(0), abstmp);
            Core.min(abstmp, new Scalar(tau), mintmp);
            Core.pow(mintmp, alpha, tmp);
            meanI = Core.mean(tmp).val[0];
        Core.divide( Math.pow(meanI, 1.0/alpha ...
edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted

answered 2013-12-31 08:00:29 -0500

berak gravatar image

updated 2013-12-31 08:04:47 -0500

i think, this line (close to the end) might not be working:

// assigning to a copy ? probably needs a put() there on the left side
I.get(r,c)[0] = Math.tanh(I.get(r,c)[0]) / tau;<float>(r,c) ( in c++ ) is a reference type

(also, your result image looks like it's before the tanh)

edit flag offensive delete link more


I tried this: I.put(r, c, (Math.tanh(I.get(r,c)[0]) / tau)); instead of I.get(r,c)[0] = Math.tanh(I.get(r,c)[0]) / tau; but the result is much worse

Fisher gravatar imageFisher ( 2013-12-31 08:18:03 -0500 )edit

yes, that's what i meant. and the result is the expected outcome.

now you have to go and tweak alpha, gamma, tau, sigma

berak gravatar imageberak ( 2013-12-31 08:23:38 -0500 )edit

So you say that the result is correct but I need to experiment with the float alpha = 0.1f; float tau = 10.0f; float gamma = 0.2f; int sigma0 = 1; int sigma1 = 2; values? Did I get this right?

Fisher gravatar imageFisher ( 2013-12-31 08:26:34 -0500 )edit

yes, indeed.

(and the result is the same as in the c++ code now)

berak gravatar imageberak ( 2013-12-31 08:28:51 -0500 )edit

thank you for help then, it seems to get the result i want is still long way to go

Fisher gravatar imageFisher ( 2013-12-31 08:30:40 -0500 )edit

oh, also, bytefish had an additional normalizing pass after the tan-triggs (norm_0_255):

cv::normalize(src, dst, 0, 255, NORM_MINMAX, CV_8UC1);

berak gravatar imageberak ( 2013-12-31 08:41:20 -0500 )edit

I did one normalization after Mat I = tan_triggs_preprocessing(cleanFaceMatGRAY); did you try it in C++ and It gave better results?

Fisher gravatar imageFisher ( 2013-12-31 08:47:47 -0500 )edit

slightly better(smoother), but not much

berak gravatar imageberak ( 2013-12-31 09:25:49 -0500 )edit
Login/Signup to Answer

Question Tools

1 follower


Asked: 2013-12-31 07:25:27 -0500

Seen: 2,576 times

Last updated: Dec 31 '13