Skip to content

Instantly share code, notes, and snippets.

@codekoala
Created September 22, 2011 02:09
Show Gist options
  • Select an option

  • Save codekoala/1233865 to your computer and use it in GitHub Desktop.

Select an option

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.
/*******************************************************
* 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;
}
}
#!/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