This post is about face recognition (=matching a face against a set of known faces), not face detection (=finding a face in an image). For more information on the difference between the two, have a look at this ppt: http://www.ee.pdx.edu/~mperkows/class_4 ... nition.ppt
I recently started looking into OpenCV's face recognition capabilities for a project of mine and found that whilst information is available on numerous websites and the OpenCV documentation, it is either too abstract or too scientific for someone who just wants to whip up a quick script to do face recognition. Hence why I decided to write this tutorial.
To create a simple Python application that takes an image and then runs OpenCVs Eigenfaces face recognition algorithm against it - returning the ID of the recognized face plus a confidence level.
We're going to use Python and require the following modules to be installed (via sudo apt-get install *modulename*):
- libatlas-dev (not sure, but can't hurt)
- libatlas3gf-base (not sure either)
In order to run face detection, we need a database of faces to recognize. I used the AT&T Face Database (http://www.cl.cam.ac.uk/research/dtg/at ... abase.html). It contains 40 folders (one folder per subject s) with 10 92x112px grayscale images of that subject's face. The directory structure looks like this::
I recommend deleting folders s11 to s40 in order to increase computation speed.
You of course also need to set up a folder for the face you want to detect (e.g. yourself). Call that s99 and put 10 pictures (format irrelevant, I used JPG) of yourself into it (92x112, grayscale, different light settings etc).
The code to run the face recognition is now rather simple. It can be broken down into the following steps:
- Load flattened training images into array
- Perform principal component analysis on the training images
- Load test image(s)
- Perform principal component analysis on training image(s)
- Calculate euclidian distance from test image to each training image and pick result with the smallest distance (=recognized face)
Code: Select all
from sklearn.decomposition import RandomizedPCA import numpy as np import glob import cv2 import math import os.path import string #function to get ID from filename def ID_from_filename(filename): part = string.split(filename, '/') return part.replace("s", "") #function to convert image to right format def prepare_image(filename): img_color = cv2.imread(filename) img_gray = cv2.cvtColor(img_color, cv2.cv.CV_RGB2GRAY) img_gray = cv2.equalizeHist(img_gray) return img_gray.flat IMG_RES = 92 * 112 # img resolution NUM_EIGENFACES = 10 # images per train person NUM_TRAINIMAGES = 110 # total images in training set #loading training set from folder train_faces folders = glob.glob('train_faces/*') # Create an array with flattened images X # and an array with ID of the people on each image y X = np.zeros([NUM_TRAINIMAGES, IMG_RES], dtype='int8') y =  # Populate training array with flattened imags from subfolders of train_faces and names c = 0 for x, folder in enumerate(folders): train_faces = glob.glob(folder + '/*') for i, face in enumerate(train_faces): X[c,:] = prepare_image(face) y.append(ID_from_filename(face)) c = c + 1 # perform principal component analysis on the images pca = RandomizedPCA(n_components=NUM_EIGENFACES, whiten=True).fit(X) X_pca = pca.transform(X) # load test faces (usually one), located in folder test_faces test_faces = glob.glob('test_faces/*') # Create an array with flattened images X X = np.zeros([len(test_faces), IMG_RES], dtype='int8') # Populate test array with flattened imags from subfolders of train_faces for i, face in enumerate(test_faces): X[i,:] = prepare_image(face) # run through test images (usually one) for j, ref_pca in enumerate(pca.transform(X)): distances =  # Calculate euclidian distance from test image to each of the known images and save distances for i, test_pca in enumerate(X_pca): dist = math.sqrt(sum([diff**2 for diff in (ref_pca - test_pca)])) distances.append((dist, y[i])) found_ID = min(distances) print "Identified (result: "+ str(found_ID) +" - dist - " + str(min(distances)) + ")"