I will apologize a head of time for this posting.  It takes a bit of a dive into nerdom with some technical specifications, talk of _Linux, servers, _a mentioning of a thing called firewire and, at the end, there is information on the software that I am using to make time lapse videos.  But, interspersed between bits of this and that are some time lapse videos as well as some other nice photos.

Around five years ago, I made a time lapse video from a series of photographs.  The photographs, all 4,748 of them, were taken using a JVC MiniDV camcorder. The camera was tethered to a PowerBook (running Linux) via a firewire cable; the laptop would trigger the camera and then download the still-frame every 15 minutes.  Each photo was then uploaded to a server that was running in the basement.  The original video that was produced was over ten minutes long – the above video is a reprocessed version sped-up by four times.

Using a bit of software that I wrote, each photo was analyzed to determine if it was “too dark”. The analysis consisted of averaging the value of all the colors contained in a given photo; if the average was too close to black, the photo was rejected.  Another bit of processing involved inserting text, a timestamp and a watermark into the photo being processed.  Given the tools I was working with – a crufty PowerBook (held together with duct tape) running Linux and a MiniDV camera – embedding the text, timestamp and watermark as part of the photo/image made sense to me at the time.  Looking back, it would have been more useful to not have embedded that information into the images; some other location – either an ancillary place or even within each JPEG.

This go around, I am still using a nine year old camera (in 2009, the camera I used was from 2000), but a nine year old in 2014 is a different bit of technology than a nine year old camera in 2009.  The _new__ _camera is a Nikon D50 with a 35-70mm lens.  The camera body, lens, DC power adapter, and USB cable came to a total of about $225.  The laptop that is effectively acting as an intervalometer would likely sell for another $225 (or less), but since the laptop is one that I have had for a long while and no longer actively use it, it is plausible to think of it as having no cost for me.

If you are still unclear as to what I am talking about with intervalometers, laptops and Nikon cameras, the basic idea is making a camera take a picture again and again and again at a regular interval.  It is kind of like regular motion pictures but on a much slower pace.  Instead of having 24 or 30 frames per second (as with a typical motion picture), there is only one frame every fifteen minutes.  Fifteen minutes is about the closest interval between photos that does not cause a tremendous waste of disk space and, in my case, you are able to capture enough difference in plant growth that it is noticeable; at 5 megabytes per photo, it amounts to a little less than half a gigabyte per day – with the particular laptop, I could safely shoot 140 days of photos.  Add a tweak to the software mix – and push the photos else where – like Amazon S3 – and you have an unlimited number of days.

Once I have a pile of photos, they need to be strung together into a video. In the Apple ecosystem, there is iMovie.  It is relatively inexpensive and is fairly easy to use.  This is what I use.  If you are hellbent on free or open source – checkout ffmpeg.

But that does not actually clear-up getting photos from the Nikon to the laptop; it also does not clear-up getting the laptop to trigger the camera at regular intervals.

I am using gphoto2.  This is a bit of open source software.  It took a bit of wrangling to get it to work, but it is quite robust and, so far, is quite reliable.  At the end of this posting, there are some random notes and a link to a bit of software I wrote to make it easier to trigger, download from the camera, and rename the photos in a consistent manner.

I am not sure why I like making or even watching time lapse videos of plants growing.  Maybe it has to do with being able to visualize something that ordinarily takes too long to be noticed by the human eye.

Maybe, I just feel a bit like Art Clokey.

Currently, the photo-snapping-rig is busy taking photos of a seedling started from a seed I pulled from a Braeburn apple.  The seedling is about an inch tall; its cotyledons have spread and the second set of leaves are little tiny spikes just above the stem.  I plan to photograph it for a couple weeks, or until the tripod the camera is attached to gets bumped.

Notes for a deep dive into nerdom:

If you are using Windows, you are on your own – I have not been an active or engaged Windows user for years. You’ll likely need cygwin in order to get gphoto2 working.  If you are using a Mac, I found it easiest to use homebrew.  Install homebrew, and then a simple brew install gphoto2 did the trick to get it installed.  I also installed ufraw for processing Nikon Raw format photos, but this is not necessary if you are using other Apple pieces of software for knitting your photos into movies (e.g. iMovie).

