Raspberry Pi scene monitoring with ImageMagick

This isn't motion detection - it's a much simpler algorithm impemented in bash - better place to start with less knowlege required to understand than OpenCV based solutions.

The only prerequisites are a working RaspberryPi Camera and

apt-get install imagemagick

A lot of this uses the ram drive for the scene change detection loop, this is faster than using the SD card filesystem and prevents wear from repeated write/delete operations in the loop.

There are 3 components.

  1. Run the camera to update a file as regularly as you need to.
    raspistill -o new.jpg --nopreview --timeout 0 --exposure auto --timelapse 500 --sharpness 66
  2. Monitor the output (see inline comments)
    EpochPrevious=0                                                         # Epoch timestamp of the last update to new.jpg
    I=99                                                                    # Iterations through the main loop that have seen a new new.jpg
    RingBuf=0                                                               # current position of the original capture Ring Buffer
    cd /run/user/1000
    while [ 1 ]; do
            EpochCurrent=`stat --printf=%Y new.jpg`
            if [[ $EpochPrevious -ne $EpochCurrent ]]; then                 # only continue if there is a "new" new.jpg from raspistill
                    convert new.jpg -crop 1000x500+250+950 -resize 300x300 test.jpg
                    DTE=`date +%Y%m%d_%H%M%S.%N`                            # this is sortable and with nano time accounts for 2 images in the same second
                    let I=I+1                                               # used for a hard timeout to force update the master image
                    if [ "$I" -gt "20" ]; then
                            echo FORCE RESAVE MASTER
                            cat test.jpg > master.jpg
                    let RingBuf=RingBuf+1                                   # $RingBuf buffer pointer to recall a few seconds of history
                    if [ "$RingBuf" -gt "5" ]; then
                    let DIFFTHRESHOLD=$I*500                                # The Diff Threshold (below which the master is replaced) increases over time
                    rm $RingBuf-*                                           # Remove the previous occupant of this Ring Buffer position
                    cp new.jpg $RingBuf-$DTE.jpg                            # Add the new occupant of this of this Ring Buffer position
                    DIFF="$(compare -metric ae -fuzz 6% jpg:master.jpg jpg:test.jpg diff.jpg 2>&1 > /dev/null)"
                    if [ "$DIFF" -gt "5000" ]; then                         # If the change against the base is significant, save the ring and note the time
                            date +"%Y-%m-%d %H:%M:%S" >> /home/pi/log.txt
                            /home/pi/dumpring.sh &
                    if [ "$DIFF" -lt "$DIFFTHRESHOLD" ]; then               # If the change against the base us INSIGNIFICANT, re-base line
                            echo -n "/R/"
                            cat test.jpg > master.jpg
                    echo -n .
            sleep 0.2
  3. Once a day (or whatever your preference) deal with all the files in /home/pi/saved - add the filename (date) into the JPG images and assemble into a timelapse
    for FN in `ls 2022*.jpg`; do
    	ffmpeg -i $FN -q:v 1 -qmin 1 -qmax 1 -vf \\"crop=2592:1544:0:400, drawtext=text=$TS: fontcolor=white: fontsize=60: box=1: boxcolor=black@0.6: x=50:y=50: fontfile=/C/Windows/Fonts/tahoma.ttf\\" mod-$FN
    ffmpeg -framerate 15 -pattern_type  glob -i "mod*.jpg" ../vi
  4. Delete the days files in /home/pi/saved - this folder could grow significantly.

Scene monitoring with a Raspberry Pi (4 Model B) + camera using ImageMagick's compare to recognise passing motor vehicles with a bash script.

I still read the reg plates manually from the raw images, but I only keep the compiled timelapse for reference.