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.
- 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
- Monitor the output (see inline comments)
#!/bin/bash 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 I=0 fi let RingBuf=RingBuf+1 # $RingBuf buffer pointer to recall a few seconds of history if [ "$RingBuf" -gt "5" ]; then RingBuf=0 fi 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 & fi if [ "$DIFF" -lt "$DIFFTHRESHOLD" ]; then # If the change against the base us INSIGNIFICANT, re-base line echo -n "/R/" I=0 cat test.jpg > master.jpg fi else echo -n . fi EpochPrevious=$EpochCurrent sleep 0.2 done
- 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
#!/bin/bash for FN in `ls 2022*.jpg`; do D=${FN:0:8} H=${FN:9:2} M=${FN:11:2} S=${FN:13:2} TS="$D-$H.$M.$S" 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 done; ffmpeg -framerate 15 -pattern_type glob -i "mod*.jpg" ../vi
- Delete the days files in /home/pi/saved - this folder could grow significantly.