Face Detection Using Skin Tone Threshold(RGB-YCrCb): Python Implementation.

This post explains how can we take advantage of the skin segmentation algorithm, described in my first article, and how can we use it in face detection.

Mahmoud Harmouch
The Startup

--

Face-Detection

What Is Face Detection?

Face Detection is the act of finding and extracting a face from any given image, video, webcam… based on some specific features (skin color, nose, eyes, mouth…). This method is used in a program for recognizing a face(see if is it familiar or not familiar face) and performed by using the color segmentation of the image. To do so, python provides us a useful function: cv2.findContours.

findContours function.

Using the OpenCV library, you can extract the contour of an image. The function, which accomplishes this purpose, is, as the title suggests, find contours, which has the following syntax:

contours, hierarchy=cv2.findContours(image, mode, method[,contours[, hierarchy[, offset]]])

1- Image: An 8-bit binary picture, in which we want to find the contours.

2- Mode: one of the four modes:

  • Cv2. RETR _EXTERNAL:

Extract only the outermost contour. If there a contour inside, it will be ignored. The outermost matrix of the image is not extracted as a contour.

outermost contour(cont1)

output:

[array ([[[1, 1]],[[1, 9]],[[2, 9]],[[3, 8]],[[5, 8]],[[5, 9]],[[10, 9]],[[10, 1]],[[6, 1]],[[5, 2]],[[4, 2]],[[3, 1]],[[2, 1]]])]

As you can see, each point of the contour is represented as [[x, y]] and the output contains only one array (cont1), and the cont2 has been ignored. The order of detection is counterclockwise in the direction of y increase if x is fixed, and in the direction of x increasing if y is fixed.

Since I want to detect the outermost contour, so I will use this mode in my program. For more info about the other modes, you can check out on OpenCv docs

3- Method: There are three methods for packaging contours:

a- Cv2.CHAIN_APPROX_SIMPLE - join all horizontal, vertical and diagonal contours;

b- Cv2.CHAIN_APPROX_TC89_L1, CV_CHAIN_APPROX_TC89_KCOS -Applies the Teh-Chin packing method;

c- cv2.CHAIN_APPROX_NONE — no packaging and all contours are stored as segments consisting of two pixels;

Therefore, while reading these options, it is obvious to choose cv2.CHAIN_APPROX_SIMPLE method.

For the sake of simplicity, I am good with these three parameters because it will do the job very well.

4- Return values:

contours : a list of all found contours represented as a matrix
hierarchy : information about the topology of the contours.

In this project, our purpose is to draw a rectangle around faces. So the idea is to take advantage of the findContours and boundingRect methods which give us the base x, y coordinates, and width, height for a given contour(top left and bottom right points).

x, y, w, h = cv2.boundingRect(contours)# contours is an array list of contours

According to the documentation:

we have two options:

  1. Straight rectangle.
  2. Rotated rectangle.

Since we want to draw straight lines around a face, we need to choose the straight rectangle method.

Python code:

draw contour

Running the above piece of code, the program will draw the contour image:

contour

Now, our goal is to draw a rectangle around this contour with the help of the boundingRect method which will draw a Straight rectangle.

the previous code will return the coordinates of the face like the following image:

Face Detection In Video

we can improve our program to detect faces in a given video.

face detection in video

The idea is to extract a frame from a provided video for each iteration of the while loop, and apply the previous procedure to get the coordinates of the face in that frame. But, at the same time, we need to take into consideration the frame rate, which is, at the input, equal to fps(30 frames/sec). so to solve this problem, and get a smooth transition between the frame, we need to estimate the processing time from the first iteration of the loop till the last one.

At this point, you need to pause the python iterator for (1/fps- (finish - start)) sec. By doing that, we are ensuring a 30 fps as the input frame rate.

scale_factor is used to resize the image to quickly compute the coordinates of the face.

frame rate

Conclusion

In my opinion, Skin segmentation is one of the most powerful techniques that can be used for face detection while maintaining good performance and a higher frame rate.

If you like my project, please check out my repo for source code, and feel free to fork it and make pull requests providing your changes on it, I will appreciate that!

--

--

Mahmoud Harmouch
The Startup

Senior Blockchain Rust Enjoyer at GigaDAO - I occasionally write articles about data science, machine learning and Blockchain in Rust - Currently Writing Books