Skip to content

Instantly share code, notes, and snippets.

@stephenlb
Forked from domadev812/RasCam Constants.py
Created November 15, 2017 21:05
Show Gist options
  • Select an option

  • Save stephenlb/173299ad638e9ef238a43e045c9533d4 to your computer and use it in GitHub Desktop.

Select an option

Save stephenlb/173299ad638e9ef238a43e045c9533d4 to your computer and use it in GitHub Desktop.
Raspberry Pi Security Cam (Kevin and Justin)
import cv2
class Detector():
def __init__(self, image_name):
self.image_name = image_name # The image file name
self.image = [] # OpenCV image array
self.drawn = 0 # Count of how many detector-boxes have been drawn
self.drawColors = [(255,0,0),(0,255,0),(0,0,255),(255,255,0),(255,0,255),(0,255,255)] #RGB Values
self.path = "xml/" # The path to the haarcascades data xml files
self.rects = [] # Discovered rectangles from Image Analysis
def detect(self, xml): # Detect people in image and save the image bounds around them
cascade = cv2.CascadeClassifier(self.path + xml)
self.image = cv2.imread(self.image_name) # Loads the image into a numpy array
gray = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY)
hits = cascade.detectMultiScale( # Grayscale and analyze image using
gray, # the selected cascade classifier file
scaleFactor=1.1,
minNeighbors=5,
minSize=(10, 10),
flags=cv2.cv.CV_HAAR_SCALE_IMAGE
)
self.rects.append(hits) # Add detected people to rect-list for drawing
return hits # Can use len(hits) to check if anyone was found
# The following functions provide an xml file to be used as the cascade classifier
# to detect different things, such as face, upper body, or pedestrian
def face(self):
return self.detect('haarcascade_frontalface_default.xml')
def face2(self):
return self.detect('haarcascade_frontalface_alt.xml')
def face3(self):
return self.detect('haarcascade_frontalface_alt2.xml')
def full_body(self):
return self.detect('haarcascade_fullbody.xml')
def upper_body(self):
return self.detect('haarcascade_upperbody.xml')
def pedestrian(self):
return self.detect("hogcascade_pedestrians.xml")
# This function will draw the rectangles around all objects found and then
# overwrite the original image file.
def draw(self):
for hits in self.rects:
color = self.drawColors[self.drawn % len(self.drawColors)] # Rect color selection
self.drawn += 1
for (x,y,w,h) in hits:
cv2.rectangle(self.image, (x, y), (x+w, y+h), color, 1) # Draws the Rect
cv2.imwrite(self.image_name, self.image) # Saves the file over the original image name
return hits
from pubnub.pnconfiguration import PNConfiguration
from pubnub.pubnub import PubNub
from detector import Detector
import RPi.GPIO as GPIO
import time
import picamera
import sys, os
import json,httplib
import base64
#This is the input number for our PIR sensor
sensor = 4
#We set mode to BCM
GPIO.setmode(GPIO.BCM)
#Set up Sensor as input
GPIO.setup(sensor, GPIO.IN, GPIO.PUD_DOWN)
previous_state = False
current_state = False
#Connect to Parse
connection = httplib.HTTPSConnection('api.parse.com', 443)
connection.connect()
#Connect to PubNub
pnconfig = PNConfiguration()
pnconfig.subscribe_key = 'your_sub_key'
pnconfig.publish_key = 'your_pub_key'
pnconfig.uuid = 'pi'
pubnub = PubNub(pnconfig)
#initialize camera
cam = picamera.PiCamera()
#define PubNum Channels
channel = 'iotchannel'
subchannel = 'liveCamStatus'
#Camera Settings
imgCount = 1
frameSleep = 0.5 # Seconds between burst-snaps
camSleep = 5 # Seconds between Detections
#Catch and Print Error
def _error(m):
print(m)
#Kill PubNub subscription thread
def _kill(m, n):
pubnub.unsubscribe().channels("subchannel").execute()
def is_person(image):
det = Detector(image)
faces = len(det.face())
print "FACE: ", det.drawColors[det.drawn-1 % len(det.drawColors)], faces
uppers = len(det.upper_body())
print "UPPR: ", det.drawColors[det.drawn-1 % len(det.drawColors)], uppers
fulls = len(det.full_body())
print "FULL: ", det.drawColors[det.drawn-1 % len(det.drawColors)], fulls
peds = len(det.pedestrian())
print "PEDS: ", det.drawColors[det.drawn-1 % len(det.drawColors)], peds
det.draw()
det.overlay()
return faces + uppers + fulls + peds
#This function will examine our image and make decision
def processImage(imgFile):
global connection
if is_person(imgFile):
#Our image contains a person so print True
print "True"
#Encode our image file as base64, neccessary to store image into Parse
with open(imgFile, "rb") as image_file:
encoded_string = base64.b64encode(image_file.read())
try:
#Lets send our image to Parse
##Fill in the name of your custom Parse Class, we send the base64 string and name of our image
connection.request('POST', '/1/classes/Your_Parse_Class_Here', json.dumps({
"fileData": encoded_string,
"fileName": imgFile,
}), {
##Grab your Parse keys and fill them in here. Keys can be found by going to Settings->Keys
"X-Parse-Application-Id": "Your_X-Parse-Application-Id",
"X-Parse-REST-API-Key": "Your_X-Parse-REST-API-Key",
"Content-Type": "application/json"
})
result = json.loads(connection.getresponse().read())
#If all goes well print "Photo Uploaded"!
print "Photo Uploaded!"
#If our connection to Parse doesnt work
except:
#Close the connection and try again
connection.close()
connection = httplib.HTTPSConnection('api.parse.com', 443)
connection.connect()
print "Error Uploading."
#Send a message to PubNub with the name of our image to channel
pubnub.publish(channel, imgFile)
else: # Not a person
print "False"
#delete the file locally
os.remove(imgFile)
sys.exit(0)
//initialize an instance of PubNu
var pubnub = PUBNUB.init({
publish_key: 'Your_pub_key',
subscribe_key: 'Your_sub_key'
});
Parse.initialize("Your_Parse_Application_ID", "Your_Parse_Javascript_Key");
var Your_Parse_Class_name = Parse.Object.extend("Your_Parse_Class_name");
var query = new Parse.Query(Your_Parse_Class_name);
//Lets pull our photos with the most recent at top
query.addDescending('createdAt');
query.find({
success: function(results) {
// Do something with the returned Parse.Object values
for (var i = 0; i < queryLimit; i++) {
var object = results[i];
var filedata = "data:image/png;base64," + object.get('fileData')
//create an element of type image
var elem = document.createElement("img");
//set the source of the image to our base64 encoded data
elem.setAttribute("src", filedata);
//set the name of the image to the time it was created at
var filename = object.createdAt.toString();
var text = document.createElement("h1");
text.innerHTML = filename.split("GMT")[0];
//add the image to our div
document.getElementById("placehere");
}
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
//Subscribe to PubNub to listen for new photos in realtime
pubnub.subscribe({
channel: 'iotchannel',
message: function(m){
var Your_Parse_Class_name = Parse.Object.extend("Your_Parse_Class_name");
var query = new Parse.Query(Your_Parse_Class_name);
query.addDescending('createdAt');
//Look for a photo with the same name as the message you got from PubNub
query.equalTo("fileName", m);
query.find({
success: function(results) {
// Do something with the returned Parse.Object values
for (var i = 0; i < queryLimit; i++) {
var object = results[i];
var filedata = "data:image/png;base64," + object.get('fileData')
//create an element of type image
var elem = document.createElement("img");
//set the source of the image to our base64 encoded data
elem.setAttribute("src", filedata);
//set the name of the image to the time it was created at
var filename = object.createdAt.toString();
var text = document.createElement("h1");
text.innerHTML = filename.split("GMT")[0];
//add the image to our div
document.getElementById("placehere");
}
},
error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
},
error: function (error) {
// Handle error here
console.log(JSON.stringify(error));
}
});
//This channel will look for the number of people on the channel using Presence
pubnub.subscribe({
channel: "liveCam",
presence: function(m){
console.log(m)
$(".occupancy").text("There are " + m['occupancy'] + " viewers here right now");
},
message: function(m){console.log(m)}
});
//This channel will look to check the status of the Camera by seeing if it is subscribed to liveCamStatus or not
pubnub.subscribe({
channel: "liveCamStatus",
presence: function(m){
console.log(m)
if(m['uuid'] == "pi"){
if (m['action']=="join"){
document.getElementById("status").className = "cameraON";
document.getElementById("status").innerHTML = "On";
}
else {
document.getElementById("status").className = "cameraOff";
document.getElementById("status").innerHTML = "Off";
}
}
},
message: function(m){console.log(m);}
});
try:
#Subscribe to subchannel, set callback function to _kill and set error fucntion to _error
pubnub.subscribe(channels=subchannel, callback=_kill, error=_error) ## Change to callback
while True:
previous_state = current_state
#our current state is set to our PIR sensor state
current_state = GPIO.input(sensor)
#if our PIR sensor state changes
if current_state != previous_state:
new_state = "HIGH" if current_state else "LOW"
#Then we know motion has been detected
if current_state:
#Lets turn on camera preview so we can see what the camera is snapping a picture of
cam.start_preview() # Comment in future
cam.preview_fullscreen = False
cam.preview_window = (10,10, 320,240)
print('Motion Detected')
#set a variable with the current time to use as image file name
curTime = (time.strftime("%I:%M:%S")) + ".jpg"
#take a photo, give it a name, and resize it to fit into Parse
cam.capture(curTime, resize=(320,240))
#Now turn off the camera preview after photo is taken
cam.stop_preview()
#If we interrupt main thread with a Keyboard Interrupt
except KeyboardInterrupt:
#Turn off any camea preview
cam.stop_preview()
#unsubscribe from subchannel
pubnub.unsubscribe(subchannel)
sys.exit(0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment