Wednesday, February 10, 2010

A face full of celebration

As I mentioned earlier, I was able to get an openCV based python script that pulls images from a webcam and locates faces. Some of you may be wondering why I'd want to track faces? Well, I could make my rig constantly point a laser pointer at some one's face, but realistically speaking, this is merely an exercise in image processing with openCV.

Before I go any further, here's an example of a tracked face:

(Yes, this was actually identified as a face)

And here's the code to go with it:
#!/usr/bin/python

import sys, os, pygame
from pygame.locals import *
from opencv.cv import *
from opencv.highgui import *
from opencv.adaptors import Ipl2PIL #need python-numeric

fps = 30.0
pygame.init()
window = pygame.display.set_mode((640,480))
pygame.display.set_caption("Face track Demo")
screen = pygame.display.get_surface()
camera = cvCreateCameraCapture(0)

def get_image():
im = cvQueryFrame(camera)
#return Ipl2PIL(im)
return im

def detectFace(image):
grayscale = cvCreateImage(cvSize(640, 480), 8, 1)
cvCvtColor(image, grayscale, CV_BGR2GRAY)
storage = cvCreateMemStorage(0)
cvClearMemStorage(storage)
cvEqualizeHist(grayscale, grayscale)
cascade = cvLoadHaarClassifierCascade('haarcascade_frontalface_alt.xml', cvSize(1,1))
faces = cvHaarDetectObjects(grayscale, cascade, storage, 1.2, 2, CV_HAAR_DO_CANNY_PRUNING, cvSize(100,100))

if faces:
for i in faces:
cvRectangle(image, cvPoint( int(i.x), int(i.y)), cvPoint(int(i.x+i.width), int(i.y+i.height)), CV_RGB(0,255,0), 3, 8, 0)

def displayObject(image):
cvShowImage("face", image)
cvWaitKey()

def main(im):
events = pygame.event.get()
for event in events:
if event.type == KEYDOWN:
if event.key == K_q:
sys.exit(0)

if event.key == K_p:
cvSaveImage("face.jpg", im)
print "Snapshot saved"

im = get_image()
pygame.display.flip()
pygame.time.delay(int(1000 * 1.0/fps))

detectFace(im)
temp = Ipl2PIL(im)
screen.blit(pygame.image.frombuffer(temp.tostring(), temp.size, temp.mode), (0,0))
return im

if __name__ == "__main__":
im = get_image()
while(True):
im = main(im)
Sources:

I drew a lot of the code from both sources, but I wrote my own little GUI in pygame (hard, I know).

I did encounter a number of issues along the way, most prominently a lack of Windows compatibility. While the python bindings are available on Windows, some of the methods would simply not work and cause the python interpreter to crash. This only became an issue because I have to use Windows 7 for school and it was a little difficult to play around with this program during class because many classes require the use of Windows only software.

The next step is to try and coerce openCV into recognize other objects besides faces. Also, translating a recognized object in a picture to movement of the pan-tilt rig could prove difficult. Luckily, I already have a few ideas on how I can accomplish this.

Friday, February 5, 2010

Hardware issues and the beginning of vision processing

It's been a while since my last post, but I've made a fair amount of progress. I was testing the pan-tilt rig when I started to run into some issues with it. The power supply I was using could only supply a maximum of .5 amps and the two servos together were drawing substantially more then that. This was causing the voltage to dip and the servo motors to start acting sporadically. Luckily, a guy I work with was kind enough to give me an old computer power supply, which can provide more than enough current to power the two servos. Unfortunately, using the PSU limits me to running the servos at 12 volts, which isn't ideal because it will wear the servos out, but the servos are cheap and it's what I've got.

During my time troubleshooting the servos, I took the two of them apart to see if anything overt was wrong. Much to my dismay, I discovered that the servo controlling the tilt action is actually missing about 2 teeth on one of the gears. While the servo still works, there is a certain area in its rotation where it sputters and skips. I'm still going to use it, but the laser pointer won't be nearly as precise now.

I should be making another post soonish as I've made some headway with object tracking using python and openCV. More on that to come in the near future.

Monday, January 18, 2010

IT LIVESSSSS!

After many hours of toiling away (and by many hours, I really mean about one or so), I wrote the necessary Arduino code needed to run the servos. It looks like this (I wish this blog site had actual code quoting):
#include

Servo pan, tilt;

void setup()
{
  Serial.begin(9600);
  pan.attach(3, 1000, 2000);
  tilt.attach(10, 1000, 2000);
  pinMode(2, OUTPUT);
  pinMode(4, OUTPUT);
  delay(15);
  pan.write(100);
  tilt.write(100);
}

void loop()
{
  digitalWrite(2, HIGH);
  digitalWrite(4, LOW);
  while(Serial.available() > 2)
  {
    int command = Serial.read();
    if(command == 255)
    {
      int command = Serial.read();
      int value = Serial.read();

      switch (command)
      {
      case 0:
        pan.write(value);
        break;

      case 1:
        tilt.write(value);
        break;
      }
    }
  }
}

All the code does is set up the servos and the on board serial port using the nice included libraries. It then instructs the Arduino to sit around and wait for serial data. When it gets something on its serial port, it checks first for a start byte (255), then for a servo ID (either 0 or 1), then a value to move the servo. This value should range from 0 to 180 and it (theoretically) corresponds to the degree the servo rotates to.

Here's a quick video of it moving:

There are still a number of issues to be worked out, mainly, it seems that sometimes when I issue a command to control one of the motors, it inadvertently moves the other motor as well. I am not completely sure what causes this, but I think I may try rewriting a large portion of the Arduino code to better deal with the serial communication.

Although I can (mostly) control the pan-tilt rig via a computer, there is still one last hardware issue that needs to be addressed before I can start distracting kittens and that is I need to create a method by which the computer can actually turn the laser pointer on and off. This shouldn't be too difficult of a challenge seeing as it should only consist of a few resistors and a transistor. I'll post that update sometime in the future.

Saturday, January 9, 2010

The pan-tilt rig

As I mentioned before, the pan-tilt rig takes relatively little time to construct

You can see from the picture the rig is built using wooden blocks I cut out of scraps of 2x4. The servos are connected to an Arduino via a servo shield I constructed last year for a robotic platypus. The battery in the background supplies power to the servos and while it probably is not necessary when only two servos are involved (a single USB port should supply enough current), the way the shield was constructed necessitates and external power source.

I will eventually construct a nice little enclosure for the rig, the Arduino, and the camera, but I'm more excited about getting something that actually points up and running.

The next step is to write code for the Arduino that allows a computer to actually control the servos.

Finally, as a note to those that know me, I plan to make this rig fully compatible with a wiimote for a more futuristic pointing experience.


Thursday, January 7, 2010

Game Plan



The first step any sane person would conduct in creating a device is to have a plan, and this is it.

The actual pointing will be done by a green laser pointer I purchased off Amazon for about $30 some time ago. It will be mounted on a pan-tilt rig constructed from two servo motors and some random scraps of wood. The servos will interface to the computer via an Arduino micro-controller and a webcam will provide the video feed of what to point at.

That's my plan, the rest is winging it. The hardware aspect of this project is rather simple and should hopefully be completed in a few days, but there is a lot of leeway with the software side of things, so completion of that will take a long time.


Introduction

This is a blog about pointing at things. Why would someone ever write a blog about pointing at things, you may ask. Well, the answer to that is that it isn't so much about the direct action of pointing, but rather about building a mean, green laser pointing machine. This will serve as a build log for a small project I am doing in my free time.

Why am I documenting this project? Because a particular physics genius told me I should do so. He also enlisted the help of a number of individuals to scream "raserbrog" resulting in the title of this log.