Created
June 29, 2015 20:01
-
-
Save ToeJamson/ad8e56bc8ff97f56267b to your computer and use it in GitHub Desktop.
Raspberry Pi Security Cam (Kevin and Justin)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| from 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 | |
| pubnub = Pubnub(publish_key = 'your_pub_key', | |
| subscribe_key = 'your_sub_key', | |
| uuid='pi') | |
| #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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #Catch and Print Error | |
| def _error(m): | |
| print(m) | |
| #Kill PubNub subscription thread | |
| def _kill(m, n): | |
| pubnub.unsubscribe(subchannel) | |
| 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) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //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);} | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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