Overview
Digital SLRs record a number of information (metadata) about the shot being made together with the actual image. This includes for example the aperture, shutter speed and the focal length that were used during the shot. This information is stored in an Exchangeable Image Format (EXIF) datastructure, that we can read, and process. If you have a large collection of photos, you can learn about certain facts that you may not know otherwise. I’ve done, for example, an analysis of my collection in the context of focal length I use, before deciding on what prime lens I will purchase.
Attempt 1 – nodejs with exif module
If you are not into nodejs and coffeescript, you may skip this section entirely.
Prerequisites:
- nodejs
- coffeescript
- exif module (npm install exif)
- fs module (npm install fs)
The script will run through your directory and generate a comma-saparated-value file, with a date, aperture, focal length and exposure time, that then could be imported into Excel or used in Gnuplot.
ExifImage = require('exif').ExifImage
fs = require 'fs'
process_image = (img_filename) ->
console.log 'Processing file: ' + img_filename
new ExifImage { image : img_filename }, (err, img) ->
if err
console.log 'Error: ' + err.message
else
process.stdout.write tag.value for tag in img.exif when tag.tagName is 'DateTimeOriginal'
process.stdout.write ', ' + tag.value for tag in img.exif when tag.tagName is 'ExposureTime'
process.stdout.write ', ' + tag.value for tag in img.exif when tag.tagName is 'FocalLength'
process.stdout.write ', ' + tag.value for tag in img.exif when tag.tagName is 'FNumber'
process.stdout.write '\n'
process_directory = (dir_name) ->
fs.readdirSync(dir_name).forEach (file) ->
extension = file.split('.').pop()
if extension.toLowerCase() == 'jpg'
process_image dir_name + file
a = process.argv[2..]
a.forEach (val, index, array) ->
console.log 'Processing directory: ' + val
process_directory val
Unfortunately, even for a directory that contains 20 files this will not work. Your script will chew all available memory and crash. It will work for a directory with only few files though. Try it.
TODO: check how the existing exif module is implement it and see if it is possible to make it only use the EXIF record instead of loading the entire image into the memory.
Attempt 2 – bash and awk
After failing with the cool coffeescript-based histogram-drawing attempt, I’ve decide to quickly hack a command line bash script that would together with awk and command line exif program, achieve what I want: a histogram of all focal lengths used in a photo collection. This method is fast and reliable.
Prerequisites:
To do that for your collection, here’s what you’ll need
- bash
- awk
- exif (or any other command line executable tool you fancy, that can read EXIF data)
- (optional) gnuplot (command line plotting tool); you can use Excel or similar program, too.
If you do not have exif installed, and you are on macosx, to get exif you say: brew install exif (if you do not use homebrew, you should definitely give it a try; you’ll love it.).
If you on Linux, use your package manager and install exif. bash and awk come as default on both macosx and Linux.
First, we need to collect all the focal length from all the images in a given location. The following, will go into your specified DIRECTORY, and search for all files in the top level and all subdirectories. The command assumes that you store only images – if you want to limit it to .JPG or .jpg files only, check the manual for find command:
find DIRECTORY -type f -exec exif -m -t 'Focal Length' {} \; > mydata.txt
After that, you can have a look, and mydata.txt should contain something along the lines:
25.0 mm 20.0 mm 26.0 mm 16.0 mm 19.0 mm 39.0 mm 34.0 mm
Great. Now, we need to convert it to a histogram-like structure, so that we can visualize it on a graph. To do that, we’ll use cat and awk:
cat mydata.txt | awk '{count[$1]++} END {for (j in count) print j, count[j]}' > mydata
The above line will count each occurance of a given focal length, and combine it into a table. If you look inside mydata file, you should see something like that:
29.0 22 20.0 44 150.0 1 187.0 1 105.0 13 31.0 15
Now, with the mydata file, we’re ready to use gnuplot (or you can load the file into Excel). Simply fire up gnuplot, and do:
plot "mydata" w impulses lw 3 lc rgb "#00AA00"
Done. I hope you’ll enjoy checking what is the focal length you love to shoot at.
Check examples of focal length histograms of my photos.
Pingback: F-stop analysis of a photo collection – Praeteritio