The camera needs to be in “PTP Mode” to communicate over USB; this is done by actually changing a setting on the camera – most likely by changing a setting from USB Mass Storage to PTP Mode. Once you have done that, with the camera connected to the computer, issue the command:

gphoto2 –auto-detect.

#> gphoto2 --auto-detect
Model                          Port                                            
Nikon D50 (PTP mode)           usb:253,003


If you are on a Mac, you will likely get an error at this point – instead of getting the listing of the attached camera.  Apple has a “helper process” that may latch onto the USB of the attached camera.  This will prevent gphoto2 from being able to communicate with it.

My solution was a bit of a big hammer.  I moved the offending program out of the way so it could be executed to latch onto the USB.  Another approach would be to terminate the process.  The program is called “PTPCamera”; if you would like to use the small-hammer approach, terminating it from a command line can be done like this:

ps -ax | grep PTPCamera | grep -v ' grep ' | awk '{print $1}' | xargs kill -9


Or the big-hammer approach:

sudo mv /System/Library/Image\ Capture/Devices/PTPCamera.app /tmp

You might still need to terminate the process even if you move the program out of the way.

Once you have the PTPCamera process terminate/moved, try running gphoto2, again.

#> gphoto2 --summary
Camera summary:                                                                
Manufacturer: Nikon Corporation
Model: D50
  Version: V1.00
Vendor Extension ID: 0xa (1.0)
Vendor Extension Description: Nikon PTP Extensions

Capture Formats: JPEG Undefined Type
Display Formats: Undefined Type, Association/Directory, TIFF, JPEG, DPOF, Script

Device Capabilities:
	File Download, File Deletion, File Upload
	Generic Image Capture, No Open Capture, Nikon Capture 1

Storage Devices Summary:
	StorageDescription: None
	VolumeLabel: NIKON D50
	Storage Type: Removable RAM (memory card)
	Filesystemtype: Digital Camera Layout (DCIM)
	Access Capability: Read Only with Object deletion
	Maximum Capability: 2014969856 (1921 MB)
	Free Space (Bytes): 2009399296 (1916 MB)
	Free Space (Images): 267

Device Property Summary:
Battery Level(0x5001):(read only) (type=0x2) Range [0 - 100, step 1] value: 100% (100)
Image Size(0x5003):(readwrite) (type=0xffff) Enumeration [
	] value: '1504x1000'
