Question

I want to detect how blurred an image is, may be It can be called "blur extend". I found a useful paper for this:

http://www.cs.cmu.edu/~htong/pdf/ICME04_tong.pdf

I used OpenCV and implemented all steps from this paper, but the result is not same as result from this paper.

Can someone give me any advise for detecting "blur extend"?

Was it helpful?

Solution

You can detect a blurring image with using next algorithm:

  1. Convert the image into gray format.
  2. Calculate the maximal absolute second derivative from the gray image (for every point):

    d[x,y] = max(abs(2*d[x,y] - d[x,y+1] -d[x,y-1]), abs(2*d[x,y] - d[x+1,y] -d[x-1,y]));
    
  3. Calculate the histogram of this estimated image (maximal absolute second derivative).

  4. Find the upper quantile (0,999) of this histogram.

  5. If this value is less than the threshold (about 25% from image dynamic range), then the image is blurred.

  6. If you want to estimate a blur value, perform steps 2-5 for reduced image.

You can write these algorithms on their own or use one from the implementation of Simd Library (disclaimer: I'm the author).

  • Simd::BgrToGray or Simd::BgraToGray (for step 1).
  • Simd::AbsSecondDerivativeHistogram (for steps 2-5).
  • Simd::ReduceGray2x2 (for step 6).

OTHER TIPS

The answer of Ermlg looks close to best, but in code way in this way I achieved it.

The score below 100 was giving me somewhat blury images.

# applying fast fourier transform to fin d the blur images , taken threshold to be 100 but it can vary

import cv2

def variance_of_laplacian(frame_path):
    # compute the Laplacian of the image and then return the focus
    # measure, which is simply the variance of the Laplacian
    image = cv2.imread(frame_path)
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    return cv2.Laplacian(gray, cv2.CV_64F).var()

Source of method was from adrian rosebrock

One important point to note here is that an image can have some blurry areas and some sharp areas. For example, if an image contains portrait photography, the image in the foreground is sharp whereas the background is blurry. In sports photography, the object in focus is sharp and the background usually has motion blur. One way to detect such a spatially varying blur in an image is to run a frequency domain analysis at every location in the image. One of the papers which addresses this topic is "Spatially-Varying Blur Detection Based on Multiscale Fused and Sorted Transform Coefficients of Gradient Magnitudes" (cvpr2017).

  • the authors look at multi resolution DCT coefficients at every pixel. These DCT coefficients are divided into low, medium, and high frequency bands, out of which only the high frequency coefficients are selected.
  • The DCT coefficients are then fused together and sorted to form the multiscale-fused and sorted high-frequency transform coefficients
  • A subset of these coefficients are selected. the number of selected coefficients is a tunable parameter which is application specific.
  • The selected subset of coefficients are then sent through a max pooling block to retain the highest activation within all the scales. This gives the blur map as the output, which is then sent through a post processing step to refine the map.

This blur map can be used to quantify the sharpness in various regions of the image. In order to get a single global metric to quantify the bluriness of the entire image, the mean of this blur map or the histogram of this blur map can be used

Here are some examples results on how the algorithm performs: enter image description here

The sharp regions in the image have a high intensity in the blur_map, whereas blurry regions have a low intensity.

The github link to the project is: https://github.com/Utkarsh-Deshmukh/Spatially-Varying-Blur-Detection-python

The python implementation of this algorithm can be found on pypi which can easily be installed as shown below:

pip install blur_detector

A sample code snippet to generate the blur map is as follows:

import blur_detector
import cv2
if __name__ == '__main__':
    img = cv2.imread('image_name', 0)
    blur_map = blur_detector.detectBlur(img, downsampling_factor=4, num_scales=4, scale_start=2, num_iterations_RF_filter=3)

    cv2.imshow('ori_img', img)
    cv2.imshow('blur_map', blur_map)
    cv2.waitKey(0)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top