{"id":471,"date":"2014-01-23T12:21:13","date_gmt":"2014-01-23T17:21:13","guid":{"rendered":"http:\/\/homepages.uc.edu\/~yaozo\/wordpress\/?p=471"},"modified":"2014-01-23T12:21:13","modified_gmt":"2014-01-23T17:21:13","slug":"fun-with-python-opencv-and-face-detection","status":"publish","type":"post","link":"https:\/\/zhuoyao.net\/index.php\/2014\/01\/23\/fun-with-python-opencv-and-face-detection\/","title":{"rendered":"FUN WITH PYTHON, OPENCV AND FACE DETECTION"},"content":{"rendered":"<p>I had some fun with\u00a0<a href=\"http:\/\/wwwx.cs.unc.edu\/~gb\/wp\/blog\/2007\/02\/04\/python-opencv-wrapper-using-ctypes\/\">Gary Bishop\u2019s OpenCV Python wrapper<\/a>\u00a0this morning. I wanted to try out\u00a0<a href=\"http:\/\/www.intel.com\/technology\/computing\/opencv\/\">OpenCV<\/a>\u00a0for 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\u2019s\u00a0<a href=\"http:\/\/www.python.org\/\">Python<\/a>\u00a0wrapper since I didn\u2019t want to code in C++.<\/p>\n<p>I didn\u2019t know where to start, so I searched for existing OpenCV face detection examples. I found a\u00a0<a href=\"http:\/\/eclecti.cc\/code\/face-detection-on-the-olpc-xo\">blog post by Nirav Patel<\/a>\u00a0explaining how to use OpenCV\u2019s official Python bindings to perform face detection. Nirav will be\u00a0<a href=\"http:\/\/eclecti.cc\/bytes\/the-summer-of-nirav\">working on a webcam module<\/a>\u00a0for\u00a0<a href=\"http:\/\/www.pygame.org\/\">Pygame<\/a>\u00a0for the\u00a0<a href=\"http:\/\/code.google.com\/soc\/2008\/\">Google Summer of Code<\/a>.<\/p>\n<p>I managed to rewrite Nirav\u2019s example to get it working with\u00a0<a href=\"http:\/\/sourceforge.net\/project\/showfiles.php?group_id=82407&amp;%23038;package_id=232299&amp;%23038;release_id=509128\">CVtypes<\/a>:<\/p>\n<p><a href=\"http:\/\/blog.jozilla.net\/wp-content\/uploads\/2008\/06\/cvtypes_face-recognition.png\"><img loading=\"lazy\" decoding=\"async\" title=\"cvtypes_face-recognition\" alt=\"\" src=\"http:\/\/blog.jozilla.net\/wp-content\/uploads\/2008\/06\/cvtypes_face-recognition-500x500.png\" width=\"500\" height=\"500\" \/><\/a><\/p>\n<p>Here\u2019s the code. Although it\u2019s 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\u00a0<a href=\"http:\/\/www.amazon.com\/Logitech-961465-0403-QuickCam-Communicate-Deluxe\/dp\/B000RZSHQM\">Logitech QuickCam Communicate Deluxe<\/a>webcam. You will need Nirav\u2019s\u00a0<a href=\"http:\/\/eclecti.cc\/files\/2008\/03\/haarcascade_frontalface_alt.xml\">Haar cascade file<\/a>\u00a0as well.<\/p>\n<div>\n<table>\n<tbody>\n<tr>\n<td>\n<pre>import sys\nfrom CVtypes import cv\n\ndef detect(image):\n    image_size = cv.GetSize(image)\n\n    # create grayscale version\n    grayscale = cv.CreateImage(image_size, 8, 1)\n    cv.CvtColor(image, grayscale, cv.BGR2GRAY)\n\n    # create storage\n    storage = cv.CreateMemStorage(0)\n    cv.ClearMemStorage(storage)\n\n    # equalize histogram\n    cv.EqualizeHist(grayscale, grayscale)\n\n    # detect objects\n    cascade = cv.LoadHaarClassifierCascade('haarcascade_frontalface_alt.xml', cv.Size(1,1))\n    faces = cv.HaarDetectObjects(grayscale, cascade, storage, 1.2, 2, cv.HAAR_DO_CANNY_PRUNING, cv.Size(50, 50))\n\n    if faces:\n        print 'face detected!'\n        for i in faces:\n            cv.Rectangle(image, cv.Point( int(i.x), int(i.y)),\n                         cv.Point(int(i.x + i.width), int(i.y + i.height)),\n                         cv.RGB(0, 255, 0), 3, 8, 0)\n\nif __name__ == \"__main__\":\n    print \"OpenCV version: %s (%d, %d, %d)\" % (cv.VERSION,\n                                               cv.MAJOR_VERSION,\n                                               cv.MINOR_VERSION,\n                                               cv.SUBMINOR_VERSION)\n\n    print \"Press ESC to exit ...\"\n\n    # create windows\n    cv.NamedWindow('Camera', cv.WINDOW_AUTOSIZE)\n\n    # create capture device\n    device = 0 # assume we want first device\n    capture = cv.CreateCameraCapture(0)\n    cv.SetCaptureProperty(capture, cv.CAP_PROP_FRAME_WIDTH, 640)\n    cv.SetCaptureProperty(capture, cv.CAP_PROP_FRAME_HEIGHT, 480)    \n\n    # check if capture device is OK\n    if not capture:\n        print \"Error opening capture device\"\n        sys.exit(1)\n\n    while 1:\n        # do forever\n\n        # capture the current frame\n        frame = cv.QueryFrame(capture)\n        if frame is None:\n            break\n\n        # mirror\n        cv.Flip(frame, None, 1)\n\n        # face detection\n        detect(frame)\n\n        # display webcam image\n        cv.ShowImage('Camera', frame)\n\n        # handle events\n        k = cv.WaitKey(10)\n\n        if k == 0x1b: # ESC\n            print 'ESC pressed. Exiting ...'\n            break<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>A known problem is that pressing the escape key doesn\u2019t 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\u2019t recognize multiple faces yet, but that might be due to the training data. It would be interesting to experiment with OpenCV\u2019s support for eye tracking in the future.<\/p>\n<p><ins datetime=\"2008-06-28T16:12+01:00\">Update:\u00a0the script\u00a0<em>does<\/em>\u00a0recognize multiple faces in a frame. Yesterday when Alex stood at my desk, it recognized his face as well. I think it didn\u2019t work before because I used\u00a0<code>cv.Size(100, 100)<\/code>\u00a0for the last parameter of\u00a0<code>cv.HaarDetectObjects<\/code>\u00a0instead of\u00a0<code>cv.Size(50, 50)<\/code>. 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\u00d7100 pixels.<br \/>\n<\/ins><\/p>\n<p>Just a quick note on\u00a0<a href=\"http:\/\/docs.python.org\/lib\/module-ctypes.html\">ctypes<\/a>. I remember when I created\u00a0<a href=\"http:\/\/jozilla.net\/software\/pydgetrfid\">PydgetRFID<\/a>that I tried to use libphidgets\u2019\u00a0<a href=\"http:\/\/www.swig.org\/\">SWIG<\/a>-generated Python bindings, but couldn\u2019t get them to work properly. I had read about ctypes, and decided to use it for creating my own wrapper around\u00a0<a href=\"http:\/\/libphidgets.alioth.debian.org\/\">libphidgets<\/a>. Within a few hours I had a working prototype. When you\u2019re struggling with\u00a0SWIG-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\u00a0<a href=\"http:\/\/wwwx.cs.unc.edu\/~gb\/wp\/blog\/2007\/02\/11\/ctypes-tricks\/\">ctypes tricks<\/a>\u00a0to make the process easier.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I had some fun with\u00a0Gary Bishop\u2019s OpenCV Python wrapper\u00a0this morning. I wanted to try out\u00a0OpenCV\u00a0for detecting faces using a web cam. This could be used&hellip; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[],"class_list":["post-471","post","type-post","status-publish","format-standard","hentry","category-computer-vision"],"_links":{"self":[{"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/posts\/471","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/comments?post=471"}],"version-history":[{"count":0,"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/posts\/471\/revisions"}],"wp:attachment":[{"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/media?parent=471"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/categories?post=471"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/zhuoyao.net\/index.php\/wp-json\/wp\/v2\/tags?post=471"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}