Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A simple example of using the Raspberry Pi Camera Module and python picamera for motion detection
#!/usr/bin/python
import picamera
import cv2
import io
import numpy as np
import imutils
camera = picamera.PiCamera()
# Motion detection sensitivity
min_area = 100
def handle_new_frame(frame, past_frame, min_area):
(h, w) = frame.shape[:2]
r = 500 / float(w)
dim = (500, int(h * r))
frame = cv2.resize(frame, dim, cv2.INTER_AREA) # We resize the frame
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # We apply a black & white filter
gray = cv2.GaussianBlur(gray, (21, 21), 0) # Then we blur the picture
# if the first frame is None, initialize it because there is no frame for comparing the current one with a previous one
if past_frame is None:
past_frame = gray
return past_frame
# check if past_frame and current have the same sizes
(h_past_frame, w_past_frame) = past_frame.shape[:2]
(h_current_frame, w_current_frame) = gray.shape[:2]
if h_past_frame != h_current_frame or w_past_frame != w_current_frame: # This shouldnt occur but this is error handling
print('Past frame and current frame do not have the same sizes {0} {1} {2} {3}'.format(h_past_frame, w_past_frame, h_current_frame, w_current_frame))
return
# compute the absolute difference between the current frame and first frame
frame_detla = cv2.absdiff(past_frame, gray)
# then apply a threshold to remove camera motion and other false positives (like light changes)
thresh = cv2.threshold(frame_detla, 50, 255, cv2.THRESH_BINARY)[1]
# dilate the thresholded image to fill in holes, then find contours on thresholded image
thresh = cv2.dilate(thresh, None, iterations=2)
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if imutils.is_cv2() else cnts[1]
# loop over the contours
for c in cnts:
# if the contour is too small, ignore it
if cv2.contourArea(c) < min_area:
continue
print("Motion detected!")
if __name__ == '__main__':
camera.resolution = (640, 480)
past_frame = None
print("Starting motion detection")
try:
while True:
stream = io.BytesIO()
camera.capture(stream, format='jpeg', use_video_port=False)
data = np.fromstring(stream.getvalue(), dtype=np.uint8)
frame = cv2.imdecode(data, 1)
if frame is not None:
past_frame = handle_new_frame(frame, past_frame, min_area)
else:
print("No more frame")
finally:
print("Exiting")
@theawsomeboss1102

This comment has been minimized.

Copy link

commented May 17, 2018

I sound like a total noob but where are the captured pictured stored and how do I run this script on my raspberry pi

@Esser420

This comment has been minimized.

Copy link

commented Jun 28, 2018

@theawsomeboss1102 this script just detects motion and prints to the console if it does indeed detect something. It does not save video or pictura of motion happening.

I suggest learning python and read the PiCamera docs if you need to tinker with this script.

@bluejakester

This comment has been minimized.

Copy link

commented Jul 20, 2018

Thank you for writing and sharing this! I've been trying unsuccessfully to modify "motion" and other programs to take a night vision image with "raspistill" and my parms. With your code the motion detect is there and working, making it simple to add my specific image capture requirements.

@itsmysurport

This comment has been minimized.

Copy link

commented Dec 9, 2018

Code Error Founded

You left out double quotation marks in 42 line. print "Scanning for Motion threshold=%i sensitivity=%i... % (threshold, sensitivity)

print "Scanning for Motion threshold=%i sensitivity=%i..." % (threshold, sensitivity)

@cooc1501

This comment has been minimized.

Copy link

commented Jan 5, 2019

getting a syntax error at line 25, any idea what's causing that?

@mrcolo

This comment has been minimized.

Copy link

commented Feb 7, 2019

same syntax error, line 25..

@khalidbourhaba

This comment has been minimized.

Copy link

commented Apr 2, 2019

If you are having error on line 25, try to run the script with python 2.7..

@pabe40

This comment has been minimized.

Copy link

commented Apr 8, 2019

 Line38       data2 = data1 . Shouldn't be data1 = data2 to get a new offset and not always comparing against the initial image in data1?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.