5x12 pentomino tiling
«

Beth's Magic Script

»

I've written here before about "Beth's magic script" for stacking images for HDR purposes and I've been meaning to write that up as other people in Milton Photographic club had expressed an interest so here goes. If you're not into photography feel free to click "Next".

The script takes a stack of images of different exposures and merges them. So, using the example I showed before, here's three images my camera took of All Saints' church, at 0EV, -2EV and +2EV using the auto-bracketing setting (click on any image to see a larger version):

All Saints' church, Milton -2EV
0EV
     
All Saints' church, Milton 0EV
-2EV
     
All Saints' church, Milton +2EV
+2EV

The one on the left is the one at the "correct" exposure and it looks like this:

All Saints' church, Milton

Nice sky, good exposure on most of the church except for the bit in the shade, but the foreground is just lost in shadow. But here's the same view made using Beth's script to merge the three images together:

All Saints' church, Milton

The sky and the church are still fine, but you've got a bit more detail on the tower side facing left especially in the shadow and you can now see into the shadow in the foreground. That's the magic.

So anyway this is my version of Beth's original script:

#!/bin/bash
#

function stack_images()
{
    FILES=
    LAST=

    FIRST=$1

    until [ -z "$1" ] ; do  # Until all parameters used up . . .
        if [ `basename $1` = `basename $1 SRW` ] ; then
            FILES=$FILES" "$1
        else
            dcraw -T -6 -W -H 0 $1
            FILES=$FILES" "`basename $1 SRW`tiff
        fi
        LAST=`basename $1 .tiff`
        LAST=`basename $LAST .JPG`
        shift
    done

    align_image_stack -v -a /tmp/align_ $FILES

    STACKED_JPEG=${LAST}_stacked.JPG
    
    enfuse -v --wExposure=0.5 --wSaturation=0.0 -o $STACKED_JPEG /tmp/align_*.tif
 
    # mogrify -sigmoidal-contrast 5 stacked.jpg

    rm /tmp/align_*.tif

    exiv2 ex $FIRST
    mv `basename $FIRST JPG`exv `basename $STACKED_JPEG JPG`exv
    exiv2 in $STACKED_JPEG
    rm `basename $STACKED_JPEG JPG`exv
}

IN_STACK=0

if [ $# -gt 0 ] ; then
    stack_images $*
else
    for FILE in *JPG ; do
        case $IN_STACK in
            0)
                EXP=`exiv2 $FILE | grep "Exposure bias" | awk '{ print $4 }'`
                if [ $EXP = "(0/0)" ] ; then
                    FILE1=$FILE
                    IN_STACK=1
                fi
                ;;
            1)
                FILE2=$FILE
                IN_STACK=2
                ;;
            2)    
                stack_images $FILE1 $FILE2 $FILE
                IN_STACK=0
                ;;
        esac
    done
fi

# Overrides for Emacs
# -------------------
# Local variables:
# mode: sh
# End:

All the real work happens in the function stack_images(). Here the parameters are the pathnames to your images and the steps are:

  1. if the images are SRWs (Samsung EX1 RAW files) then convert them to TIFF format using dcraw (if your RAW files have a different extension you will need to change that line).
  2. use align_image_stack (part of the hugin project) to align the images, which by now are either TIFFs or JPEGs.
  3. use enfuse to merge the images together, naming the resulting JPEG using the name of the last image.
  4. optionally use mogrify (part of Imagemagick) to tweak the contrast of the stacked image (this is from Beth's original script but I found I didn't need that, which is why it's commented out).
  5. take the EXIF data from the first image of the stack and use that as the EXIF data for the stacked image.

So the key bits of magic are that:

  • dcraw means that the script can cope with a stack of images which are JPEGs, RAW files (if you tweak it), or TIFFs.
  • align_image_stack means that the images don't need to be perfectly aligned, so no need for a tripod: hand held should be good enough so long as you're using a camera which does autobracketing.
  • enfuse means you can get what is effectively a cheap and dirty version of HDR of the stack quickly and without fuss as part of a batch process. Basically what it does is combine images that overlap into a single image with good exposure and good focus using the Mertens-Kautz-Van Reeth exposure fusion algorithm (Adobe/PDF, 4.0MB).

Step 5. above, where I'm copying the EXIF data, is because my Samsung EX1 produces a set of three bracketed images and the first one is the one at 0EV so that's likely to be closest to the correct exposure of the stacked image. If your camera produces its set in a different order you would need to re-code.

I won't say much about the main body of the code which calls stack_images() other than to observe that it has two modes of operation: one where you explicitly tell it which images you want it to stack and the other where you just run it in the directory where some stacked images live and it relies on the EXIF data to detect the stack sets among the images it finds there. As such it will probably only work as written for photos taken by a Samsung EX1 so you will need to rewrite it or simply drop it and replace it with:

if [ $# -gt 0 ] ; then
    stack_images $*
else
    echo Give me some images
fi

All the software described in this post is Open Source and either available in the common distributions or can be downloaded and compiled from source.

Oh yes, and if you're not using Linux then Cygwin may be your friend although I'm told that enfuse at least is available built for Windows.


Update: 15/12/12

I discovered a camera new Android app for my elderly Motorola Defy yesterday. I'd previously used ProCapture (which I still recommend, it's very versatile and the panorama mode it very clever) but there's another app Camera FV-51 which does pretty much everything ProCapture does (except panoramas) plus more beside and especially bracketed sets. It's limited by phone cameras being fix aperture so it has to rely on a combination of ISO and shutter speed to vary the exposure but it does work. It will do ±2EV if your phone supports it. Mine will only manage ±1EV but even so it's not bad. Here's a stack I took pointing down our drive this morning (click on any image to see a larger version):

-2EV
-1EV
     
0EV
0EV
     
+2EV
+1EV

And here's the resulting image after pushing the stack through Beth's magic script.

Stacked image

I think this actually illustrates the benefits of the script even better than the original example, perhaps because the camera is more basic. Even though I'm only using ±1EV you can really see into the shadow now (although the sky is a bit blown out, but it is in all the images in the stack so that's not surprising).

  1. This is the Lite version with limited picture resolution support, the full "Pro" version is only £2.47 so I'll be upgrading shortly unless I find any major gotchas.

Tags: linux, photos Written 12/12/12

Comment on this article

« »
I am currently reading:

A History of Women in 101 Objects by Annabelle Hirsch Game On by Janet Evanovich

(?)
Word of the Day:
polity