Compression Setting(0x5004):(readwrite) (type=0x2) Enumeration [0,1,2,4,5] value: RAW (4)
White Balance(0x5005):(readwrite) (type=0x4) Enumeration [2,4,5,6,7,32784,32785,32787] value: Automatic (2)
F-Number(0x5007):(readwrite) (type=0x4) Enumeration [450,500,560,630,710,800,900,1000,1100,1300,1400,1600,1800,2000,2200,2500,2900,3200] value: f/4.5 (450)
Focal Length(0x5008):(read only) (type=0x6) Range [3500 - 7000, step 1] value: 70 mm (7000)
Focus Mode(0x500a):(read only) (type=0x4) Enumeration [1,32784,32785,32786] value: Manual Focus (1)
Exposure Metering Mode(0x500b):(readwrite) (type=0x4) Enumeration [2,3,4] value: Multi-spot (3)
Flash Mode(0x500c):(readwrite) (type=0x4) Enumeration [2,4,32784] value: Auto (32784)
Exposure Time(0x500d):(read only) (type=0x6) Enumeration [20,25,31,40,50,62,80,100,125,166,200,250,333] value: 0.0017 sec (166)
Exposure Program Mode(0x500e):(read only) (type=0x4) Enumeration [1,2,3,4,32784,32785,32786,32787,32788,32789,32791] value: Auto (32784)
Exposure Index (film speed ISO)(0x500f):(readwrite) (type=0x4) Enumeration [200,400,800,1600] value: ISO 200 (200)
Exposure Bias Compensation(0x5010):(readwrite) (type=0x3) Enumeration [-5000,-4666,-4333,-4000,-3666,-3333,-3000,-2666,-2333,-2000,-1666,-1333,-1000,-666,-333,0,333,666,1000,1333,1666,2000,2333,2666,3000,3333,3666,4000,4333,4666,5000] value: 0.0 stops (0)
Date & Time(0x5011):(readwrite) (type=0xffff) '20140330T221926'
Still Capture Mode(0x5013):(readwrite) (type=0x4) Enumeration [1,2,32785,32787,32788] value: Power Wind (2)
Burst Number(0x5018):(readwrite) (type=0x4) Range [1 - 49, step 1] value: 1
Focus Metering Mode(0x501c):(readwrite) (type=0x4) Enumeration [2,32784,32785] value: Closest Subject (32785)
White Balance Preset Number(0xd01f):(readwrite) (type=0x2) Range [0 - 1, step 1] value: 0
White Balance Preset Value 0(0xd025):(read only) (type=0x6) 33685926
White Balance Preset Value 1(0xd026):(read only) (type=0x6) 33685926
Sharpening(0xd02a):(readwrite) (type=0x2) Range [0 - 6, step 1] value: Auto (0)
Tone Compensation(0xd02b):(readwrite) (type=0x2) Range [0 - 6, step 1] value: Auto (0)
Color Model(0xd02c):(readwrite) (type=0x2) Range [0 - 2, step 1] value: sRGB (0)
Hue Adjustment(0xd02d):(readwrite) (type=0x1) Range [-9 - 9, step 3] value: 0
Reset Menu Bank(0xd045):(readwrite) (type=0x2) Range [0 - 1, step 1] value: 0
Auto ISO(0xd054):(readwrite) (type=0x2) Range [0 - 1, step 1] value: On (1)
Exposure Step(0xd056):(readwrite) (type=0x2) Range [0 - 2, step 1] value: 1/3 (0)
Exposure Lock(0xd05e):(readwrite) (type=0x2) Range [0 - 1, step 1] value: Off (0)
Focus Lock(0xd05f):(readwrite) (type=0x2) Range [0 - 5, step 1] value: AE/AF Lock (0)
Auto Meter Off Time(0xd062):(readwrite) (type=0x2) Range [0 - 3, step 1] value: 6 seconds (1)
Self Timer Delay(0xd063):(readwrite) (type=0x2) Range [0 - 3, step 1] value: 10 seconds (2)
LCD Off Time(0xd064):(readwrite) (type=0x2) Range [0 - 4, step 1] value: 20 seconds (1)
Long Exposure Noise Reduction(0xd06b):(readwrite) (type=0x2) Range [0 - 1, step 1] value: Off (0)
File Number Sequencing(0xd06c):(readwrite) (type=0x2) Range [0 - 2, step 1] value: Off (0)
NIKON Auto Bracketing Set(0xd07c):(readwrite) (type=0x2) Range [0 - 2, step 1] value: 0
No CF Card Release(0xd08a):(readwrite) (type=0x2) Range [0 - 1, step 1] value: Off (1)
Image Comment String(0xd090):(readwrite) (type=0xffff) '                                    '
Image Comment Enable(0xd091):(readwrite) (type=0x2) Range [0 - 1, step 1] value: Off (0)
Image Rotation(0xd092):(readwrite) (type=0x2) Range [0 - 1, step 1] value: On (0)
Auto Exposure Bracket Count(0xd0c3):(read only) (type=0x2) Range [1 - 3, step 1] value: 1
White Balance Bracket Step(0xd0c4):(readwrite) (type=0x2) Range [0 - 2, step 1] value: 0
Lens ID(0xd0e0):(read only) (type=0x2) 29
Lens Sort(0xd0e1):(read only) (type=0x2) Range [0 - 1, step 1] value: 1
Lens Type(0xd0e2):(read only) (type=0x2) 0
Min. Focal Length(0xd0e3):(read only) (type=0x6) 35 mm (3500)
Max. Focal Length(0xd0e4):(read only) (type=0x6) 70 mm (7000)
Max. Aperture at Min. Focal Length(0xd0e5):(read only) (type=0x4) f/3.3 (330)
Max. Aperture at Max. Focal Length(0xd0e6):(read only) (type=0x4) f/4.5 (450)
Nikon Exposure Time(0xd100):(read only) (type=0x6) Enumeration [66036,65936,65856,65786,65736,65696,65661,65636,65616,65596,65586,65576,65566] value: 65596
AC Power(0xd101):(read only) (type=0x2) Range [0 - 1, step 1] value: Yes (1)
Warning Status(0xd102):(read only) (type=0x2) 0
Maximum Shots(0xd103):(read only) (type=0x2) Range [0 - 49, step 1] value: 4
AF Locked(0xd104):(read only) (type=0x2) Range [0 - 1, step 1] value: No (0)
AE Locked(0xd105):(read only) (type=0x2) Range [0 - 1, step 1] value: No (0)
FV Locked(0xd106):(read only) (type=0x2) Range [0 - 1, step 1] value: No (0)
Active AF Sensor(0xd108):(readwrite) (type=0x2) Range [0 - 4, step 1] value: Centre (0)
Flexible Program(0xd109):(readwrite) (type=0x1) Range [-30 - 30, step 2] value: 0
Exposure Meter(0xd10a):(read only) (type=0x1) Range [-128 - 127, step 1] value: -6.7 stops (-81)
Recording Media(0xd10b):(readwrite) (type=0x2) Range [0 - 1, step 1] value: Card (0)
CCD Serial Number(0xd10d):(read only) (type=0xffff) '            20058684'
Camera Orientation(0xd10e):(read only) (type=0x2) Range [0 - 2, step 1] value: 0' (0)
External Flash Attached(0xd120):(read only) (type=0x2) Range [0 - 1, step 1] value: No (0)
External Flash Status(0xd121):(read only) (type=0x2) Range [0 - 1, step 1] value: No (0)
External Flash Sort(0xd122):(read only) (type=0x2) Range [0 - 1, step 1] value: 0
External Flash Compensation(0xd124):(read only) (type=0x1) Range [-18 - 18, step 1] value: 0 (0)
External Flash Mode(0xd125):(read only) (type=0x2) Range [0 - 7, step 1] value: 0
Flash Exposure Compensation(0xd126):(readwrite) (type=0x1) Range [-18 - 6, step 2] value: 0.0 stops (0)
Optimize Image(0xd140):(readwrite) (type=0x2) Range [0 - 7, step 1] value: Normal (0)
Saturation(0xd142):(readwrite) (type=0x2) Range [0 - 2, step 1] value: Normal (0)
AF Beep Mode(0xd160):(readwrite) (type=0x2) Range [0 - 1, step 1] value: Off (1)
Autofocus Mode(0xd161):(readwrite) (type=0x2) Range [0 - 2, step 1] value: AF-A (2)
AF Assist Lamp(0xd163):(readwrite) (type=0x2) Range [0 - 1, step 1] value: On (0)
Auto ISO P/A/DVP Setting(0xd164):(readwrite) (type=0x2) Range [0 - 7, step 1] value: 1/30 (2)
Image Review(0xd165):(readwrite) (type=0x2) Range [0 - 1, step 1] value: On (0)
AF Area Illumination(0xd166):(readwrite) (type=0x2) Range [0 - 2, step 1] value: Auto (0)
Flash Mode(0xd167):(readwrite) (type=0x2) Range [0 - 1, step 1] value: iTTL (0)
ISO Auto(0xd16a):(readwrite) (type=0x2) Range [0 - 1, step 1] value: 0
Remote Timeout(0xd16b):(readwrite) (type=0x2) Range [0 - 3, step 1] value: 1 min (0)
Flash Mode Manual Power(0xd16d):(readwrite) (type=0x2) Range [0 - 4, step 1] value: Full (0)
CSM Menu(0xd180):(readwrite) (type=0x2) Range [0 - 1, step 1] value: Yes (1)
Bracketing Frames and Steps(0xd190):(readwrite) (type=0x2) Range [0 - 12, step 2] value: 12
Exposure Display Status(0xd1b0):(read only) (type=0x2) Range [0 - 4, step 1] value: No (0)
Flash Open(0xd1c0):(read only) (type=0x2) Range [0 - 1, step 1] value: Yes (1)
Flash Charged(0xd1c1):(read only) (type=0x2) Range [0 - 1, step 1] value: Yes (1)


Additional software used:  ruby (via rvm) and scheduling of photo snapping was done via crontab.