- Python 3 Demopack Download
- GeeXLab Downloads
- Forum thread (EN)
For the fourth and last article (previous articles are here, here and here), we’re going to look at face detection using OpenCV. So far, the OpenCV functions we used (image reading, webcam output) are basic functions we find in many softwares inlcuding GeeXLab. What makes OpenCV interesting is the availability of some computer vision algorithms such as face detection (or face recognition).
The face detection method used in the demo is based on the Haar Cascades. If, like me, you are not an expert of Haar cascades, here is what you need to know:
Object Detection using Haar feature-based cascade classifiers is an effective method proposed by Paul Viola and Michael Jones in the 2001 paper, “Rapid Object Detection using a Boosted Cascade of Simple Features”. It is a machine learning based approach in which a cascade function is trained from a lot of positive images (images of faces) and negative images (images without faces). It is then used to detect objects in other images.
More about Haar cascades can be found HERE.
OpenCV comes with pre-trained classifiers for faces and eyes we can use in our demo. These pre-trained classifiers are XML files stored in opencv/data/haarcascades/ folder. In the demo, the classifiers are stored in the demo/data/ folder:
haarcascade_eye_tree_eyeglasses.xml is an eye detector with better handling of eyeglasses.
Once the classifiers (one classifier for faces, one for eyes) are initialized with XML files, they are used in detectMultiScale() function, that performs the detection.
Let see how to initialize the face and eyes classifiers and how to detect faces and eyes on a static image:
import cv2 demo_dir = gh_utils.get_demo_dir() image = cv2.imread(demo_dir + 'data/pexels-people-03.jpg', cv2.IMREAD_COLOR) # Parameter specifying how much the image size is reduced at each image scale. fd_scaleFactor = 1.1 # Parameter specifying how many neighbors each candidate rectangle should have to retain it. fd_minNeighbors = 3 # Initializes classifiers face_cascade = cv2.CascadeClassifier(demo_dir + 'data/haarcascade_frontalface_default.xml') eye_cascade = cv2.CascadeClassifier(demo_dir + 'data/haarcascade_eye_tree_eyeglasses.xml') # detectMultiScale requires an CV_U8 image (gray). gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # Detects objects of different sizes in the input image. # The detected objects are returned as a list of rectangles. image_faces = face_cascade.detectMultiScale(gray_image, fd_scaleFactor, fd_minNeighbors, minSize=(80, 80)) # detect eyes for each face. for (x,y,w,h) in image_faces: roi_gray = gray_image[y:y+h, x:x+w] eyes = eye_cascade.detectMultiScale(roi_gray) for (ex,ey,ew,eh) in eyes: e = (x+ex, y+ey, ew, eh) image_eyes.append(e)
image_faces is a list of rectangles for all faces. image_eyes is a list of lists: list of all face eyes lists (for each face, there is a list of eyes rectangles).
In the FRAME script, faces and eyes rectangles can be rendered as follows for the static image (face and eyes detection is done once for a static image):
num_faces_detected = len(image_faces) if (num_faces_detected > 0): gh_renderer.set_line_width(4.0) gh_gpu_program.bind(color_prog) # Face rectangles --------------------- # for (x,y,w,h) in image_faces: gh_gpu_program.uniform4f(color_prog, "color", 0.2, 0.5, 1.0, 1) draw_rectangle(x-texture_width/2, texture_height/2-y, w, h) if (enable_eyes_detection == 1): num_eyes_detected = len(webcam_eyes) gh_gpu_program.uniform4f(color_prog, "color", 0, 1, 0, 1) # Eye rectangles --------------------- # for e in image_eyes: draw_rectangle(e-texture_width/2, texture_height/2-e, e, e) gh_renderer.set_line_width(1.0)
For a dynamic image like the webcam, faces and eyes detection works in a similar way. The only difference is that detection is launched for every new webcam image.
I prepared a demo that shows faces + eyes detection on a static image and on the webcam output. I also added the possibility to add a hat on detected faces…
Remark: on my system, the demo takes more than 10 seconds to start. The guilty is the webcam initialization step (OpenCV)…
The OpenCV face detector works also with masks: