0

I want to detect blurred images using Laplacian Operator. This is the code I am using:

bool checkforblur(Mat img)
{
    bool is_blur = 0;
    Mat gray,laplacianImage;
    Scalar mean, stddev, mean1, stddev1; 
    double variance1,variance2,threshold;
    cvtColor(img, gray, CV_BGR2GRAY);
    Laplacian(gray, laplacianImage, CV_64F);
    meanStdDev(laplacianImage, mean, stddev, Mat()); 
    meanStdDev(gray, mean1, stddev1, Mat()); 
    variance1 = stddev.val[0]*stddev.val[0];
    variance2 = stddev1.val[0]*stddev1.val[0];
    double ratio= variance1/variance2;
    threshold = 90;
    cout<<"Variance is:"<<ratio<<"\n"<<"Threshold Used:"
    <<threshold<<endl;
    if (ratio <= threshold){is_blur=1;}
    return is_blur;
}

This code takes an image as input and returns 1 or 0 based on whether the image is blurred or not. As suggested I edited the code to check for ratio instead of variance of the laplacian image alone.

But still the threshold varies for images taken with different cameras.

Is the code scene dependent?

How should I change it?

Example:

Good

For the above image the variance is 62.9 So it detects that the image is blurred.

Bad

For the above image the variance is 235, Hence it is detecting wrongly as not blurred.

janu777
  • 1,940
  • 11
  • 26

2 Answers2

2

The Laplacian operator is linear, so that its amplitude varies with the amplitude of the signal. Thus the response will be higher for images with a stronger contrast.

You might have a better behavior by normalizing the values, for instance using the ratio of the variance of the Laplacian over the variance of the signal itself, or over the variance of the gradient magnitude.


I also advise you to experiment using sharp images that you progressively blur with a wider and wider gaussian, and to look at the plots of "measured blurriness" versus the know bluriness.

  • If you try this, please let us know the outcome. –  Dec 12 '17 at 09:01
  • Thank you for your time. I have edited the question. Is that what you were suggesting? – janu777 Dec 12 '17 at 09:14
  • @janu777: yep. I didn't take care that you were computing the StdDev then converting to variance. I think that using the StdDev is even better. But before setting a fixed threshold, look at the values for different images and different levels of blur. –  Dec 12 '17 at 09:17
  • So instead of variance you suggest that I use the stdDev itself. Is that right? – janu777 Dec 12 '17 at 09:19
  • @janu777: yep, this makes the scale more linear (but it is not essential). –  Dec 12 '17 at 09:20
  • Yeah thanks. Let me test this out in images and check how it's working. Will update. – janu777 Dec 12 '17 at 09:21
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/161001/discussion-between-janu777-and-yves-daoust). – janu777 Dec 12 '17 at 09:25
  • Is the code scene dependent? Will it not work with different cameras? – janu777 Dec 14 '17 at 09:32
  • @janu777: experimentation will tell you. –  Dec 14 '17 at 09:59
  • I tested it and it doesn't work. So should I go building for deep learning models? Any suggestions? – janu777 Dec 14 '17 at 10:03
  • @janu777 I mean rigorous experimentation. –  Dec 14 '17 at 10:08
0

As suggested above, you should normalize this ratio. Basically, if you divide your variance by the mean value you will get the normalized gray level variance, which I think is what you are looking for.

That said, there is an excellent thread on blur detection which I would recommend - full of good info and code examples.