This is a tool that helps convert a timelapse series of photos from raw images to JPEGs, with a continuous EV curve, suitable for conversion to video. Using a continuous EV curve rather than relying on automatic camera settings, or manually tweaking camera settings avoids jarring changes in exposure when sitched together into a video.
Download the batch conversion script.
I originally wrote this (hack of a) shellscript when I was travelling to New York last year, and took a set of time-lapse photos from Brooklyn Bridge Park, looking back towards Manhattan at sunset. Originally, I had taken the photos with manual metering, and manually changed the exposure time as the light receded. This was somewhat accurate, but there were still harsh transitions between the available stops on the camera - most SLRs only provide ½ or ⅓ stops between aperture and exposure time settings, and these transitions are very visible when images are combined into a video.
First up, a bit of theory. What is EV? EV, or Exposure Value, is a metric that summarises the relative amount of light passed by a given aperture, exposure time and sensitivity ("ISO") settings on a camera. The formula for EV is given as:
EV = log2 (100 / ISO * Aperture2 / time)
Effectively speaking, this means that an EV of 3 will pass twice the amount of light as EV 4, and due to the logarithmic nature of the eye's sensitivity to light, EV is a useful linear approximation of how bright a scene will be perceived. So, back to the example. I took nearly 500 photos about 3 seconds apart, with manual changes in the exposure time, guided by the camera's exposure sensor. The limitations of ½ or ⅓ stop changes in illumination can be clearly seen when plotted:
This isn't exactly ideal. Some of these jumps can be as severe as ⅔ of a stop, only to jump back up again a few frames later. What we'd like to instead do is calculate an offset for each frame to smooth out the changes in exposure, and manually specify exposure compensation for each frame when converting from raw to JPEG. We'd prefer to watch a timelapse with exposure changes more like this:
There are two tasks we need to perform with the conversion: firstly, to obtain the exposure values of every photo in the series and to calculate a desired offset for each photo; and secondly, to perform the conversion from a raw image to JPEG for every photo, with the desired offset.
Obtaining the exposure values and calculating a desired EV curve is fairly simple with most timelapses that only last an hour or two - there will only be a single transition in light level of the scene, so we can assume a linear transition between the first frame's EV and the final frame's EV will give a reasonable result. The script allows for a fixed offset to be applied to the first and final frame, to allow for any consistent mis-metering of the scene.
As you might recall from the theory section, there are only three variables that we need consider - exposure time, aperture and ISO sensitivity. Nearly every digital camera on the market includes EXIF metadata that specifies attributes such as date/time, aperture, camera model and exposure length. By exporting this metadata into text with the tool exiv2, we can calculate the EV for each image.
Once the EV curve has been calculated, we use the UFRaw fork of Dave Coffin's DCRaw tool, which provides a library for decoding the myriad digital camera raw image formats out there. We call ufraw with --exposure=${OFFSET}, and convert the raw images to high-quality JPEG.