Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
265 lines (211 sloc) 8.47 KB
from pyimagesearch.tempimage import TempImage
#add dropbox packages later if desired
from picamera.array import PiRGBArray
from picamera import PiCamera
import argparse
import warnings
import datetime
import imutils
import json
import time
import cv2
"""class Camera(PiCamera):
#This is broken, but I'm hoping to encapsulate many of the steps of the
#execution in this class, to have a good set of autosets and to work with
#mulitple cameras and configuration files
def __init__(self, resolution, framerate):
self.resolution = resolution
self.framerate = framerate
def set_configuration_file(config):
#constructs the argument parser, parses the arguments, filters the
#warnings, and returns a loaded json file passed as an argument
ap=argparse.ArgumentParser()
ap.add_argument("-c","--conf", required=True,
help="path to the JSON configuration file")
args=vars(ap.parse_args())
warnings.filterwarnings("ignore")
return json.load(open(args[config]))
conf=set_configuration_file(config="conf")
resolution = tuple(conf["resolution"])
framerate= conf["fps"]"""
def set_configuration_file(config):
"""constructs the argument parser, parses the arguments, filters the
warnings, and returns a loaded json file passed as an argument"""
ap=argparse.ArgumentParser()
ap.add_argument("-c","--conf", required=True,
help="path to the JSON configuration file")
args=vars(ap.parse_args())
warnings.filterwarnings("ignore")
return json.load(open(args[config]))
def bootup_sequence(conf):
"""allow the camera to warmup, then initialize the average frame, last
uploaded timestamp and a frame motion counter.
WARNING: it does so by declaring global variables, so be careful.
as the name implies this is only meant to be run at the beginning of the
program"""
global avg
global lastUploaded
global motionCounter
print ("[INFO] warming up...")
time.sleep(conf["camera_warmup_time"])
avg = None
lastUploaded= datetime.datetime.now()
motionCounter= 0
motion_detect_loop()
def set_motion_detect(current_frame):
"""sets global variables for loop used for motion detect"""
global room_status
global timestamp
global frame
global gray
frame=current_frame.array
timestamp= datetime.datetime.now()
room_status="Unoccupied"
frame= imutils.resize(frame, width=500)
gray=cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray=cv2.GaussianBlur(gray, (21,21), 0)
def start_background_model():
"""creates the average background for use in motion detection"""
global avg
global rawCapture
print ("[INFO] starting background model...")
avg = gray.copy().astype("float") if avg is None else avg
rawCapture.truncate(0)
def set_delta():
"""accumulate the weighted average between the current frame and previous
frames, then compute the difference between the current frame and
running average"""
cv2.accumulateWeighted(gray, avg, 0.5)
frameDelta = cv2.absdiff(gray, cv2.convertScaleAbs(avg))
return frameDelta
def prep_frame_for_processing():
global cnts
"""threshhold the delta image, dilate the threshholded image to
fill in holes, then find countours on threshhold image"""
thresh = cv2.threshold(frameDelta, conf["delta_thresh"], 225,
cv2.THRESH_BINARY)[1]
thresh = cv2.dilate(thresh, None, iterations=2)
(_,cnts, _) = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
def check_contours(cnts):
global room_status
for contours in cnts:
#if the contour is too small ignore it
if cv2.contourArea(contours)< conf["min_area"]:
continue
#compute the bounding box for the contour, draw it on the frame,
#and update the room status
(x, y, w, h)=cv2.boundingRect(contours)
cv2.rectangle(frame, (x,y), (x+w, y+h), (0,255, 0), 2)
room_status = "Occupied"
def display_information():
"""prints various values on the frame, currently only occupation status
and the time stamp"""
ts = timestamp.strftime("%A %d %B %Y %I:%M:%S%p")
cv2.putText(frame, "Room Status: {}".format(room_status), (10,20),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,255), 2)
cv2.putText(frame, ts,(10, frame.shape[0]-10),
cv2.FONT_HERSHEY_SIMPLEX,0.35, (0,0,255), 1)
def check_room_status():
global motionCounter
global lastUploaded
if room_status=="Occupied":
#check if enough time has passed between uploads, increments motion
#counter, then resets as to not endless create files
if (timestamp - lastUploaded).seconds >= conf["min_upload_seconds"]:
if (timestamp - lastUploaded).seconds >=conf["min_upload_seconds"]:
motionCounter += 1
#Check if the number of frames with consistent motion is high
#enough
if motionCounter >= conf["min_motion_frames"]:
upload()
lastUploaded=timestamp
motionCounter=0
else:
motionCounter=0
def upload():
"""this is eventually going to be a method to upload to either another pc
or cloud service"""
print ("upload file")
def display_feed():
"""display security feed"""
global tripwire
if conf["show_video"]:
cv2.imshow("Security Feed", frame)
key = cv2.waitKey(1) & 0xFF
tripwire=(True if key==ord('q') else False)
def motion_detect_loop():
"""capture frames from the camera, and detect motion"""
global frameDelta
for f in camera.capture_continuous(rawCapture, format="bgr",
use_video_port=True):
set_motion_detect(f)
#if the average frame is none, initialize it
if avg is None:
start_background_model()
continue
frameDelta=set_delta()
prep_frame_for_processing()
check_contours(cnts)
display_information()
check_room_status()
display_feed()
if tripwire == True:
break
rawCapture.truncate(0)
conf=set_configuration_file(config="conf")
client= None
#here you would refer to the conf.json file and start a session authorization
#for dropbox
#here you would finish the authorization and grab the Dropbox client
#initialize the camera and grab a reference to the raw camera capture
#when class is fixed, this one line should replace much of the code before
#the for loop
#camera = Camera()
camera= PiCamera()
camera.resolution= tuple(conf["resolution"])
camera.framerate= conf["fps"]
rawCapture = PiRGBArray(camera, size=tuple(conf["resolution"]))
bootup_sequence(conf)
# capture frames from the camera
"""for f in camera.capture_continuous(rawCapture, format="bgr",
use_video_port=True):
set_motion_detect(f)
#if the average frame is None, initialize it
if avg is None:
start_background_model()
continue
frameDelta= set_delta()
prep_frame_for_processing()
#loop over the countours
check_contours(cnts)
#draw the text and timestamp on the frame
display_information()
check_room_status()
# if motionCounter >= conf["min_motion_frames"]:
#check to see if dropbox should be used
# if conf["use_dropbox"]:
#write the image to a file
# t=TempImage()
# cv2.imwrite(t.path, frame)
#upload the image Dropbox and cleanup the temporary
#image
# print ("[UPLOAD] {}".format(ts))
# path ="{base_path}/{timestamp}.jpg".format(base_path=conf["dropbox_base_path"],
# timestamp=ts)
# client.put_file(path, open(t.path, "rb"))
# t.cleanup()
#update the last uploaded timestamp and reset the motion
#counter
# lastUploaded= timestamp
# motionCounter= 0
#otherwise, the room is not occupied
# else:
# motionCounter = 0
#check to see if the frames should be displayed to screen
display_feed()
#if the 'q' key is pressed, break the loop
if tripwire == True:
break
#clear the stream in preparation for the next frame
rawCapture.truncate(0)"""