In [ ]:
%pylab inline
In [ ]:
import sys,os,re,time
import urllib

import numpy as np

from IPython import parallel

First, initialize OpenCV for simple facial detection

In [ ]:
HAAR_CASCADE_PATH = "haarcascade_frontalface_default.xml"
# if you have opencv installed via homebrew, this would be in
# /usr/local/share/OpenCV/haarcascades/

import cv
storage = cv.CreateMemStorage()
cascade = cv.Load(HAAR_CASCADE_PATH)

Then define a few functions for extracting faces from images

In [ ]:
def extract_faces(image, faces):
    """Returns any faces in an image in a list of numpy arrays"""
    import numpy as np
    A = np.frombuffer(image.tostring(), dtype=np.uint8).reshape((image.height, image.width, image.nChannels))
    A = A[:,:,::-1]
    face_arrays = []
    for face in faces:
        Aface = A[face[1]:face[1]+face[3],face[0]:face[0]+face[2]]
        face_arrays.append(Aface)
    return face_arrays


def detect_faces(filename):
    """Loads an image into OpenCV, and detects faces

    returns None if no image is found,
    (filename, [list of numpy arrays]) if there are faces
    """
    
    image = cv.LoadImage(filename)
    faces = []
    detected = cv.HaarDetectObjects(image, cascade, storage, 1.2, 2, cv.CV_HAAR_DO_CANNY_PRUNING, (100,100))
    if detected:
        for (x,y,w,h),n in detected:
            faces.append((x,y,w,h))
    if faces:
        return filename, extract_faces(image, faces)

Since we don't trust the network, we can just build a list of images from anywhere on our filesystem. Any list of images will do. For instance, you can use the path to the 'Thumbnails' directory in your iPhoto library, which from ~320x240 - 1024x768.

In [ ]:
pictures_dir = 'images'

This will search pictures_dir for any jpegs.

See the Downloading images from flickr notebook for a quick way to populate a folder with images from flickr with a certain tag.

In [12]:
import glob
pictures = []
for directory, subdirs, files in os.walk(pictures_dir):
    for fname in files:
        if fname.endswith('.jpg'):
            pictures.append(os.path.join(directory, fname))
len(pictures)
Out[12]:
480

Let's test our output

In [13]:
for p in pictures:
    found = detect_faces(p)
    if found:
        break

filename, faces = found
for face in faces:
    plt.figure()
    plt.imshow(face)

Hey, that looks like a face!

Now in parallel

First, we connect our parallel Client

In [14]:
rc = parallel.Client()
all_engines = rc[:]
view = rc.load_balanced_view()

Then we initialize OpenCV on all of the engines (identical to what we did above)

In [15]:
%%px
HAAR_CASCADE_PATH = "haarcascade_frontalface_default.xml"

import cv
storage = cv.CreateMemStorage()
cascade = cv.Load(HAAR_CASCADE_PATH)

and make sure extract_faces is defined everywhere

In [16]:
all_engines.push(dict(extract_faces=extract_faces))
Out[16]:
<AsyncResult: _push>

Now we can iterate through all of our pictures, and detect and display any faces we find

In [17]:
tic = time.time()

amr = view.map_async(detect_faces, pictures[:1000], ordered=False)
nfound = 0
for r in amr:
    if not r:
        continue
    filename, faces = r
    nfound += len(faces)
    print "%i faces found in %s" % (len(faces), filename)
    for face in faces:
        plt.imshow(face)
        plt.show()

toc = time.time()

print "found %i faces in %i images in %f s" % (nfound, len(amr), toc-tic)
1 faces found in images/portrait/8572134659_26bf7fe973_m.jpg
1 faces found in images/portrait/8572301213_ccfcac5ed6_m.jpg
1 faces found in images/portrait/8565053833_79c5e83862_m.jpg
1 faces found in images/boy/8568678503_187c2f6385_m.jpg
1 faces found in images/boy/8569518192_e0214a511d_m.jpg
1 faces found in images/face/8564623958_0dbcd1c770_m.jpg
1 faces found in images/face/8566602623_a6b8ddd2a2_m.jpg
1 faces found in images/boy/8568418749_fdac679393_m.jpg
1 faces found in images/boy/8569778086_9faa7a7e7a_m.jpg
1 faces found in images/boy/8568680957_7943230365_m.jpg
1 faces found in images/boy/8568528841_f7a7f0bbc9_m.jpg
1 faces found in images/face/8568683430_0d46eef747_m.jpg
1 faces found in images/boy/8569777590_76f6553518_m.jpg
1 faces found in images/boy/8569777000_2172eec5e1_m.jpg
1 faces found in images/face/8564762406_fdbd3360cd_m.jpg
1 faces found in images/face/8567518326_d3fe82d2dd_m.jpg
1 faces found in images/face/8562525798_6e2595dd4d_m.jpg
1 faces found in images/girl/8572134659_26bf7fe973_m.jpg
1 faces found in images/face/8569218469_36c5b5ba00_m.jpg
1 faces found in images/girl/8571917735_0e7785631f_m.jpg
1 faces found in images/girl/8571917117_2663eaa139_m.jpg
found 21 faces in 480 images in 5.779426 s
In [ ]: