Tag: facade

Moving my code from Launchpad to GitHub

This afternoon, I decided to convert my old code repositories from bzr to git, and move them from Launchpad to GitHub. I have converted Cassowary.net, PydgetRFID, Facade, as well as Uiml.net.

It turns out that converting a bzr repository with a single branch to git is quite easy. Here’s how I did it (after installing the latest versions of both bzr and git):

$ mkdir repo.git
$ cd repo.git
$ git init
$ bzr fast-export --plain ../repo.bzr | git fast-import
$ git reset --hard

Of course, repo.bzr is your old bzr repository here, while repo.git is your newly created git repository. The fast-export/fast-import commands convert the repository’s history from bzr to git. To populate our directory with the bzr repository’s files, however, we also need to perform a hard reset. If you need to convert multiple bzr branches to git, have a look at this post.

I started experimenting with distributed version control systems (DVCS) while working on my MSc thesis (around 2005). I originally maintained Cassowary.net using darcs (a DVCS written in Haskell), and switched to bzr later. Back in the early days of Uiml.net, we used CVS, which was horrible at moving or renaming files, not to mention the inability to work offline and still commit your work.

I preferred darcs and bzr over git at the time because they were a lot easier to use. These days, git seems to have catched up to bzr in that regard. Back in 2006, I also did a few performance tests and found that bzr was a lot slower than git. Things seem to have improved somewhat, but git is still The King of Speed. Oh, and GitHub is great!

Facade update: code available and information about related student projects

My previous posts on face detection with Python and on changing the user’s presence when he/she is detected by the webcam are two of the most popular articles on my blog. There were quite a few comments that asked about the code for this project.

Although I already created a Facade project page a while ago and made the code available through Bazaar, I never announced it here. To make it easier to try the script out, I also uploaded an archive of the code. This version includes a simple Python script that works on Windows (simple_winclient.py) that performs face detection.

I noticed today that Jinwei Gu, a PhD student at the University of Columbia and teaching assistant for the course COMS W4737 (E6737) Biometrics, included my blog post in a list of links to resources for doing face detection.

Last year, two students improved the presence detection in Facade during their Bachelor’s theses.

Bram Bonné worked on the network aspect, to allow users to have their presence detected on multiple computers. When users would move from one computer to another (or to a mobile device), their messages would automatically be routed to their current machine.

Here are a few screenshots from Bram’s thesis:

Multi-device presence

An everywhere messaging service that takes into account the user's presence.

Bram also created a demo video of his system:

Kristof Bamps worked on supporting a more diverse set of sensors (e.g. presence of a Bluetooth phone, keyboard and mouse input). He used a decision tree to model all these sensors, and determine the user’s correct presence based on the collected information.

Two screenshots from Kristof’s thesis:

Showing the user's presence state

A history of presence changes

Kristof’s demo video:

I have unfortunately not yet found the time yet to merge Kristof’s and Bram’s code into the main Facade branch, but this should not be too big of a problem.

Small update on face detection post

Just a quick update on my previous post. I hooked my code up to a D-Bus daemon, and used it to detect if I was sitting behind my desk or not.

I had to position the camera a bit lower, because it would sometimes not recognize my face when I was looking at the bottom of my screen. Having a dual-monitor setup doesn’t help either, since you should ideally position the webcam in the middle of the two displays to have good coverage. I positioned the webcam in the middle of the two displays at the bottom and tilted it upwards, which gives good results:

I guesstimated that if the system couldn’t detect a face for a period of 10 seconds, I would be away from my desk (or at least not paying attention to the screen). I played around a bit with pygtk and notify-python to create a status icon and show notification bubbles whenever my status changed. Here’s what happens when it detects that I’m away from my desk (notice the bubble in the upper right corner):

When I return, the system will change its status icon accordingly and notify me again:

OpenCV is fun!

Fun with Python, OpenCV and face detection

I had some fun with Gary Bishop’s OpenCV Python wrapper this morning. I wanted to try out OpenCV for detecting faces using a web cam. This could be used for instance to see if someone is sitting behind his desk or not. I used Gary’s Python wrapper since I didn’t want to code in C++.

I didn’t know where to start, so I searched for existing OpenCV face detection examples. I found a blog post by Nirav Patel explaining how to use OpenCV’s official Python bindings to perform face detection. Nirav will be working on a webcam module for Pygame for the Google Summer of Code.

I managed to rewrite Nirav’s example to get it working with CVtypes:

Here’s the code. Although it’s just a quick and dirty hack, it might be useful to others. It requires CVtypes and OpenCV, and was tested on Ubuntu Hardy with a Logitech QuickCam Communicate Deluxe webcam. You will need Nirav’s Haar cascade file as well.

import sys
from CVtypes import cv
 
def detect(image):
    image_size = cv.GetSize(image)
 
    # create grayscale version
    grayscale = cv.CreateImage(image_size, 8, 1)
    cv.CvtColor(image, grayscale, cv.BGR2GRAY)
 
    # create storage
    storage = cv.CreateMemStorage(0)
    cv.ClearMemStorage(storage)
 
    # equalize histogram
    cv.EqualizeHist(grayscale, grayscale)
 
    # detect objects
    cascade = cv.LoadHaarClassifierCascade('haarcascade_frontalface_alt.xml', cv.Size(1,1))
    faces = cv.HaarDetectObjects(grayscale, cascade, storage, 1.2, 2, cv.HAAR_DO_CANNY_PRUNING, cv.Size(50, 50))
 
    if faces:
        print 'face detected!'
        for i in faces:
            cv.Rectangle(image, cv.Point( int(i.x), int(i.y)),
                         cv.Point(int(i.x + i.width), int(i.y + i.height)),
                         cv.RGB(0, 255, 0), 3, 8, 0)
 
if __name__ == "__main__":
    print "OpenCV version: %s (%d, %d, %d)" % (cv.VERSION,
                                               cv.MAJOR_VERSION,
                                               cv.MINOR_VERSION,
                                               cv.SUBMINOR_VERSION)
 
    print "Press ESC to exit ..."
 
    # create windows
    cv.NamedWindow('Camera', cv.WINDOW_AUTOSIZE)
 
    # create capture device
    device = 0 # assume we want first device
    capture = cv.CreateCameraCapture(0)
    cv.SetCaptureProperty(capture, cv.CAP_PROP_FRAME_WIDTH, 640)
    cv.SetCaptureProperty(capture, cv.CAP_PROP_FRAME_HEIGHT, 480)    
 
    # check if capture device is OK
    if not capture:
        print "Error opening capture device"
        sys.exit(1)
 
    while 1:
        # do forever
 
        # capture the current frame
        frame = cv.QueryFrame(capture)
        if frame is None:
            break
 
        # mirror
        cv.Flip(frame, None, 1)
 
        # face detection
        detect(frame)
 
        # display webcam image
        cv.ShowImage('Camera', frame)
 
        # handle events
        k = cv.WaitKey(10)
 
        if k == 0x1b: # ESC
            print 'ESC pressed. Exiting ...'
            break

A known problem is that pressing the escape key doesn’t quit the program. Might be something wrong in my use of the cv.WaitKey function. Meanwhile you can just use Ctrl+C. All in all, the face detection works pretty well. It doesn’t recognize multiple faces yet, but that might be due to the training data. It would be interesting to experiment with OpenCV’s support for eye tracking in the future.

Update: the script does recognize multiple faces in a frame. Yesterday when Alex stood at my desk, it recognized his face as well. I think it didn’t work before because I used cv.Size(100, 100) for the last parameter of cv.HaarDetectObjects instead of cv.Size(50, 50). This parameter indicates the minimum face size (in pixels). When people were standing around my desk, they were usually farther away from the camera. Their face was then probably smaller than 100×100 pixels.

Just a quick note on ctypes. I remember when I created PydgetRFID that I tried to use libphidgets’ SWIG-generated Python bindings, but couldn’t get them to work properly. I had read about ctypes, and decided to use it for creating my own wrapper around libphidgets. Within a few hours I had a working prototype. When you’re struggling with SWIG-generated Python bindings, or have some C library without bindings that you would like to use, give ctypes a try. Gary Bishop wrote about a couple of interesting ctypes tricks to make the process easier.