Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Illumination Normalization not giving expected results

Hello

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

http://lear.inrialpes.fr/pubs/2007/TT07/Tan-amfg07a.pdf

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

https://github.com/bytefish/opencv/blob/master/misc/tan_triggs.cpp

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:

https://dl.dropboxusercontent.com/u/108321090/a1.png https://dl.dropboxusercontent.com/u/108321090/Screenshot_2013-12-31-14-09-25.png

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

//GET IMAGE URI
Uri selectedImage = imageReturnedIntent.getData();

//CREATE BITMAP FROM IT
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;      

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

//CREATE OPENCV MAT OBJECT
Mat imageMat = new Mat();
Utils.bitmapToMat(bmp, imageMat);

//CONVERT TO GRAYSCALE
Mat grayMat = new Mat();
Imgproc.cvtColor(imageMat, grayMat, Imgproc.COLOR_BGR2GRAY);

//CUT OUT FACE FROM WHOLE IMAGE
(...) 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 grayMat = 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);

//DISPLAY MAT IN IMAGEVIEW
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), I, I);
    }

    // Squash into the tanh:
    {
        for(int r = 0; r < I.rows(); r++) {
            for(int c = 0; c < I.cols(); c++) {
                I.get(r,c)[0] = Math.tanh(I.get(r,c)[0]) / tau;
            }
        }
        Core.multiply(I,new Scalar(tau), I);
    }
    return I;
}

And what I didn't understand while I was rewriting this code was the iteration over the matrix. In .cpp there was

I.at<float>(r,c)

Where I have replaced it with just:

I.get(r,c)[0]

Do you think I might have lost some data here so thats why image is shady?

Illumination Normalization not giving expected results

Hello

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

http://lear.inrialpes.fr/pubs/2007/TT07/Tan-amfg07a.pdf

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

https://github.com/bytefish/opencv/blob/master/misc/tan_triggs.cpp

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:

https://dl.dropboxusercontent.com/u/108321090/a1.png https://dl.dropboxusercontent.com/u/108321090/Screenshot_2013-12-31-14-09-25.png

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

//GET IMAGE URI
Uri selectedImage = imageReturnedIntent.getData();

//CREATE BITMAP FROM IT
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;      

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

//CREATE OPENCV MAT OBJECT
Mat imageMat = new Mat();
Utils.bitmapToMat(bmp, imageMat);

//CONVERT TO GRAYSCALE
Mat grayMat = new Mat();
Imgproc.cvtColor(imageMat, grayMat, Imgproc.COLOR_BGR2GRAY);

//CUT OUT FACE FROM WHOLE IMAGE
(...) 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 grayMat  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);

//DISPLAY MAT IN IMAGEVIEW
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), I, I);
    }

    // Squash into the tanh:
    {
        for(int r = 0; r < I.rows(); r++) {
            for(int c = 0; c < I.cols(); c++) {
                I.get(r,c)[0] = Math.tanh(I.get(r,c)[0]) / tau;
            }
        }
        Core.multiply(I,new Scalar(tau), I);
    }
    return I;
}

And what I didn't understand while I was rewriting this code was the iteration over the matrix. In .cpp there was

I.at<float>(r,c)

Where I have replaced it with just:

I.get(r,c)[0]

Do you think I might have lost some data here so thats why image is shady?

click to hide/show revision 3
retagged

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

berak gravatar image

Illumination Normalization not giving expected results

Hello

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

http://lear.inrialpes.fr/pubs/2007/TT07/Tan-amfg07a.pdf

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

https://github.com/bytefish/opencv/blob/master/misc/tan_triggs.cpp

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:

https://dl.dropboxusercontent.com/u/108321090/a1.png https://dl.dropboxusercontent.com/u/108321090/Screenshot_2013-12-31-14-09-25.png

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

//GET IMAGE URI
Uri selectedImage = imageReturnedIntent.getData();

//CREATE BITMAP FROM IT
BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();
bmpFactoryOptions.inPreferredConfig = Bitmap.Config.ARGB_8888;      

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

//CREATE OPENCV MAT OBJECT
Mat imageMat = new Mat();
Utils.bitmapToMat(bmp, imageMat);

//CONVERT TO GRAYSCALE
Mat grayMat = new Mat();
Imgproc.cvtColor(imageMat, grayMat, Imgproc.COLOR_BGR2GRAY);

//CUT OUT FACE FROM WHOLE IMAGE
(...) 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);

//DISPLAY MAT IN IMAGEVIEW
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), I, I);
    }

    // Squash into the tanh:
    {
        for(int r = 0; r < I.rows(); r++) {
            for(int c = 0; c < I.cols(); c++) {
                I.get(r,c)[0] = Math.tanh(I.get(r,c)[0]) / tau;
            }
        }
        Core.multiply(I,new Scalar(tau), I);
    }
    return I;
}

And what I didn't understand while I was rewriting this code was the iteration over the matrix. In .cpp there was

I.at<float>(r,c)

Where I have replaced it with just:

I.get(r,c)[0]

Do you think I might have lost some data here so thats why image is shady?