Saturday, November 17, 2012

Raspberry Pi HDR Machine

Intro


It has been a very long time since I've posted on this blog, but I hope to make up for it with a whopper of a post.

I have always liked a little bit of HDR to add some pop and dazzle to photos, tuning a somewhat average photo, into something noteworthy. I have however found, that some times the scene requires more than the 3 bracketed shot I can take with my Canon 600D. What to do?

Recently I got my hands on a Raspberry Pi - a small little ARM computer that runs Linux on 512MB RAM. It only consumes about 430mA at 5V under normal loads, which means you can run it off a USB port or any mobile phone charger that outputs 5V.

Initially my Raspberry Pi was to replace my webserver PC which blew a motherboard, but I soon realised this small device will be perfect as a mobile camera controlling device. I can run it off a portable battery pack and control it through a SSH session from my mobile phone.

For sample photos I have taken through my Raspberry Pi, please refer to my Flickr group called Rasperry Pi HDR.

Because it runs Linux, there are a lot in terms of photography pre-packed and functional in Linux. The focus of my efforts to date have been to create two scripts:
  1. Use the Pi to take bracketed photos that extends the 3 shot limit imposed by my Canon 600D.
  2. Use the Pi to control my Canon to take photos to make a time lapse video with. This part will be sensitive to increasing or decreasing light conditions making it possible to capture sunrise or sunset scenes at the correct exposure throughout the sequence.
So, to date I have developed two scripts, one to take >3 bracketed photos for HDR purposes, and the other to take a time lapse photo set. Below a short summary of each script:

TakeHDR

My takehdr BASH script uses gphoto to communicate with, and control my Canon 600D. The sample script later on, is hard coded for my Canon 600D and a 7 shot +-1EV bracketed set of photos. Some simple editing will make this script suit your camera make and model.

This script will alter EV values automatically and the resulting images will remain on your camera. The script can optionally perform some basic HDR post processing by specifying additional command arguments. Please refer to the script for more details.

TakeTimeLapse

This is another BASH script that will take a sequence of photos for a specified duration for the purpose of generating a time lapse video. It can optionally compile the time lapse video at the end of the photo sequence. Please keep in mind that the full image sequence will be downloaded to your Pi, so your Pi's SD card must have enough capacity for both the full set of video source photos, and also the resulting video. Video output will be both AVI and FLV. An option will be to connect an external HDD to the Pi to store these files.

