6

I am attempting to locate the Variation for the Laplacian based on an image with the goal of getting a numerical value based on the blurriness of an image.

This is a useful post http://www.pyimagesearch.com/2015/09/07/blur-detection-with-opencv/

cv2.Laplacian(image, cv2.CV_64F).var()

I've been trying to implement the same without luck. My starting point is a byte[] representing the image (img):

Mat mat = new Mat(img.getImageHeight(), img.getImageWidth(), CvType.CV_8UC3);
Imgproc.cvtColor(mat, mat, Imgproc.COLOR_BGR2GRAY);
mat.put(0, 0, putData.getFileContents());
Imgproc.Laplacian(mat,mat, CvType.CV_64F);

Any help would be appreciated.

Essentially, I'm starting with an image and want to get a value representing the blurriness of an image using Laplacian.

Scott
  • 61
  • 1
  • 3

2 Answers2

14

The Laplacian transformation can be replaced by a kernel applied with the filter2D method. I have been running that same python example in a java program like this:

    Mat destination = new Mat();
    Mat matGray=new Mat();  
    Mat kernel = new Mat(3,3, CvType.CV_32F){
       {
          put(0,0,0);
          put(0,1,-1);
          put(0,2,0);

          put(1,0-1);
          put(1,1,4);
          put(1,2,-1);

          put(2,0,0);
          put(2,1,-1);
          put(2,2,0);
       }
    };        
    Imgproc.cvtColor(image, matGray, Imgproc.COLOR_BGR2GRAY);          
    Imgproc.filter2D(matGray, destination, -1, kernel); 
    MatOfDouble median = new MatOfDouble();
    MatOfDouble std= new MatOfDouble();        
    Core.meanStdDev(destination, median , std);

    Math.pow(std.get(0,0)[0],2);

Hope this helps your coding.

Note: The values I get from the Python and Java program are different and I still didn't figure out why. Anyway the java code runs well.

Found out why the values were not the same. Using the Imgproc.Laplacian method instead of Imgproc.filter2D produces exactly the same values in python and java.

The new code becomes:

Mat destination = new Mat();
Mat matGray=new Mat();  

Imgproc.cvtColor(image, matGray, Imgproc.COLOR_BGR2GRAY);          
Imgproc.Laplacian(matGray, destination, 3); 
MatOfDouble median = new MatOfDouble();
MatOfDouble std= new MatOfDouble();        
Core.meanStdDev(destination, median , std);

Math.pow(std.get(0,0)[0],2);

Much simpler and with same results as python.

Pedro Nogueira
  • 153
  • 1
  • 9
  • I have also been using this algorithm to find the best focus value in a collection of images taken at different focal lengths. However, I just evaluated 2 images where the results are not correct. My input images are gray scale so I create the image like this: `Mat image = Imgcodecs.imdecode(new MatOfByte(bytes), Imgcodecs.CV_LOAD_IMAGE_UNCHANGED)` I don't think I can upload the images to this post, but if anyone is interested in looking at them, I can send them to you. – Eric Hansen Jan 31 '20 at 02:24
  • Should the `put(1,0-1)` line be corrected as `put(1,0,-1)`? – Batta Jun 15 '22 at 14:37
0

I have not found any direct function to calculate the variance of an image in OpenCV. But I have found something to calculate the mean standard deviation. And from mathematics, the variance is just the square of the mean standard deviation.

This is how I calculate the mean standard deviation of an image

Mat im = Imgcodecs.imread("relative/path/to/file");
Imgproc.cvtColor(im, im, Imgproc.COLOR_BGR2GRAY);
MatOfDouble mu = new MatOfDouble(); // mean
MatOfDouble sigma = new MatOfDouble(); // standard deviation
Core.meanStdDev(d, mu, sigma);
double variance = Math.pow(mu.get(0,0)[0], 2);

I ran this on a some 37 JPGs I converted from RAW (each about 8MB) and it worked albeit slowly. I tried doing this for my 340 pictures and my laptop turned off. There should be ways to optimize this.

Igbanam
  • 5,904
  • 5
  • 44
  • 68
  • First of all, thank your for your post! Please let me know where the 'd' variable coming from? What is the value of d? It is same as im? –  Jan 20 '18 at 19:10