Sunday, May 2, 2010

Photobooth Round 2 - Derby Day

I was having my first real party after buying my new place, so I decided to revive the photobooth to commemorate it. Only this time I took pictures!

The guts (camera, printer, software) were basically the same, but I had to build a new booth, since all I had from the last one was the white backdrop.

Despite using all the same software, I still hit a few glitches. First, I decided I wanted to upgrade the camera to something that would do a live preview while it was being controlled from the computer. That way, I wouldn't have to deal with getting the webcam pointed at the same spot as the actual camera. The readme for the Canon remote software has a list of cameras that can do that:

5. CAMERAS SUPPORTING IMAGE DISPLAY
================================================

The following Canon camera(s) can display the image on their LCD monitor
or output it to the Video Out terminal while connected to RemoteCapture.

- Canon PowerShot G2
- Canon PowerShot S40
- Canon PowerShot S30
- Canon PowerShot G3
- Canon PowerShot S45
- Canon PowerShot A70
- Canon PowerShot A60
- Canon PowerShot S50
- Canon PowerShot G5

Note
Please note that images in the camera's LCD monitor and Video Out output only
reflect the optical zoom and not the digital zoom when the digital zoom is
adjusted.
Please use the viewfinder display in the RemoteCapture Shooting window when
setting the digital zoom.

I bought a cheap Powershot S30 off of eBay to give it a try. Unfortunately, I was never able to get the A/V out to stay on once I plugged in the USB cable. Additionally, either the plug or my cord were faulty, so I had to hold it in a particular way to get video at all. Since I wasn't really able to get it working the way I wanted, I took the camera apart to take a look at the A/V jack and ended up breaking the whole thing. It won't even turn on now. Oh well -- back to the trusty A20 + webcam.

The second problem I has was that, for whatever reason, the Perl script I'd been using with the panic button was no longer working. I found a Python script that did work (once I got all the modules installed) and used that instead. Actually, it looks like someone just recently released a Python library that would simplify the script dramatically. Too bad I only found that now...

Anyway, here's what I had to do to get it working from a fresh install of Mint:
1) Download and extract pyusb
2) Open a command prompt and cd into the pyusb directory
3) sudo apt-get install libusb
4) sudo python setup.py install

And here's the exact Python script I used:
#!/usr/bin/python

# change the FILE= to point to the file you want mplayer to play
# change the very last line to change the command


# This work is licensed under the New BSD License
#
#Copyright (c) , Ross Bevington
#
#All rights reserved.
#
#Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
# * Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
#
#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
#"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
#LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
#A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
#CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
#EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
#PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
#PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
#LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
#NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
#SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# start PyPanic

import usb
import time
import os

DEVICEID = 0x1130
PRODUCTID = 0x0202
FILE = "/home/acid2000/Desktop/air_raid_siren.wav"

device = 0;

# find device
busses = usb.busses()

for bus in busses:
devices = bus.devices
for dev in devices:
#print dev.idVendor, dev.idProduct
if dev.idVendor==DEVICEID and dev.idProduct==PRODUCTID:
device = dev
conf = dev.configurations[0]
intf = conf.interfaces[0][0]
if device == 0:
print "Could not find device"
exit()

# device find, now open it and claim

interface = device.open()
interface.reset()
interface.detachKernelDriver(0)
interface.detachKernelDriver(1)
interface.setConfiguration(conf)
interface.claimInterface(intf)

bufferA = (0x55, 0x53, 0x42, 0x43, 0, 8, 1, 0)
bufferB = 0x08
while (True):
time.sleep(0.2)
interface.controlMsg(0x21, 0x09, bufferA, value=0x200, index=0x001)
result = interface.controlMsg(0xa1, 0x01, bufferB, value=0x300, index=0)
if result[0] == 0x1:
os.spawnvp(os.P_WAIT,"/usr/bin/mplayer",["", FILE])

And, finally, the last glitch I ran into was that the printer was only printing on the bottom 1/8th of the page. I change the print command in take.sh to force the media size:

lp -o media=Custom.4x6in print.ps

Other than that, everything works just the same way it did last time. Next up: booth construction!

Monday, July 20, 2009

You're Building a What?

A couple of months ago, my sister decided she wanted a photo booth at her wedding reception. She looked in to renting one, but decided it was prohibitively expensive. So, what's a bride to do? Call her tech-savvy sister of course!

I happily accepted the challenge, as it was right up my alley. After doing some research online (she was not the first person to have this idea, after all), I decided on a course of action.

Following is a description of the build:

Hardware:
Thinkpad T30 (courtesy of Dad)
Powershot A20 (my first digital camera)
A20 Power Supply ($13 on eBay)
Generic Webcam (a ViewQuest VQ110 -- something I picked up years ago and never use)
USB Panic Button ($9.50 on eBay)
Photosmart 325 Compact Photo Printer ($20 from Craigslist)
Generic USB hub
USB extension cable
LCD monitor
the actual booth and some furniture (thanks to my parents)

Notes on the printer: HP printers have excellent Linux support, and I basically just bought the cheapest photo printer I could find that could use the 100 cartridge (for best quality B&W photo printing)

Software:
Ubuntu 9.10
gphoto2 - for remote controlling the camera
Cheese - web cam video display
Panic Button Script - listens to the button and fires something off when it's pushed
Imagemagick - image processing
flickr_upload - Perl module to, you guessed it, upload to Flickr
Bash script to do everything

I made some modifications to the panic button script. Here's my version:

use Device::USB::PanicButton;

printf( "*******************\n" );
printf( "Push the button to\n" );
printf( "start taking photos\n" );
printf( "*******************\n" );

my $pbutton = Device::USB::PanicButton->new();
my $count = 0;


if(!$pbutton || $pbutton->error()) {
printf(STDERR "FATAL: ". $pbutton->error() ."\n");
exit(-1);
}

while(1) {
my $result = $pbutton->pressed();

if($result == 1) {
system( "/home/t30user/Photobooth/take.sh" ); # take the picture
} elsif($result <>error() ."\n"); # uh-oh!
} elsif($count % 60 == 0) {
$count = 0;
system("gphoto2 -n > /dev/null 2>&1"); # keep the camera alive
}
$count++;
sleep(1);
}


And here's take.sh:

#!/bin/bash

# Time stamped directory
stamp=`date '+%Y%m%d%H%M%S'`
cd working

echo
echo "*******************"
echo "* Taking photos *"
echo "*******************"
echo


# Take pictures
gphoto2 --capture-image -F 4 -I 2 --quiet > /dev/null 2>&1

echo "*******************"
echo "* Creating strip *"
echo "*******************"
echo

# Put them in a strip
img_list=" "
for i in $(ls ./*JPG)
do
img=`basename $i`
cp $img ../photos/$img
chmod 777 ../photos/$img
img_list="$img_list $img "
mogrify -colorspace Gray -resize 640x480 $img
done


montage $img_list -tile 1x4 -geometry +20+12 ../strips/$stamp.jpg
montage ../strips/$stamp.jpg ../strips/$stamp.jpg -tile 2x1 -geometry +0+12 -resize 600x1788 -density 300 ../print.ps
chmod 777 ../print.ps
cp ../print.ps ../prints/$stamp.ps

rm $img_list
cd ..

echo "*******************"
echo "* Printing strip *"
echo "*******************"
echo

lp print.ps

echo "*******************"
echo "* Uploading strip *"
echo "*******************"
echo

flickr_upload strips/$stamp.jpg

clear
echo "*******************"
echo "* Push the button *"
echo "* to start taking *"
echo "* photos! *"
echo "*******************"
echo
To start the photobooth, I ran
sudo perl panicbutton.pl
in the terminal -- all the user had to do then was push the button.

I stacked the webcam on top of the digicam (and held it in place with some rubber bands) and tried to make them point at roughly the same place. The monitor went inside the photo booth (while the laptop and printer stayed outside). I stretched the desktop across the two displays, and had Cheese in fullscreen mode on the monitor.

The photo booth prints out two copies of the strip side by side on 4x6 photo paper. This way, we had one copy for the photo album, and the guests could take a copy home with them as well.

Sorry - I have no screenshots or photos. However, I do have tenative plans to rebuild the booth (my dad wasn't giving up the laptop permanently, and the furniture pieces we were using were scrounged from around my parents' house), so I'll see if I can write this up properly then.