#!/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 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.
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.
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)
getting a syntax error at line 25, any idea what's causing that?
same syntax error, line 25..
If you are having error on line 25, try to run the script with python 2.7..
Line38 data2 = data1 . Shouldn't be data1 = data2 to get a new offset and not always comparing against the initial image in data1?
I sound like a total noob but where are the captured pictured stored and how do I run this script on my raspberry pi