From c6c30f1c9ff79a3faa0a40cbc6f98e627ec91c1f Mon Sep 17 00:00:00 2001 From: SteveKekacs Date: Fri, 4 May 2018 16:07:04 -0400 Subject: [PATCH] Updated code and README.md --- README.md | 9 ++++++++- autonomous_receiver.py | 31 +++++++++++++++++-------------- detection/stopsign_detection.py | 23 ++++++++++++++--------- 3 files changed, 39 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index a5aa69d..fda4659 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,9 @@ # 144-Client -This is the code that runs on an external server, in our case a MacBook Air running macOS High Sierra. The main purpose of this code is to perform object recognition(for stop signs) on video that is transmitted from the Raspberry Pi which has a camera module attached. There are three important files: +This is the code that runs on an external server, in our case a MacBook Air running macOS High Sierra, that performs object recognition (for stop signs) on video that is transmitted from the Raspberry Pi which has a camera module attached. + +There are three important files: +1. `autonomous_receiver.py`: Takes in one paramater that specifies which protocol to use (either UDP or TCP), sets up the appropriate sockets and receives video frames from the Raspberry Pi for processing. After an initial 10 frames are received, a `start` command is sent to the Pi to signal the car to start driving, then each following frame is passed through our Stop Sign object detector and once a match has been found sends a `stop` command back to the Pi to signal to the car that a stop sign has been found. +2. `detection/stopsign_detection.py`: Defines a simple `StopSignClassifier` class that loads a pre-trained haar stop sign classifier file (`detection/stopsign_classifier.xml`), and contains a function that given an opencv frame, attempts to detect a stop sign and returns `True` if found else `False`. +3. `detection/stopsign_classifier.xml`: Pre-trained haar classifier for stop signs. + +There is also one irrelevant file (for fun) `client.py`, that allows you to manually drive the mobile RC car from ane external server. diff --git a/autonomous_receiver.py b/autonomous_receiver.py index c50f3f0..0a1193c 100644 --- a/autonomous_receiver.py +++ b/autonomous_receiver.py @@ -1,22 +1,22 @@ """ Receives opencv frames from Rasperry Pi Sender -to process for object detection. +to process for object detection and sends car commands back. """ import sys import cv2 -import pickle import numpy as np -import struct import socket -import random import time from detection.stopsign_detection import StopSignClassifier -HOST_IP='' -SENDING_HOST_IP='10.251.45.1' +# IP address of Raspberry Pi +RPI_IP='10.251.45.1' + +# ports to use for transmitting video and receiving commands VIDEO_PORT=8018 COMMAND_PORT=8019 +# size of each msg (frame) MSG_SZ = 230400 @@ -37,7 +37,7 @@ def receive_video(protocol): # bind to host print("Binding to port %d..." % VIDEO_PORT) - sock.bind((HOST_IP, VIDEO_PORT)) + sock.bind(('', VIDEO_PORT)) # if TCP listen and accept connection conn = None @@ -49,20 +49,22 @@ def receive_video(protocol): print("Established connection with %s..." % addr) # sleep then establish command socket - time.sleep(3) + time.sleep(1) print("\n\nCreating socket for sending car commands...") command_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print("Socket for sending car commands created...") - print("Connecting sending socket to %s:%d..." % (SENDING_HOST_IP, COMMAND_PORT)) + print("Connecting sending socket to %s:%d..." % (RPI_IP, COMMAND_PORT)) while True: # try to connect to socket, if not ready sleep and try again try: - command_sock.connect((SENDING_HOST_IP, COMMAND_PORT)) + command_sock.connect((RPI_IP, COMMAND_PORT)) break except: + print("Connection failed, retrying...") time.sleep(1) - print("Connected sending socket to %s:%d...\n\n" % (SENDING_HOST_IP, COMMAND_PORT)) + + print("Connected sending socket to %s:%d...\n\n" % (RPI_IP, COMMAND_PORT)) # initialize stop sign detection print("Initializing stopsign detection classifier...") @@ -118,10 +120,10 @@ def receive_video(protocol): if cv2.waitKey(1) & 0xFF == ord('q'): break - print(num_frame) + # start car after 10 frames have been received if num_frame == 10: print("Starting car...") - # start car + # send start car command command_sock.send('start'.encode('utf-8')) # close sockets @@ -129,8 +131,9 @@ def receive_video(protocol): command_sock.close() +# check protocol arg, then call receive_video if __name__ == '__main__': - if len(sys.argv) == 2 and sys.argv[1] in ['tcp', 'udp', 'rdp']: + if len(sys.argv) == 2 and sys.argv[1] in ['tcp', 'udp']: protocol = sys.argv[1].upper() receive_video(protocol) else: diff --git a/detection/stopsign_detection.py b/detection/stopsign_detection.py index ff9de60..91e5e42 100644 --- a/detection/stopsign_detection.py +++ b/detection/stopsign_detection.py @@ -1,14 +1,13 @@ -import time - import cv2 -import imutils -import numpy as np + class StopSignClassifier: def __init__(self, *args, **kwargs): + # on init load classifier self.load_classifier() def load_classifier(self): + # loads classifier from pre-trained classifier file (must use absolute path) self.classifier = cv2.CascadeClassifier("/Users/stevenkekacs/144-Client/detection/stopsign_classifier.xml") def detect_stopsign(self, img): @@ -20,16 +19,22 @@ def detect_stopsign(self, img): # Detect any stop signs in the image using the classifier at various scales. stop_signs = self.classifier.detectMultiScale(gray, 1.02, 10) - # Draw a rectangle around each detected sign and display it. - for (x, y, w, h) in stop_signs: + # if stop signs found, draw rectange, calc area and return True + if stop_signs.any(): + # get position and dimensions + x, y, w, h = stop_signs[0] + + # draw rectangle around stop sign cv2.rectangle(img, (x, y), (x+w , y+h), (255, 0, 0), 2) - # calculate area of stop sign, if greater than cutoff - # return True + # calculate area of stop sign stopsign_area = w * h - print(stopsign_area) + print("Stopsign found:", stopsign_area) + + # return True for stopsign found return True + # no stop sign found so return False return False