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: , , , , , ,

  • TechB
    After about a week of work, I couldn't get opencv to work. I used VideoCapture again, and fdlib.dll to detect the faces. http://www.kyb.mpg.de/bs/people/kienzle/facedem...
  • TechB
    Hey great post. I can't wait to get started hacking it to my needs. I made a script that tracts an IR LED and maps the mouse to the movements(http://hackaday.com/2010/02/25/python-ir-tracking-for-the-handicapped/).

    I used VideoCapture(http://videocapture.sourceforge.net/) for the webcam interface though. I'm going to try and map the mouse movements to this new face-recognition.
  • auttapong
    hi. i have this
    Null pointer (Invalid classifier cascade)
    in function cvHaarDetectObjects,
    C:\User\VP\operncv\cv\src\cvhaar.cpp(890)
  • Are you sure you have the cascade file in the same directory?
  • auttapong
    C:\Dev\OpenCV\data\haarcascades
  • I currently don't have a Linux machine for testing, but IIRC the line

    cascade = cv.LoadHaarClassifierCascade('haarcascade_frontalface_alt.xml', cv.Size(1,1))

    requires the cascade file to be in the same directory as the script.

    By the way, the script I presented in this blog post won't work on Windows. You should use the simple_winclient.py script for that (which can be found in the tarball available from my website).
  • auttapong
    thank you very much Jo ^^
  • You're welcome!
  • AlexMikhalev
    Thank you for posting it online. I find it useful.
  • You're welcome! I'm glad you found it useful.
  • samsnaap
    its been great coming across your site.however is there a way for me detect and display the available webcams conected to a pc.i tried searching online buy couldnt comeup with anything.Pygame 1.9 however has a module to take care of that.but the problem with pygame is .i cant include it in the gui of my project.not can i attach any stuff like buttons onto the defaul gui provided.would really appreciate if you could help my out.thanks in advance
  • I know there is a function to get the number of cameras:

    cvcamGetCamerascount()

    Maybe that helps?
  • samsnaap
    thanks jo.well i kindda figured a way out last week. and these are basically the codes
    def listWebcam(self,path='/dev'):
    """detects the available webcam mounted to a computer """
    devicelist = []
    for device in os.listdir(path):#loops through devices all mounted devices
    if device.startswith('video'):#returns true if a device with video prefix is found
    devicenum = device.rsplit('o')#seperates video from the device index
    devicelist.append(devicenum[1])
    return devicelist
  • That's Linux-specific of course, but will indeed do the trick.
  • samsnaap
    yup,sorry i guess i forgot to mention i was looking for linux specific solution.
    oh and by the way.i do have some issues with the camera though.when i connect to the webcam.sometimes it just doesnt connect and the entire application just closes.
    that is when i change the device value to different numbers ."self.capture = cv.CaptureFromCAM(device).i tested it with three webcams connected.it connected to two but not to the third.and then i removed the third and it just connected to one.
    any idea why this is happening
  • selva
    hi...hw can i edit this coding so that i can detect an image that i have saved. i'm using ubuntu 9.04....need ur help...thank u...
  • Its really cool, I came to know this really worth visiting, just bookmarked your site.

    http://gisnap.com/
    The place where fun never ends
  • So cool. Python can make opencv more easy and funny.
  • the-maxx
    hi, i stumbled upon your little nice python script a few days ago and ported it to opencv 2.0 with its new python bindings. Hope anyone is interested, maybe you can update your version with this.

    import sys
    import cv

    class FaceDetect():
    def __init__(self):
    cv.NamedWindow ("CamShiftDemo", 1)
    device = 0
    self.capture = cv.CaptureFromCAM(device)
    capture_size = (320,200)
    cv.SetCaptureProperty(self.capture, cv.CV_CAP_PROP_FRAME_WIDTH, capture_size[0])
    cv.SetCaptureProperty(self.capture, cv.CV_CAP_PROP_FRAME_HEIGHT, capture_size[1])

    def detect(self):
    cv.CvtColor(self.frame, self.grayscale, cv.CV_RGB2GRAY)

    #equalize histogram
    cv.EqualizeHist(self.grayscale, self.grayscale)

    # detect objects
    faces = cv.HaarDetectObjects(image=self.grayscale, cascade=self.cascade, storage=self.storage, scale_factor=1.2,\
    min_neighbors=2, flags=cv.CV_HAAR_DO_CANNY_PRUNING)

    if faces:
    #print 'face detected!'
    for i in faces:
    if i[1] > 10:
    cv.Circle(self.frame, ((2*i[0][0]+i[0][2])/2,(2*i[0][1]+i[0][3])/2), (i[0][2]+i[0][3])/4, (128, 255, 128), 2, 8, 0)

    def run(self):
    # check if capture device is OK
    if not self.capture:
    print "Error opening capture device"
    sys.exit(1)

    self.frame = cv.QueryFrame(self.capture)
    self.image_size = cv.GetSize(self.frame)

    # create grayscale version
    self.grayscale = cv.CreateImage(self.image_size, 8, 1)

    # create storage
    self.storage = cv.CreateMemStorage(128)
    self.cascade = cv.Load('haarcascade_frontalface_default.xml')

    while 1:
    # do forever
    # capture the current frame
    self.frame = cv.QueryFrame(self.capture)
    if self.frame is None:
    break

    # mirror
    cv.Flip(self.frame, None, 1)

    # face detection
    self.detect()

    # display webcam image
    cv.ShowImage('CamShiftDemo', self.frame)
    # handle events
    k = cv.WaitKey(10)

    if k == 0x1b: # ESC
    print 'ESC pressed. Exiting ...'
    break
    sys.exit(1)

    if __name__ == "__main__":
    print "Press ESC to exit ..."
    face_detect = FaceDetect()
    face_detect.run()
  • Thanks a lot! I'll give it a try!
  • the-maxx
    argh, it killed my tabs!!!
  • njay
    hey!! i am nj here, i am trying to execute this program on windows I am getting following error. I saw a post with same thing, where u said u will be releasing new version so that it works on windows. Is it not released yet?
  • You should install OpenCV first, and try to run the simple_winclient.py script. The software is available at my website.
  • this is awesome, i have been wanting to do this with python for awhile now. great stuff.
  • I'm still having trouble with the escape key. Any tips?
  • cyril84
    I have do sudo apt-get install python-opencv. It is already installed. What can i do?
  • The script uses Gary Bishop's CVtypes, not python-opencv.
  • cyril84
    Hello, i have this:

    Traceback (most recent call last):
    File "opencv.py", line 2, in <module>
    from CVtypes import cv
    ImportError: No module named CVtypes

    What is this mistake? how install cvtypes?

    Thinks
  • Hello, i try your code but i have this:

    cyril@zilo2:~/Bureau/test$ sudo python webcam2.py
    Traceback (most recent call last):
    File "webcam2.py", line 3, in <module>
    from CVtypes import cv
    ImportError: No module named CVtypes

    i use ubuntu, how cab i install opencv? sudo apt-get install ?

    Thinks @+
  • nop
    In synaptic you can fing python-opencv
  • sreeraj
    hi, i'm having this problem when i'm running your code..

    i have an integrated camera on my laptop, which works with some apps like cheese.

    while running this code, the camera(led) turns on, but nothing comes on the screen.
    the script hangs and i have to ctrl+C to close it.

    any pointers to help me with this situation will be appreciated.
    thanks
  • 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).
  • nop
    Hello!
    Your if script silently hangs on this line for me:
    cascade = cv.LoadHaarClassifierCascade('haarcascade_frontalface_alt.xml', cv.Size(1,1))

    What can be the problem here? This xml exists in same directory and the is no any error output.

    Thanks in advance!
  • Are you using Ubuntu?
  • nop
    yes, 9.04
  • gabox
    hi i want to put the window's webcam in other program both under python, but i dont how to do it, the project is a program with bottons and they controll a robot and the robot get the webcam, by the way im using linux mint 6
  • It might be good to use a specific GUI toolkit in this case, such as WxWindows.

    Have a look at Gary Bishop's blog post, where he grabs a bitmap from the camera and displays this in a Wx window: http://wwwx.cs.unc.edu/~gb/wp/blog/2007/02/04/p...
  • Simon
    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 opencv

    Thank you very much.
  • Venkat
    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!
  • 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!
  • randomm
    this is great stuff! thanks for this...

    We managed to get up to 4 faces recognized at the same time.
  • You're welcome, I'm glad it was useful for you.
  • Jhon
    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
  • Ah thanks, that's very helpful!
  • daxroc
    Nice script , worked fine for me @30fps
  • You are right, I noticed yesterday that the cascade file was part of OpenCV. Thanks for clarifying!
  • 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.
  • Si
    excellent stuff. Many thanks
  • You're welcome! I'm glad you find it useful.
blog comments powered by Disqus