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.

112 Comments

Add yours

  1. excellent stuff. Many thanks

  2. You're welcome! I'm glad you find it useful.

  3. 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.

  4. You are right, I noticed yesterday that the cascade file was part of OpenCV. Thanks for clarifying!

  5. Nice script , worked fine for me @30fps

  6. 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

  7. Ah thanks, that's very helpful!

  8. this is great stuff! thanks for this…

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

  9. You're welcome, I'm glad it was useful for you.

  10. This article I so true, keep on writing like this, enjoyment to read 144

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

    D:SWCamFD>python test2.py
    Traceback (most recent call last):
    File “test2.py”, line 2, in <module>
    from CVtypes import cv
    File “D:SWCamFDCVtypes.py”, line 42, in <module>
    _cxDLL = cdll.cxcore100
    File “C:Python25libctypes__init__.py”, line 423, in __getattr__
    dll = self._dlltype(name)
    File “C:Python25libctypes__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!

  12. 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!

  13. 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.

  14. 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.

  15. I am into doing same stuff but sad to say I'm still at the first phase of learning. I look forward to being like you so I can also share my know how for others to use.

  16. how is running? fast or not? I think opencv is universal thing… if u write your own codes it will be faster than opencv because there too many functions and processes unneedful… so goodluck!!!

  17. 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

  18. 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!

  19. Are you using Ubuntu?

  20. 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

  21. 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).

  22. 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

  23. 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 @+

  24. In synaptic you can fing python-opencv

  25. 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

  26. I have do sudo apt-get install python-opencv. It is already installed. What can i do?

  27. I'm still having trouble with the escape key. Any tips?

  28. The script uses Gary Bishop's CVtypes, not python-opencv.

  29. this is awesome, i have been wanting to do this with python for awhile now. great stuff.

  30. 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?

  31. You should install OpenCV first, and try to run the simple_winclient.py script. The software is available at my website.

  32. 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()

  33. argh, it killed my tabs!!!

  34. Thanks a lot! I'll give it a try!

  35. So cool. Python can make opencv more easy and funny.

  36. Its really cool, I came to know this really worth visiting, just bookmarked your site.

    http://gisnap.com/
    The place where fun never ends

  37. 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…

  38. 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

  39. I know there is a function to get the number of cameras:

    cvcamGetCamerascount()

    Maybe that helps?

  40. 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

  41. That's Linux-specific of course, but will indeed do the trick.

  42. 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

Leave a Reply

Your email address will not be published. Required fields are marked *