What you need - Hardware

  • You need to get yourself the B model of the Raspberry Pi. The price is about NZD48.00. Also get one of those nice snap together cases for the Pi.
  • A SD card of at least 4GB in size. If you want to perform photo processing on the Pi to view HDR or time lapse videos on the go, get a 16GB SD card.
  • You need an Android phone or tablet, or a touch screen phone that supports USB tethering and can run some form of SSH.
  • A battery pack. I use the Yoobao Power Bank which gives me 11200mAh that will power the Pi for about 16-24 hours. I can also use it to charge my phone or tablet when I am out and about. I got mine from TradeMe. But there are many other similar devices available. Key is to make sure you get one that can deliver at least 700mA at 5V. The Yoobao has two USB ports, one for 1A at 5V and the other at 2.1A at 5V.
  • Get one Mini USB cable and one Micro USB cable. The Mini USB will be to connect the Pi to your Camera (check you specific model's requirements) and the Micro USB will be to connect the Pi to your phone.

What you need - Software

  • Win32DiskImager to get the Raspberry Pi boot image onto the SD and in the future to back up your SD card to hard disk. Get the binary ZIP and extract to your PC.
  • Get the latest version of Raspbian which is a Debian distro specific for the Pi's ARM processor and RAM. Simplified installation instructions can be found at the video below.

  • Once your Raspberry Pi can boot from the SD card, enable SSH and VNC using the steps in the following link.
  • Also install the following packages using:
sudo apt-get update
sudo apt-get install gphoto2 imagemagick ffmpeg ufraw dcraw enfuse mencoder

  • To enable USB tethering edit your interfaces file and add the following code at the end:
sudo nano /etc/network/interfaces

iface usb0 inet static
address 192.168.42.42
netmask 255.255.255.0
network 192.168.42.0
broadcast 192.168.42.255


What you need - Scripts

The heart of the HDR and time lapse solution consists of two shell scripts I have written. Copy the code below to your Pi. You should save it to a bin folder. The steps are:

  • Logged in as the "pi" user, run:
mkdir ~/bin
cd ~/bin

  • You should now have a bin directory called /home/pi/bin, create the following two scripts by cutting and pasting the following code into two files called takehdr and taketimelapse:

takehdr

#!/bin/bash
#===============================================================================
#
#          FILE:  takehdr
#
#         USAGE:  ./takehdr --aperture <value> --processhdr --outtype <tiff|jpeg>
#                           --outsize <width x height> --cr2path <path>
#                           --tiffpath <path> --hdrpath <path> --jpgpath <path>
#
#   DESCRIPTION:  Script to take 7 bracketed photos using AV and a specified
#                 AV value
#
#       OPTIONS:  --aperture <value> --processhdr --outtype <tiff|jpeg>
#                 --outsize <width x height> --cr2path <path>
#                 --tiffpath <path> --hdrpath <path> --jpgpath <path>
#  REQUIREMENTS:
#          BUGS:  ---
#         NOTES:  ---
#        AUTHOR:  Andre Serfontein
#       COMPANY:
#       VERSION:  1.0.0
#       CREATED:  07/11/2012
#      REVISION:
#===============================================================================


#===============================================================================
# Set defaults
#===============================================================================
usage="Script to take 7 bracketed photos using AV mode

usage: $0 --aperture <value> --processhdr --outtype <tiff|jpeg>
          --outsize <width x height> --cr2path <path>
          --tiffpath <path> --hdrpath <path> --jpgpath <path>

where:
aperture   = Mandatory, AV value to set camera to.
processhdr = Optional, converts bracketed shots to single HDR image. Output
             will be --outtype.
outtype    = Optional, output file type jpeg or tiff. TIFF files are larger but
             lossless. Default jpeg.
outsize    = Optional, output file size. Photo resizing will be limited to the
             largest side as the width and height indicate maximum values.
             Default is input file size. Example 1920x1080.
cr2path    = Optional, path to save CR2 files to.
tiffpath   = Optional, path to save TIFF files to.
hdrpath    = Optional, path to save HDR TIFF files to.
jpgpath    = Optional, path to save HDR JPG files to.
"

HASEOS=`lsusb | grep "EOS 600D" | wc -l | awk '{print $1}'`
APERTURE=8
PROCESSHDR=0
OUTTYPE="jpeg"
OUTSIZE=""
CR2PATH="$HOME/images/cr2"
TIFFPATH="$HOME/images/tiff"
HDRPATH="$HOME/images/hdr"
JPGPATH="$HOME/images/jpeg"


#===============================================================================
# Parse arguments
#===============================================================================
if [ $# -eq 0 ] ; then
   echo >&2 "$usage"
   exit 1;
fi

while [ $# -gt 0 ]
do
    case "$1" in
        --aperture) APERTURE="$2"; shift;;
        --processhdr) PROCESSHDR=1;;
        --outtype) OUTTYPE="$2"; shift;;
        --outsize) OUTSIZE="$2"; shift;;
        --cr2path) CR2PATH="$2"; shift;;
        --tiffpath) TIFFPATH="$2"; shift;;
        --hdrpath) HDRPATH="$2"; shift;;
        --jpgpath) JPGPATH="$2"; shift;;
        -*) echo >&2 "$usage"
            exit 1;;
        *)  break;;     # terminate while loop
    esac
    shift
done

echo "Capturing 7 bracketed images and processing with:"
echo "APERTURE:   $APERTURE"
echo "PROCESSHDR: $PROCESSHDR"
echo "OUTTYPE:    $OUTTYPE"
echo "OUTSIZE:    $OUTSIZE"
echo "CR2PATH:    $CR2PATH"
echo "TIFFPATH:   $TIFFPATH"
echo "HDRPATH:    $HDRPATH"
echo "JPGPATH:    $JPGPATH"


#===============================================================================
# Validate environment
#===============================================================================
if [ -z "$HASEOS" ] || [ $HASEOS -ne 1 ] ; then
  echo "EOS camera not detected, exiting"
  exit 1
fi

if [ -z "$APERTURE" ] ; then
  echo "Aperture not specified, exiting"
  exit 1
fi

if [ ! -z "$OUTTYPE" ] ; then
  if [ "$OUTTYPE" != "tiff" ] && [ "$OUTTYPE" != "jpeg" ] ; then
    echo "Invalid HDR output type, exiting"
    exit 1
  fi
fi


#===============================================================================
# Perform HDR capture
#===============================================================================
rm $CR2PATH/*
rm $JPGPATH/*
rm $TIFFPATH/*

RESETEOS=`lsusb | grep "EOS 600D" | sed 's/://g' | awk '{print "~/bin/usbreset /dev/bus/usb/" $2 "/" $4}'`
eval "$RESETEOS"

CURRMODE=`gphoto2 --get-config /main/capturesettings/autoexposuremode | grep Current | awk '{print $2}'`
eval "$RESETEOS"

if [ "$CURRMODE" != "AV" ] ; then
  echo "Please set camera to AV mode, exiting"
  exit 1
fi

#Set capture to camera SD and take 7 bracket shots
gphoto2 --set-config /main/settings/capturetarget=1 \
        --set-config-index /main/imgsettings/imageformat=9 \
        --set-config-value /main/capturesettings/aperture=$APERTURE \
        --set-config-value /main/capturesettings/exposurecompensation=-3 \
        --capture-image \
        --set-config-value /main/capturesettings/exposurecompensation=-2 \
        --capture-image \
        --set-config-value /main/capturesettings/exposurecompensation=-1.0 \
        --capture-image \
        --set-config-value /main/capturesettings/exposurecompensation=0 \
        --capture-image \
        --set-config-value /main/capturesettings/exposurecompensation=1.0 \
        --capture-image \
        --set-config-value /main/capturesettings/exposurecompensation=2 \
        --capture-image \
        --set-config-value /main/capturesettings/exposurecompensation=3 \
        --capture-image

# Reset camera
eval "$RESETEOS"
gphoto2 --set-config-value /main/capturesettings/exposurecompensation=0

#===============================================================================
# Perform optional HDR processing
#===============================================================================
if [ $PROCESSHDR -eq 1 ] ; then
  eval "$RESETEOS"
  FIRSTCR2TMP=`gphoto2 --list-files | grep "CR2" | tail -7 | sed 's/#//g'`
  FIRSTCR2NUM=`echo "$FIRSTCR2TMP" | awk '{print $1}'`
  FIRSTCR2FILE=`echo "$FIRSTCR2TMP" | awk '{print $2}'`

  eval "$RESETEOS"
  LASTCR2TMP=`gphoto2 --list-files | grep "CR2" | tail -1 | sed 's/#//g'`
  LASTCR2NUM=`echo "$LASTCR2TMP" | awk '{print $1}'`
  LASTCR2FILE=`echo "$LASTCR2TMP" | awk '{print $2}'`

  cd $CR2PATH

  eval "$RESETEOS"
  gphoto2 --get-file ${FIRSTCR2NUM}-${LASTCR2NUM}

  if [ "$OUTTYPE" == "jpeg" ] ; then
    UFRAWSETTINGS="--compression=96"
    OUTPATH=$JPGPATH
    ENFUSEFIL="IMG*.jpg"
  else
    UFRAWSETTINGS="--out-depth=16"
    OUTPATH=$TIFFPATH
    ENFUSEFIL="IMG*.tif"
  fi

  if [ ! -z "$OUTSIZE" ] ; then
    ENFUSESIZE="--size $OUTSIZE"
  else
    ENFUSESIZE=""
  fi

  FIRSTFILE=`ls -al $CR2PATH | grep CR2 | head -1 | awk '{print $9}' | sed 's/.CR2//g'`
  LASTFILE=`ls -al $CR2PATH | grep CR2 | tail -1 | awk '{print $9}' | sed 's/.CR2//g'`

  if [ "$OUTTYPE" == "jpeg" ] ; then
    ufraw-batch --wb=camera --rotate=camera --out-type="jpg" $UFRAWSETTINGS $ENFUSESIZE --out-path=$JPGPATH $CR2PATH/*.CR2
    align_image_stack -a AIS_ $JPGPATH/*.jpg
    rename 's/AIS/IMG/g' $JPGPATH/A*jpg
    enfuse -o $HDRPATH/${FIRSTFILE}_to_${LASTFILE}.jpg $JPGPATH/IMG*.jpg
  else
    ufraw-batch --wb=camera --rotate=camera --out-type="tiff" $UFRAWSETTINGS $ENFUSESIZE --out-path=$TIFFPATH $CR2PATH/*.CR2
    align_image_stack -a AIS_ $TIFFPATH/*.tif
    rename 's/AIS/IMG/g' $TIFFPATH/A*tif
    enfuse -o $HDRPATH/${FIRSTFILE}_to_${LASTFILE}.tif $TIFFPATH/IMG*.tif
  fi
fi

exit 0


taketimelapse

#!/bin/bash
#===============================================================================
#
#          FILE:  taketimelapse
#
#         USAGE:  ./taketimelapse --aperture <value> --startshutterspeed <value>
#                           --endshutterspeed <value> --videoduration <seconds>
#                           --timelapseduration <minutes> --processvideo
#                           --videopath <path> --jpgpath <path> --fps <video fps>
#                           --scale <video scale>
#
#   DESCRIPTION:  Script to take timelapse photo sequence and optionally convert
#                 to AVI video. Timelapse sequence can vary shutterspeed to match
#                 increasing or decreasing light conditions.
#
#       OPTIONS:  --aperture <value> --startshutterspeed <value>
#                           --endshutterspeed <value> --videoduration <seconds>
#                           --timelapseduration <minutes> --processvideo
#                           --videopath <path> --jpgpath <path> --fps <video fps>
#                           --scale <video scale>
#
#  REQUIREMENTS:
#          BUGS:  ---
#         NOTES:  ---
#        AUTHOR:  Andre Serfontein
#       COMPANY:
#       VERSION:  1.0.0
#       CREATED:  07/11/2012
#      REVISION:
#===============================================================================


#===============================================================================
# Set defaults
#===============================================================================
usage="Script to take timelapse photo sequence and optionally convert
to AVI video. Timelapse sequence can vary shutterspeed to match
increasing or decreasing light conditions.

usage: $0 --aperture <value> --startshutterspeed <value>
          --endshutterspeed <value> --videoduration <seconds>
          --timelapseduration <minutes> --processvideo
          --videopath <path> --jpgpath <path> --fps <video fps>
          --scale <video scale>

where:
aperture          = Mandatory, AV value to set camera to.
startshutterspeed = Mandatory, shutterspeed to initiate photo sequence with. Use
                    actual camera values ie. "1/30" etc
endshutterspeed   = Mandatory, shutterspeed to end photo sequence with. Can be
                    same as start shutterspeed. If different, then the shutter-
                    speed will be gradually increased or decreased as the photo
                    sequence progresses. Use actual camera values ie. "1/30" etc
videoduration     = Mandatory, duration in SECONDS of required video.
timelapseduration = Mandatory, duration in MINUTES of required time lapse sequence.
processvideo      = Optional, converts timelapse shots to single AVI video at 24fps.
videopath         = Optional, path to save AVI file to. Recommended to use external
                    USB HDD as this will generate large IO on SD card.
jpgpath           = Optional, path to save timelapse JPG files to. Recommended to
                    use external USB HDD as this will generate large IO on SD card.
fps               = Optional, if the time lapse video must be compiled, specify the
                    desired frames per second the video should be compiled with. 24fps
                    gives best result but will require 24 photos per second of video.
                    Default 24.
scale             = Optional, video scale. The Pi may not have the capacity to generate
                    high resolution videos. For high definition use 1920:1080.
                    Default 640:400.
"

HASEOS=`lsusb | grep "EOS 600D" | wc -l | awk '{print $1}'`
APERTURE=8
STARTSHUTTERSPEED="1/200"
ENDSHUTTERSPEED="1/200"
VIDEODURATION=30
TIMELAPSEDURATION=120
PROCESSVIDEO=0
VIDEOPATH=""
JPGPATH=""
FPS=24
SCALE="640:400"
CAPTUREDELAY=5


#===============================================================================
# Parse arguments
#===============================================================================
if [ $# -eq 0 ] ; then
   echo >&2 "$usage"
   exit 1;
fi

while [ $# -gt 0 ]
do
    case "$1" in
        --aperture) APERTURE="$2"; shift;;
        --startshutterspeed) STARTSHUTTERSPEED="$2"; shift;;
        --endshutterspeed) ENDSHUTTERSPEED="$2"; shift;;
        --videoduration) VIDEODURATION="$2"; shift;;
        --timelapseduration) TIMELAPSEDURATION="$2"; shift;;
        --processvideo) PROCESSVIDEO=1;;
        --videopath) VIDEOPATH="$2"; shift;;
        --jpgpath) JPGPATH="$2"; shift;;
        --fps) FPS="$2"; shift;;
        --scale) SCALE="$2"; shift;;
        -*) echo >&2 "$usage"
            exit 1;;
        *)  break;;     # terminate while loop
    esac
    shift
done

echo "Capturing JPG images for $TIMELAPSEDURATION minutes:"
echo "APERTURE:          $APERTURE"
echo "STARTSHUTTERSPEED: $STARTSHUTTERSPEED"
echo "ENDSHUTTERSPEED:   $ENDSHUTTERSPEED"
echo "VIDEODURATION:     $VIDEODURATION"
echo "TIMELAPSEDURATION: $TIMELAPSEDURATION"
echo "PROCESSVIDEO:      $PROCESSVIDEO"
echo "VIDEOPATH:         $VIDEOPATH"
echo "JPGPATH:           $JPGPATH"


#===============================================================================
# Validate environment
#===============================================================================
if [ -z "$HASEOS" ] || [ $HASEOS -ne 1 ] ; then
  echo "EOS camera not detected, exiting"
  exit 1
fi


#===============================================================================
# Capture time lapse shots
#===============================================================================
if [ ! -z "$JPGPATH" ] ; then
  rm $JPGPATH/*
fi

RESETEOS=`lsusb | grep "EOS 600D" | sed 's/://g' | awk '{print "~/bin/usbreset /dev/bus/usb/" $2 "/" $4}'`

eval "$RESETEOS"
CURRMODE=`gphoto2 --get-config /main/capturesettings/autoexposuremode | grep Current | awk '{print $2}'`

if [ "$CURRMODE" != "Manual" ] ; then
  echo "Please set camera to Manual mode, exiting"
  exit 1
fi

eval "$RESETEOS"
STARTSSINDEX=`gphoto2 --get-config /main/capturesettings/shutterspeed | grep "Choice" | sed 's/Choice: //g' | awk -v shutter="$STARTSHUTTERSPEED" '{if ($2 == shutter) {print $1}}'`

eval "$RESETEOS"
ENDSSINDEX=`gphoto2 --get-config /main/capturesettings/shutterspeed | grep "Choice" | sed 's/Choice: //g' | awk -v shutter="$ENDSHUTTERSPEED" '{if ($2 == shutter) {print $1}}'`

eval "$RESETEOS"
SSFIRSTINDEX=1
SSLASTINDEX=`gphoto2 --get-config /main/capturesettings/shutterspeed | grep "Choice" | sed 's/Choice: //g' | tail -1 | awk '{print $1}'`

if [ -z "$STARTSSINDEX" ] ; then
  echo "Cannot locate start shutterspeed in valid supported shutterspeed options."
  exit 1
fi

if [ -z "$ENDSSINDEX" ] ; then
  echo "Cannot locate end shutterspeed in valid supported shutterspeed options."
  exit 1
fi

# Calculate number of shutterspeed increments to make during timelapse photography
# If starting and ending shutterspeed values are the same, steps will be 1
if [ $STARTSSINDEX -ne $ENDSSINDEX ] ; then
  if [ $STARTSSINDEX -gt $ENDSSINDEX ] ; then
    SSSTEPS=$(( STARTSSINDEX - ENDSSINDEX + 1 ))
  else
    SSSTEPS=$(( ENDSSINDEX - STARTSSINDEX + 1 ))
  fi
else
  SSSTEPS=1
fi

# Calculate number of frames required to generate video
TOTFRAMES=$(( VIDEODURATION * 24 ))

# Calculate tripping point to move to next shutter speed
TRIPTMP=`echo "$TOTFRAMES / $SSSTEPS" | bc -l`
TRIPPOINT=`echo "scale=0; ($TRIPTMP + 0.5) / 1" | bc`

# Calculate number of images to take per minute. Arithmetic too complex
# for bash, so using bc so not to loose decimal place
IMGPERMINUTE=`echo "scale=1; 60 / (($TIMELAPSEDURATION * 60) / $TOTFRAMES)" | bc -l`

# Calculate sleep duration between shots taken into account 5s delay in
# taking each shot.
SLEEPDURATION=`echo "scale=0; (60 - ($CAPTUREDELAY * $IMGPERMINUTE)) / $IMGPERMINUTE" | bc -l`

echo "Calculated timelapse settings are:"
echo "STARTSSINDEX:     $STARTSSINDEX"
echo "ENDSSINDEX:       $ENDSSINDEX"
echo "SSSTEPS:          $SSSTEPS"
echo "TOTFRAMES:        $TOTFRAMES"
echo "TRIPPOINT:        $TRIPPOINT"
echo "IMGPERMINUTE:     $IMGPERMINUTE"
echo "SLEEPDURATION:    $SLEEPDURATION"

# Set capture to camera SD and exposure mode to Manual and file format to Medium Fine JPG.
# CR2 capture is too slow and images way too large for video use.
eval "$RESETEOS"
gphoto2 --set-config /main/settings/capturetarget=1 \
        --set-config-index /main/imgsettings/imageformat=2 \
        --set-config-value /main/capturesettings/autoexposuremode=Manual \
        --set-config-value /main/capturesettings/aperture=$APERTURE \
        --set-config-index /main/capturesettings/shutterspeed=$STARTSSINDEX

CURRSSINDEX=$STARTSSINDEX

for (( i=1; i <= $TOTFRAMES; i++ ))
do
  echo "Capturing"
  eval "$RESETEOS"
  gphoto2 --capture-image

  ISTRIPPOINT=$(( i % TRIPPOINT ))

  if [ $STARTSSINDEX -ne $ENDSSINDEX ] && [ $ISTRIPPOINT -eq 0 ] ; then
    eval "$RESETEOS"

    if [ $STARTSSINDEX -gt $ENDSSINDEX ] ; then
      CURRSSINDEX=$(( CURRSSINDEX - 1 ))
      echo "Decreasing shutter speed to $CURRSSINDEX"
      gphoto2 --set-config-index /main/capturesettings/shutterspeed=$CURRSSINDEX
    else
      CURRSSINDEX=$(( CURRSSINDEX + 1 ))
      echo "Increasing shutter speed to $CURRSSINDEX"
      gphoto2 --set-config-index /main/capturesettings/shutterspeed=$CURRSSINDEX
    fi
  fi

  echo "Sleeping for $SLEEPDURATION"
  sleep $SLEEPDURATION
done

#===============================================================================
# Compose video
#===============================================================================
if [ $PROCESSVIDEO -eq 1 ] ; then
  eval "$RESETEOS"
  FIRSTJPGTMP=`gphoto2 --list-files | grep "JPG" | head -1 | sed 's/#//g'`
  FIRSTJPGNUM=`echo "$FIRSTJPGTMP" | awk '{print $1}'`
  FIRSTJPGFILE=`echo "$FIRSTJPGTMP" | awk '{print $2}'`

  eval "$RESETEOS"
  LASTJPGTMP=`gphoto2 --list-files | grep "JPG" | tail -1 | sed 's/#//g'`
  LASTJPGNUM=`echo "$LASTJPGTMP" | awk '{print $1}'`
  LASTJPGFILE=`echo "$LASTJPGTMP" | awk '{print $2}'`

  cd $JPGPATH

  eval "$RESETEOS"
  gphoto2 --get-file ${FIRSTJPGNUM}-${LASTJPGNUM}

  enfuse -o $HDRPATH/${FIRSTFILE}_to_${LASTFILE}.${OUTTYPE} $OUTPATH/$ENFUSEFIL
  mencoder $JPGPATH/*JPG -mf fps=$FPS:type=jpg -ovc lavc -lavcopts vcodec=mpeg4:mbd=2:trell:vbitrate=7000 -vf scale=$SCALE -oac copy -o $VIDEOPATH/movie.avi
  ffmpeg -i $VIDEOPATH/movie.avi -s qvga $VIDEOPATH/movie.flv
fi

exit 0


  • You will also need to compile a small C program to reset the Pi's USB port following each gphoto call to address a little hardware issue. Save the following to usbreset.c:
/* usbreset -- send a USB port reset to a USB device */

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>

#include <linux/usbdevice_fs.h>


int main(int argc, char **argv)
{
    const char *filename;
    int fd;
    int rc;

    if (argc != 2) {
        fprintf(stderr, "Usage: usbreset device-filename\n");
        return 1;
    }
    filename = argv[1];

    fd = open(filename, O_WRONLY);
    if (fd < 0) {
        perror("Error opening output file");
        return 1;
    }

    printf("Resetting USB device %s\n", filename);
    rc = ioctl(fd, USBDEVFS_RESET, 0);
    if (rc < 0) {
        perror("Error in ioctl");
        return 1;
    }
    printf("Reset successful\n");

    close(fd);
    return 0;
}

  • Compile using:
gcc -o usbreset usbreset.c

  • Make sure the two scripts and usbreset are executable using:
chmod u+x usbreset
chmod u+x take*

How to take HDR photos

  • Connect your portable battery to your Pi, and wait for a minute so the Pi can finish booting.
  • Connect your Pi to you camera using a USB cable (Mini USB for Canon).
  • Connect your mobile phone to your Pi using a USB cable (Micro USB for my Samsung Galaxy S2).
  • Set your camera to A or Av.
  • Pick an ISO speed of 100 to 400. You can go higher but you do not want to start off too noisy since the HDR processing itself will introduce a lot of noise/amplify noise.
  • Disable any previous set exposure compensation etc. on your camera.
  • Enable Manual focus and make sure you compose and focus the picture you would like to take.
  • You have to shoot using a tripod so make sure to disable image stabilization on your lens.
  • Connect to the Pi by enabling a USB tethered connection through your phone.
  • Then open a SSH session to 192.168.42.42 port 22. Enter pi as the user and "raspberry" as your password if you have not yet changed that.
  • Once logged in you will get to the command prompt. Take a bracketed photo sequence using:
~/bin/takehdr --aperture 8

Comment: I choose an aperture of 8 since my lens performs best at that value.

  • Note, the script will wait for each image to be saved to the camera's SD before the next shot will be taken.
  • To take another set of bracketed photos, simply hit up arrow on your phone to get the previous command and hit return to run. Make sure your composition and focus is set each time.

How to take time lapse photos

  • Connect your portable battery to your Pi, and wait for a minute so the Pi can finish booting.
  • Connect your Pi to you camera using a USB cable (Mini USB for Canon).
  • Connect your mobile phone to your Pi using a USB cable (Micro USB for my Samsung Galaxy S2).
  • Set your camera to M or Manual.
  • Set you camera's image output to medium fine JPG. RAW is overkill for the purpose and will take too much file space.
  • Pick an ISO speed of 100 to 1600. Try to have a starting shutter speed that will allow for alteration by the script as the video sequence progress.
  • You will need to predetermine the starting shutter speed and ending shutter speed required to ensure correct exposure for the ISO and F-stop values you plan to shoot at.
  • Disable any previous set exposure compensation etc. on your camera.
  • Enable Manual focus and make sure you compose and focus the picture you would like to take.
  • You have to shoot using a tripod so make sure to disable image stabilization on your lens as this tends to introduce blur when static.
  • Connect to the Pi by enabling a USB tethered connection through your phone.
  • Then open a SSH session to 192.168.42.42 port 22. Enter pi as the user and "raspberry" as your password if you have not yet changed that.
  • Once logged in you will get to the command prompt. Take the time lapse photo sequence using:
~/bin/taketimelapse --aperture 8 --startshutterspeed "1/30" --endshutterspeed "1/4" --videoduration 30 --timelapseduration 120

Comment: This example will shoot a sunset sequence until dark, for 2 hours (120 minutes) at F8 starting at a shutter speed of "1/30" and ending at "1/4" all at ISO 100. The desired video duration is 30 seconds. The script will calculate the required shots and frequency of shots and will alter the shutter speed during the sequence to correct exposure as the light conditions change.

  • Note, the script will wait for each image to be saved to the camera's SD before the next shot will be taken.
To aid you in calculating the camera settings for your time lapse sequence, I have found the chart at http://www.fredparker.com/ultexp1.htm#EXPOSURE%20FACTOR%20RELATIONSHIP%20CHART%20B an invaluable resource.



Friday, May 11, 2012

Photoshop Statue

In this tutorial, I will show you how to change a plain and flat image into one with a bit more "pop". I will be using Adobe Photoshop CS6 Beta, but you can use an older version of Photoshop or even Elements. Make sure you have a RAW copy of your photo.

Our starting photo is this:


A bit flat with no real highlights and a lot of shadows. I could have fixed this using HDR, but let me show you how you can get amazing results just using Camera Raw and Photoshop.

Step 1, open the image in Photoshop. If you open a RAW file, Camera Raw should open up. (click to enlarge)



Step 2, in Camera Raw, drag the Highlights slider all the way to the left, and the Shadows slider all the way to the right. My source image was a bit dark so I've increased the Whites a bit as well. Also add a fair bit of clarity and Vibrance to make up for the extremes set on the Highlights and shadows. Please note in older versions of Camera Raw these are the Fill light and Blacks sliders instead of Highlights and Shadows.

By maximizing these settings you will rescue a fair bit of lost information in the image.

Alter Exposure to get a more even spread in your histogram top right.

Step 3, before you exit Camera Raw, apply sharpening and noise reduction as required.

Step 4, click Open Copy to open the image in Photoshop once you have the image set to your liking. So at this stage your image will open in Photoshop and you will already notice that the image looks less flat compared to the original. Colors will also be more saturated and vibrant. My main subject of the image, the statue, still needed some more attention to make it stand out from the rest of the image.

So, add a Brightness/Contrast layer to your photo:



Step 5, adjust the brightness to correctly expose, or slightly overexpose the subject of the photo. Do not worry about the rest of the photo at this stage.



Step 6, click the mask on the Brightness/Contrast layer, go menu Edit|Fill... or hit Shift+F5, and fill the mask with black.



Step 7, with the layer mask still selected, click the brush tool and set a very soft brush setting (hardness).





Also set the Opacity to a small percentage, which will allow you to gradually filter through the mask the overexposure set by the Brightness/Contrast layer.



Step 8, using the [ and ] keys to increase and decrease your brush size, slowly paint in white on the black layer mask. In my photo I tried to create the impression that the statue was flash lit from below. Look at how the lighter areas in my layer mask shows where I've let the Brightness/Contrast settings come through.



Finish up with a frame and signature, flatten the image and save as ZIP compressed TIFF.

My final result: