Face Detection in 10 lines for Beginners | by That Data Bloke | Towards Data Science

I was recently exploring the Haar Cascade object detection module of the OpenCV for a personal side project. Although there are a lot of technical materials on the internet in this area, my focus on this article is to explain the concepts in easy layman’s terms. I hope this will help the beginners in understanding Python’s OpenCV library in a simple manner.
In this demo, we will take an image and search for human faces in it. We are going to use a pre-trained classifier to perform this search. I plan on sharing some more articles on how we can train our own models in future. But for now, let’s get started using a pre-trained model.
For the uninitiated, OpenCV is a Python library which is mainly used in various computer vision problems.
Here, we are using the “haarcascade_frontalface_default.xml” as our model from the opencv github repository. You can download this xml file and place it in the same path as your python file. There are also a bunch of other models here that you might want to try out later (Eg:- eye detection, full body detection, cat face detection etc.)
Let’s take a look at a high level flow of the program before jumping into the code.
The algorithm requires two inputs:
Input Image matrix(we will read an image and convert it into a matrix of numbers/numpy array)The face features (available in the haarcascade_frontalface_default.xml file)
Input Image matrix(we will read an image and convert it into a matrix of numbers/numpy array)
The face features (available in the haarcascade_frontalface_default.xml file)
OpenCV’s Haar Cascade classifier works on the sliding window approach. In this method, a window (default size 20 by 20 pixels) is slid over the image (row by row) to look for the facial features. After each iteration the image is scaled down (resized) by a certain factor (determined by the parameter ‘scaleFactor’). The outputs of each iteration is stored and the sliding operation is repeated on the smaller, resized image. There could be false positives during the initial iterations which is discussed in a bit more detail later in this article. This scaling down and windowing process continues until the image is too small for the sliding window. The smaller the value of scaleFactor, greater the accuracy and higher the computation expenses.
Our output image will contain a rectangle around each of the detected faces.
Code & Explanation :
Let’s get started with the python code. We will require the following Python packages for this experiment:
pip install numpypip install opencv-python
Let’s call our python file ‘face_detector.py’ and place it in the same path as our xml file downloaded from the github link shared above.
# File Name: face_detector.py# Import the OpenCV libraryimport cv2
Now let’s looks at the promised 10 lines !
We prepare the 2 inputs [input image & face features xml]shown in the flow diagram above in the below section.
I am using this beautiful photograph by Bess Hamiti(link below) as my input image (kids.jpg).
1We begin by loading our xml classifier and the input image file. Since the input file is quite large, I have resized with approx dimensions similar to the original resolution, so that they don’t appear stretched. Then, I have converted the image into a gray scale image. The gray scale image is believed to improve the efficiency of the algorithm.
face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")image = cv2.imread("kids.jpg")image = cv2.resize(image, (800,533))gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
The image read is stored as a multidimensional numpy array, as shown below.
print(type(gray_image))<class 'numpy.ndarray'>
In the next step, we pass the gray_image as an input to the detectMultiScale method.
The detectMultiScale method is the one that will perform the detection for us. It takes the following parameters:
scaleFactor : This parameter specifies the factor by which the image is scaled down, eg:- if this value is 1.05, then the image is scaled down by 5%. If this value is 1.10, then the image is scaled down by 10%. A scaleFactor of 1.10 will require less computation than a scaleFactor of 1.05.
minNeighbors : It is a threshold value that specifies how many neighbors each rectangle should have in order for it to be marked as true positive. In other words, let’s assume that each iteration marks certain rectangles (i.e. classifies a part of the image as a face). Now, if the subsequent iterations also mark the same areas as a positive, it increases the possibility of that rectangle area to be a true positive. If a certain area is identified as a face in one iteration, but not in any other iteration, they are marked as false positives. In other words, minNeighbors is the minimum number of times a region has to be determined as a face.
Let’s perform an experiment to understand it better. We will run our code with different values for minNeighbors parameter.
For minNeighbors = 0,
All the rectangles are being detected as faces. For some rectangles, there are lots of overlapping rectangles, which signifies that those have been detected as positives during multiple iterations. We set the threshold to increase the accuracy of the algorithm.
minNeighbors = 2
With minNeighbors = 2, most of the overlapping rectangles are no longer present. However, we still have a few false positives.
If we increase this threshold to 4 or 5, we can see that there aren’t any more false positives. Let’s set this value to 5 and proceed further.
faces=face_cascade.detectMultiScale(gray_image,scaleFactor=1.10,minNeighbors=5)
The detectMultiScale method returns a numpy array with dimensions and positions of the rectangles containing the faces.
x,y — position of the top left corner of the rectangle
w, h — width and height of the rectangle
We now draw a rectangle with these dimensions in green color (0, 255, 0) (BGR color code) with the border thickness = 1.
The window waits for 2 seconds (2000 milliseconds) and closes automatically.
for x,y,w,h in faces:    image=cv2.rectangle(image, (x,y), (x+w, y+h), (0, 255, 0),1)    cv2.imshow("Face Detector", image)    k=cv2.waitKey(2000)cv2.destroyAllWindows()
Alternately, we can also save the image by adding the below line.
cv2.imwrite("kids_face_detected.jpeg", image)
Our output image now contains a green rectangle around each of the detected faces.
I hope this article leaves you with a basic understanding of how to do face detection using OpenCV in python. We can extend this code to track a face in a video as well. I have uploaded the full code discussed above and for tracking faces in a live webcam video in my GitHub repository here, in case you are interested. Have a great day ahead!
medium.com
towardsdatascience.com
medium.com
References & Further Reading:
[1]Cascade Classifier, https://docs.opencv.org/2.4/modules/objdetect/doc/cascade_classification.html
[2] 5KK73 GPU Assignment, https://sites.google.com/site/5kk73gpu2012/assignment/viola-jones-face-detection
[3] OpenCV Github page, https://github.com/opencv/opencv/tree/master/data/haarcascades