How Gyro-Cam Works

External links that leave my pages are in [square brackets]. If you have further questions about this system, please let me know.

The Hardware

A [small NTSC CCD color video camera] is fixed in one position in my garage, just below the ceiling and next to the wall opposite the project area. A 75 ohm RG6 coaxial video cable connects it to a video input jack on my VCR. A second coax cable connects a small amplified microphone directly above the work area to the mono audio input jack of the VCR. The 50 ft. cables are routed through the attic to my VCR which is positioned close to my computer; more on that later.

This simple set up is enough to record real-time summaries of each section directly onto videotape as you progress; no computer needed. After completing a working session, I hit record on the VCR and discuss what I just completed, then hit STOP.

The audio/video output of the VCR connects to the audio/video input of the [Hauppage] WinTV PCI video capture card in my computer. The computer continuously runs my custom timelapse video frame capture software. With the above wiring, the time-lapsed capturing can be easily paused without touching the computer by simply turning the VCR or camera off, thereby cutting off the video signal to the video capture card. I unplug my camera and turn the VCR off when I'm not working on the project to reduce any false frames.

The computer hardware is probably not critical. Mine is a 133 MHz [Intel] Pentium(R) Processor with 96 Megabytes of RAM. I have dedicated an entire 10.1 GB [IBM] Deskstar IDE hard disk drive to this project since it does require a lot of disk storage space. The operating system and everything else are on two smaller 1 GB and 2 GB SCSI disk drives. My hard disk drives are incrementally backed up onto an [HP] SCSI DAT tape drive automatically every night.

The Software

Firstly, I run only the [Linux] Operating System, partly due to its infinitely flexible programmability and excellent reliability (continuously runs for months on end auto-doing dozens of odd jobs for me). Sorry, I do not know how to make Windows(TM) do cool stuff, though you may be able to adapt this idea and/or software to other Operating Systems.

My [WinTV] frame grabber card is accessed by the excellent [BTTV] video4linux driver. I also run the way cool [xawtv] to set the card to grab from the video input and to preview what the camera is seeing.

timelapse

My custom time-lapsed video capture program is called timelapse. It takes a picture every n seconds. If this picture is brighter than the darkness threshold, it compares it against the last image that was saved to disk. If this image is more different than the difference threshold, it writes this one to disk and will use it to compare against next time. timelapse is a [perl] script that runs forever as a daemon process. It utilizes the [Perl Magick] module for access to [ImageMagick] image manipulation routines. The thresholds and other variables can be configured at the top of the program.

After setting up, timelapse starts an infinite loop to run forever. The first thing it does in the loop is to sleep until it is time to examine the image for change. The time between images can be set on the command line and defaults to 60 seconds. Using a value of one will run the time-lapse capture as fast as possible.

When it is time to examine the image, timelapse runs a simple C program to capture a single frame from the video capture device to a latest.jpg file. This C program is called grabone.c and is a simplified subset of the webcam.c code that comes with xawtv.

The last saved image is now read in from disk. A copy of both images is then scaled to a smaller size. I currently use 1/16 scale or from 640x480 to 40x30. This effectively reduces the number of pixels that need to be examined; multiple pixels are averaged into one.

Next, the images are quantized from color to grayscale. Now each pixel is an 8-bit "brightness" value from 0 being black to 255 being white. The pixels of the current image are now added to come up with a total "brightness". This sum is divided by the total that a 100% white image would produce, to come up with a fraction of brightness. If this brightness is less than the configured darkness threshold, then timelapse assumes the lights are off or this picture too dark to keep. It is then dropped and the program goes back to the top of the loop.

Otherwise the picture is bright enough to consider for differences. So the program now does a composite difference of this picture and the last saved one. This basically replaces each pixel with its' difference. If the pixel did not change significantly, you get numbers near 0. If it did change, you get a number proportional to the difference. The result is a now a mostly black image with gray or white where there are differences. This can be seen in my static sample images.

Now, the pixels of this difference image are added together to come up with the amount of change. Again the sum is divided by the total that a white image would produce, to come up with a fraction of change. If this number is less than the difference threshold, the image is considered the same. It is then dropped the program goes back to the top of the loop.

Finally, if the image has passed the brightness and difference tests, then it is saved to disk. The original full-size frame is first saved as last.jpg to be used in comparison next time through the loop. A timestamp is formatted and annotated onto the image. The timestamp is also used to create a unique filename of YYYY/MM/DD/HHMM[SS].jpg and the full-size image with timestamp is written there. This is linked to final.jpg so that there is always easy access to the last final saved result. The image is also written at 1/2 scale 320x240 in .yuv format to simplify .mpg compression later.

As timelapse runs, it appends its' actions to a grab.log file. This records the timestamp of each frame saved and its' brightness and difference values on one line, separated by tab characters. When frames are skipped, their values are remembered and then written as one line just before a new frame is saved. This line contains up to 3 tab-delimited fields:

busynum darknum:min/mean/max<threshold samenum@min/mean/max<threshold

This compactly records the number of frames skipped for each reason and the minimum, mean average and maximum values compared to the threshold that caused the frame to be dropped. This allows for later analysis to determine if the thresholds are set correctly.

The busynum counts the number of frames that were not analyzed because the video capture device was busy. Since only one program can use the hardware device at a time, grabone.c fails if the device is busy. This happens for example when xawtv is being used. This turns out to be a Good Thing since xawtv may be used to watch TV. We don't want to record timelapse of random TV broadcasts! Also, it provides a convenient way to suspend the timelapse process. Simply run xawtv to prevent frames from being recorded by timelapse. Always remember to reset the card source to video input before exiting xawtv.

Source Code

Copyright (C) 1998 - 1999 Timothy D. Witham

Distributed under the terms and conditions of the [GNU General Public License].

timelapse
Perl daemon that saves non-dark changed video frames
grabone.c
C program that grabs one video frame to a .jpg file, used by timelapse.
mpegit
Perl program that combines .yuv files into .mpg files
push, push.conf
Perl program to auto-update files by FTP
Makefile
Top-level Makefile that updates all data subdirectories
Makefile.mon
Month-level Makefile that updates the daily subdirectories
Makefile.day
Day-level Makefile that updates the daily .mpg movies
mpg/Makefile
mpg directory Makefile that updates the overview .mpg movies
I should probably document each of these better...


Timothy D. Witham <twitham@quiknet.com>
Last modified: Mon Feb 8 21:48:30 PST 1999