Here’s a quick python script to use the camera you can attach to a Raspberry Pi and take a picture whenever it detects motion. This is pretty cool, there are all sorts of silly things you can do if you can do motion detection. And to do it with the Raspberry Pi and attached camera is relatively inexpensive (less than $100) to boot! Next time someone knocks our mailbox down we’ll have ’em!
I started from the script here and modified it to just take one picture to both test whether anything changed as well as save the picture if something changed. Seems a bit better than the original taking two pictures – at least this doesn’t cause the Pi to freeze. That means the Pi have to scan a bit larger image for a change but skipping pixels seems to keep it under control. It also takes better pictures as takes some time (the -t 500 in the raspistill call) to calibrate the camera.
#!/usr/bin/env python import StringIO import subprocess import os import time from datetime import datetime from PIL import Image # Motion detection settings: # Threshold (how much a pixel has to change by to be marked as "changed") # Sensitivity (how many changed pixels before capturing an image) # ForceCapture (whether to force an image to be captured every forceCaptureTime seconds) threshold = 10 sensitivity = 2000 forceCapture = True forceCaptureTime = 60 * 60 # Once an hour # File settings saveWidth = 1280 saveHeight = 960 diskSpaceToReserve = 500 * 1024 * 1024 # Keep 500 mb free on disk # Capture a small test image (for motion detection) def captureTestImage(): command = "raspistill -w %s -h %s -t 500 -e bmp -o -" % (1280, 960) imageData = StringIO.StringIO() imageData.write(subprocess.check_output(command, shell=True)) imageData.seek(0) im = Image.open(imageData) buffer = im.load() imageData.close() return im, buffer # Keep free space above given level def keepDiskSpaceFree(bytesToReserve): if (getFreeSpace() < bytesToReserve): for filename in sorted(os.listdir(".")): if filename.startswith("capture") and filename.endswith(".jpg"): os.remove(filename) print "Deleted %s to avoid filling disk" % filename if (getFreeSpace() > bytesToReserve): return # Get available disk space def getFreeSpace(): st = os.statvfs(".") du = st.f_bavail * st.f_frsize return du # Get first image image1, buffer1 = captureTestImage() # Reset last capture time lastCapture = time.time() while (True): # Get comparison image image2, buffer2 = captureTestImage() # Count changed pixels changedPixels = 0 for x in xrange(0, 1280, 4): for y in xrange(0, 960, 4): # Just check green channel as it's the highest quality channel pixdiff = abs(buffer1[x,y][1] - buffer2[x,y][1]) if pixdiff > threshold: changedPixels += 1 # Check force capture if forceCapture: if time.time() - lastCapture > forceCaptureTime: changedPixels = sensitivity + 1 # Save an image if pixels changed if changedPixels > sensitivity: lastCapture = time.time() timeN = datetime.now() print "Save jpg" filename = "capture-%04d%02d%02d-%02d%02d%02d.jpg" % (timeN.year, timeN.month, timeN.day, timeN.hour, timeN.minute, timeN.second) image2.save(filename, "JPEG") keepDiskSpaceFree(bytesToReserve) # Swap comparison buffers image1 = image2 buffer1 = buffer2 time.sleep(2) print "Done waiting"