Skip to content

Instantly share code, notes, and snippets.

@laurynas
Forked from pceres/blur_detector
Created November 19, 2011 07:29
Show Gist options
  • Save laurynas/1378592 to your computer and use it in GitHub Desktop.
Save laurynas/1378592 to your computer and use it in GitHub Desktop.
blurry photos detection
#! /bin/bash
#
# Author: Pasquale Ceres (pasquale_c@hotmail.com)
# License: GPL ver. 3
#
# Script originally developed for the
# "San Lorenzo Martire Caposele Church Records Digitalization Project"
#
# http://www.facebook.com/group.php?gid=188973755117&v=photos
# http://ars.altervista.org/PhpGedView/index.php
#
#
# parameters
#
image_ext=JPG # image extension
logfile=report.txt # logfile with the list of all photos sorted by blur level
logfile_full=report_unsorted.txt # logfile with the list of all photos not sorted
temp_folder=/tmp # temporary folder
output_folder=blurry_folder # folder into which the most blurred photos are copied
perc_output_images=20 # [%] percentage of most blurred images to be copied into output folder
#
# show usage if no params in input
#
if [ ! $# == 1 ]; then
echo "Usage:"
echo "$0 <filename> : analyse the single image, determining its blur factor"
echo "$0 <folder> : analyse the images inside the folder"
exit
fi
#
# calculations
#
input=$1
if [ -d $input ]; then
# report on the files in the folder
#
# usage:
# blur_detector <folder_with_images>
#
echo "batch blur estimator..."
touch $logfile_full
rm $logfile_full
find $input -name "*.$image_ext" -exec blur_detector {} >> $logfile_full \;
# sort by blur index (from worst to best)
cat $logfile_full | sort -d -k 8.2 > $logfile
# copy blurred images to output folder
num_files=`cat $logfile | wc -l` # number of image files found
num_output_images=`echo $num_files*$perc_output_images/100.0 | bc | gawk '{printf("%d\n",int($1)+1)}'` # take a percentage
echo "copying $num_output_images (out of $num_files) blurriest photos into output folder..."
mkdir $output_folder
head $logfile -n $num_output_images | gawk '{n=split($1,a,"/");filename=sprintf("%03d_%s", FNR, a[n]);print filename; system("cp " $1 " ./'$output_folder'/" filename)}'
else
# report on single file
#
# usage:
# blur_detector <image_filename>
#
filename=$input
# original size
size0=`identify $filename | gawk '{print $3}'`
# reduce size, just take upper part of image
convert $filename -gravity north -crop 100x20% +repage $temp_folder/check0.jpg
size=`identify $temp_folder/check0.jpg | gawk '{print $3}'`
# create black image
convert -size $size xc:black $temp_folder/black.jpg
# create check image
convert -noise 2 -sigmoidal-contrast 6x25% -edge 2 $temp_folder/check0.jpg $temp_folder/check.jpg
# calculate blur factor
blur_value=`compare -metric RMSE $temp_folder/check.jpg $temp_folder/black.jpg $temp_folder/out.jpg 2>&1`
echo "$filename : $size0 -> $size : $blur_value"
# remove work files
rm $temp_folder/check0.jpg $temp_folder/check.jpg $temp_folder/black.jpg $temp_folder/out.jpg
fi
@KnutssonDevelopment
Copy link

Hi,

Just wondering if you have had any luck with this script? I have tested it for a couple of days now, and I have not had much luck.

The thing is that most photographs is not really going to be sharp in the top, where this script tests, since you often focus on stuff in the middle, or by the rule of thirds. (http://en.wikipedia.org/wiki/Rule_of_thirds)

I carved some pictures into small pieces. 20% by 20% and tested 5 of the peaces, that where around the normal focus points, the purpose was to let the MOST SHARP piece set the grade for the image, but i cannot get consistent results with the method you present in the script. The trouble i that a sharp piece can get more or less the same result as a piece totally out of focus.

I am not sure why this method would work, since I don't understand how it is supposed to work, but it seems that if there are defined lines in the peace tested it gets a high score whether the piece is sharp or not.

Do you have any ideas how to make this work better? Or did you get smarter since the time where you created this?

Did anyone else have luck using this or knows of anything else that can sort the blurry pictures out automatic.

Best Regards
Mnemonic

@nucleare
Copy link

nucleare commented Feb 9, 2022

It's been almost 10 years since @KnutssonDevelopment commented and I wonder if since then you've found an alternative? You would think that if camera software could utilize auto-focus to determine when a photo was sharp, it could simply change the rules and apply it to interpreting the data presented on a screen, but it's odd how difficult it can be to find something so trivial. Or, perhaps that's just the lazy of us. Personally, I sometimes have to sort through 20,000 photos and anything to automate this would save me at least an hour.

As a top Google search result, if anyone would like to try an alternative, here's a Python script version:

#
# Sorts pictures in current directory into two subdirs, blurred and ok
#

import os
import shutil
import cv2

FOCUS_THRESHOLD = 80
BLURRED_DIR = 'blurred'
OK_DIR = 'ok'

blur_count = 0
files = [f for f in os.listdir('.') if f.endswith('.jpg')]

try:
   os.makedirs(BLURRED_DIR)
   os.makedirs(OK_DIR)
except:
   pass

for infile in files:

   print('Processing file %s ...' % (infile))
   cv_image = cv2.imread(infile)

   # Covert to grayscale
   gray = cv2.cvtColor(cv_image, cv2.COLOR_BGR2GRAY)

   # Compute the Laplacian of the image and then the focus
   #     measure is simply the variance of the Laplacian
   variance_of_laplacian = cv2.Laplacian(gray, cv2.CV_64F).var()

   # If below threshold, it's blurry
   if variance_of_laplacian < FOCUS_THRESHOLD:
      shutil.move(infile, BLURRED_DIR)
      blur_count += 1
   else:
      shutil.move(infile, OK_DIR)

print('Done.  Processed %d files into %d blurred, and %d ok.' % (len(files), blur_count, len(files)-blur_count))

Courtesy of https://www.pyimagesearch.com/2015/09/07/blur-detection-with-opencv/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment