By admin |

Laurent22 on Github has developed a very simple bash script for capturing images using a standard default webcam with motion detection support attached to your system. This bash script process was developed to assist Laurent22 to record what his dog was doing while he wasn't at home.

The daily driver used by Laurent 22 is OSX. However, the bash script that he developed for creating images that can be converted into a motion picture .mp4 file for viewing using VLC Media Player, is cross-platform and can be run in Linux and MS Windows as well.

Frames are captured at regular intervals using ffmpeg. Next, ImageMagick's compare tool is used to check if a frame is similar to its predecessor frame. If these two frames are substantively different, then they are preserved, otherwise they are discarded in order ro conserve hard drive space. This process provides a very simple motion detection methodology and avoids filling up the hard drive with duplicate frames.

Installation


OSX


brew install ffmpeg   
brew install imagemagick   
curl -O https://raw.github.com/laurent22/pmcam/master/pmcam.sh   

Linux (Debian)
sudo apt-get install ffmpeg   
# or: sudo apt-get install libav-tools   
sudo apt-get install imagemagick   
curl -O https://raw.github.com/laurent22/pmcam/master/pmcam.sh   

Windows


(Not tested)

 

- Install [Cygwin](https://www.cygwin.com/) or [MinGW](http://www.mingw.org/)   
- Install [ffmpeg](http://ffmpeg.zeranoe.com/builds/)   
- Install [ImageMagick](http://www.imagemagick.org/script/binary-releases.php)  

Usage
./pmcam.sh   
 

The contents of the pmcam.sh file is as follows:

  
#!/usr/bin/env bash

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"   
OUTPUT_DIR="$SCRIPT_DIR/images"

CAPTURE_INTERVAL="1" # in seconds   
FFMPEG=ffmpeg   
command -v $FFMPEG >/dev/null 2>&1 || { FFMPEG=avconv ; }   
DIFF_RESULT_FILE=$OUTPUT_DIR/diff_results.txt

fn_cleanup() {   
   rm -f diff.png $DIFF_RESULT_FILE   
}

fn_terminate_script() {   
   fn_cleanup   
   echo "SIGINT caught."   
   exit 0   
}   
trap 'fn_terminate_script' SIGINT

mkdir -p $OUTPUT_DIR   
PREVIOUS_FILENAME=""   
while true ; do   
   FILENAME="$OUTPUT_DIR/$(date +"%Y%m%dT%H%M%S").jpg"   
   echo "-----------------------------------------"   
   echo "Capturing $FILENAME"   
   if [[ "$OSTYPE" == "linux-gnu" ]]; then   
       $FFMPEG -loglevel fatal -f video4linux2 -i /dev/video0 -r 1 -t 0.0001 $FILENAME   
   elif [[ "$OSTYPE" == "darwin"* ]]; then   
       # Mac OSX   
       $FFMPEG -loglevel fatal -f avfoundation -i "default" -r 1 -t 0.0001 $FILENAME   
   fi   
      
   if [[ "$PREVIOUS_FILENAME" != "" ]]; then   
       # For some reason, `compare` outputs the result to stderr so   
       # it's not possibly to directly get the result. It needs to be   
       # redirected to a temp file first.   
       compare -fuzz 20% -metric ae $PREVIOUS_FILENAME $FILENAME diff.png 2> $DIFF_RESULT_FILE   
       DIFF="$(cat $DIFF_RESULT_FILE)"   
       fn_cleanup   
       if [ "$DIFF" -lt 20 ]; then   
           echo "Same as previous image: delete (Diff = $DIFF)"   
           rm -f $FILENAME   
       else   
           echo "Different image: keep (Diff = $DIFF)"   
           PREVIOUS_FILENAME="$FILENAME"   
       fi   
   else   
       PREVIOUS_FILENAME="$FILENAME"   
   fi   
      
   sleep $CAPTURE_INTERVAL   
done   
 

This script should be made executable using the command:

  
chmod +x pmcam.sh   
 

and then executed using the command:

  
./pmcam.sh   
 

This bash script will use your default webcam to capture frames. To capture using a different camera other than the default detected, the ffmpeg command `-i` parameter can be changed - see the [ffmpeg documentation](https://trac.ffmpeg.org/wiki/Capture/Webcam) for more information.

A frame will then be saved approximately once every second to the "images" folder in the same directory as the Bash script. Both delay and target folder can be changed in the script.

To stop the script, press Ctrl + C.

This bash script process is covered under the MIT license.

Concatenating Multiple Image Files to an MP4 Video Format


Once the images are captured using the bash script process delineated previously, you can easily concatenate these images into a .mp4 format that produces a raw video from those images.

To accomplish this, go into your *Images* folder, locate the individual image files, then run the concatenation command to concatenate these image files into one single .mp4 file. So, if you have the following image files in the *images* folder, the command to run in the terminal would be:

  
$ cat imageFile1 imageFile2 ... imageFileN > movie.mp4   
 

which concatenates imageFile1, imageFile2, through imageFileN into one file called movie in the .mp4 format since we used the .mp4 extension on the final file.