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.

Tags: 

Viewing 12 Comments

      • ^
      • v

      Just to clarify, the Haar cascade file is one of the sample ones that comes with OpenCV. The script I wrote was based on the OpenCV face detection sample too, but using gstreamer instead of OpenCV’s HighGUI to interface the webcam (HighGUI didn’t support the camera in the XO).

      Its good that you got it working though. There is some pretty amazing stuff in OpenCV.

      • ^
      • v

      Jhon 6 months ago

      I figured it out how to properly use cvWaitKey.

      In your code you are waiting just 10 ms for a key, and only after the image was processed.
      So, if you wait a little bit longer(maybe 100ms, but this will slow down a lot the fps) you will be able to catch the keys.

      However, there is also another problem cvWaitKey returns -1 when no key was pressed, but return a string(char) holding the key pressed, so you need to do the following:
      if k!=-1 and ord(k) == 0x1b: # ESC
      print ‘ESC pressed. Exiting …’
      break

      • ^
      • v

      randomm 5 months ago

      this is great stuff! thanks for this…

      We managed to get up to 4 faces recognized at the same time.

      • ^
      • v

      Venkat 2 months ago

      When I tried runing the above code in windows xp, encountered the following error.

      D:\SW\CamFD>python test2.py
      Traceback (most recent call last):
      File “test2.py”, line 2, in <module>
      from CVtypes import cv
      File “D:\SW\CamFD\CVtypes.py”, line 42, in <module>
      _cxDLL = cdll.cxcore100
      File “C:\Python25\lib\ctypes\__init__.py”, line 423, in __getattr__
      dll = self._dlltype(name)
      File “C:\Python25\lib\ctypes\__init__.py”, line 348, in __init__
      self._handle = _dlopen(self._name, mode)
      WindowsError: [Error 126] The specified module could not be found

      Any help regarding this will be great!

      • ^
      • v

      You need to have OpenCV installed. I guess that is the problem. I didn’t try it on Windows yet since there’s no D-BUS support, but in theory the face detection code should work.

      I will probably release a first version of the code in the following weeks, so stay tuned!

    • ^
    • v

    Simon 2 months ago

    Hello, Sir
    I’m from Asia. I’m just starting to learn openCV.
    Is there any opinion or advise from Sir as an expert to me to start learning opencvThank you very much.

Trackbacks

(Trackback URL)

Leave a Comment