Created
September 22, 2011 02:09
-
-
Save codekoala/1233865 to your computer and use it in GitHub Desktop.
Tells an Arduino to move some servos in order to center a webcam on someone's face.
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
| /******************************************************* | |
| * SerialServoControl Sketch | |
| * Written by Ryan Owens for SparkFun Electronics | |
| * 7/15/11 | |
| * Tweaked by Josh VanderLinden for himself | |
| * 9/21/11 | |
| * | |
| * This sketch listens to serial commands and uses the data | |
| * to set the position of two servos. | |
| * | |
| * Serial Command Structure: | |
| * u/k: tilt the camera up | |
| * d/j: tilt the camera down | |
| * h/r: pan the camera right | |
| * l: pan the camera left | |
| * | |
| * Hardware Setup | |
| * Servos should be connected to pins 2 and 3 of the Arduino. | |
| * 9V DC Power supply is recommended as USB can't always handle powering two | |
| * servos | |
| */ | |
| #include <Servo.h> | |
| Servo servoTilt, servoPan; | |
| void setup(){ | |
| // The Tilt servo is attached to pin 2. | |
| servoTilt.attach(2); | |
| // The Pan servo is attached to pin 3. | |
| servoPan.attach(3); | |
| // Initially put the servos both at 90 degrees. | |
| servoTilt.write(90); | |
| servoPan.write(90); | |
| // Set up a serial connection for 57600 bps. | |
| Serial.begin(57600); | |
| } | |
| void loop() { | |
| short pos; | |
| switch (Serial.read()) { | |
| case 'u': | |
| case 'k': | |
| pos = servoTilt.read(); | |
| if (pos > 0) servoTilt.write(pos - 1); | |
| break; | |
| case 'd': | |
| case 'j': | |
| pos = servoTilt.read(); | |
| if (pos < 180) servoTilt.write(pos + 1); | |
| break; | |
| case 'l': | |
| pos = servoPan.read(); | |
| if (pos > 0) servoPan.write(pos - 1); | |
| break; | |
| case 'r': | |
| case 'h': | |
| pos = servoPan.read(); | |
| if (pos < 180) servoPan.write(pos + 1); | |
| break; | |
| } | |
| } | |
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
| #!/usr/bin/env python | |
| import cv | |
| import serial | |
| import time | |
| class SmartCam(object): | |
| def __init__(self): | |
| self.capture = cv.CaptureFromCAM(4) | |
| self.cascade = cv.Load('haarcascade_frontalface_alt.xml') | |
| self.storage = cv.CreateMemStorage(0) | |
| self.port = '/dev/ttyACM0' | |
| self.baud = 57600 | |
| self.timeout = 10 | |
| self.size = None | |
| self._serial = None | |
| cv.NamedWindow("SmartCam", 1) | |
| def run(self): | |
| frame = cv.QueryFrame(self.capture) | |
| if self.size is None: | |
| self.size = cv.GetSize(frame) | |
| color_image = cv.CreateImage(self.size, 8, 3) | |
| while True: | |
| color_image = cv.QueryFrame(self.capture) | |
| # Smooth to get rid of false positives | |
| cv.Smooth(color_image, color_image, cv.CV_GAUSSIAN, 3, 0) | |
| faces = cv.HaarDetectObjects(color_image, self.cascade, self.storage, 1.2, 2, cv.CV_HAAR_DO_CANNY_PRUNING, (60, 60)) | |
| if faces: | |
| (x, y, w, h), n = sorted(faces, key=lambda i: i[0][2] * i[0][3], reverse=True)[0] | |
| self.adjust_camera(x, y, w, h) | |
| #cv.Rectangle(color_image, (x, y), (x + w, y + h), 255) | |
| #cv.ShowImage("SmartCam", color_image) | |
| # Listen for ESC key | |
| c = cv.WaitKey(7) % 0x100 | |
| if c == 27: | |
| break | |
| @property | |
| def half_height(self): return int(self.size[1] / 2.0) | |
| @property | |
| def half_width(self): return int(self.size[0] / 2.0) | |
| @property | |
| def window(self): return 20; | |
| @property | |
| def delay(self): return 0.005; | |
| def __del__(self): | |
| try: | |
| self._serial.close() | |
| except: | |
| pass | |
| @property | |
| def serial(self): | |
| if self._serial is None: | |
| self._serial = serial.Serial(self.port, self.baud, timeout=self.timeout) | |
| return self._serial | |
| def adjust_camera(self, x, y, w, h): | |
| """Attempts to center the camera on the biggest face""" | |
| mid_y = int(y + (h / 2.0)) | |
| mid_x = int(x + (w / 2.0)) | |
| if mid_y < (self.half_height - self.window): | |
| self.serial.write('u') | |
| elif mid_y > (self.half_height + self.window): | |
| self.serial.write('d') | |
| time.sleep(self.delay) | |
| if mid_x < (self.half_width - self.window): | |
| self.serial.write('l') | |
| elif mid_x > (self.half_width + self.window): | |
| self.serial.write('r') | |
| time.sleep(self.delay) | |
| if __name__=="__main__": | |
| t = SmartCam() | |
| t.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment