Introduction
Detecting
a face in digital image is simply a way to find pixels location
containing face pattern in it. Examples of this application resides
in our smart-phone camera that has an ability to detect face in
captured frame, security system that many applied in CCTV (Closed
Circuit Television) system, and Marketing field (but this is still
rarely found). One thing needed to remember is that the term of ‘face
detection’ is different from ‘face recognition’ that the latter
means a system can identify ‘whose’ person of any face detected,
while the former means a system just ‘point out’ a face in an
image – without knowing ‘who’ is he or she’. For this post,
C++ programming language will be used to detect a face in an image.
see post equivalent in python programming language:
see post equivalent in python programming language:
Prerequisites
In
this post, bellow prerequisites are assumed have been installed on
your system
- OpenCV 4.1.1 library or latter
- C++ compiler and Cmake
- Your favorite text editor
Codes
Before
going into the code, we need to prepare these files first:
lena.jpg
(the image that we use to test), and
haarcascade_frontalface_alt.xml
(the trained classifier for detection ‘utility’)
The
two files mention above has been there in OpenCV directory you
installed, just find them on your OpenCV installation directory. In
my computer the xml file is in
installation/OpenCV-4.1/share/opencv4/haarcascades, and for the image
you can save the lena.jpg image from this post (in figure 1).
Figure 1. Our image lena.jpg (source: OpenCV org) |
Headers
and Namespaces
So
the first thing to do in C++ code is to ‘include’ the directory
where any function we use refers
#include <opencv4/opencv2/highgui.hpp>
#include <opencv4/opencv2/imgproc.hpp>
#include <opencv4/opencv2/objdetect.hpp>
#include <iostream>
using namespace std;
using namespace cv;
The
two namespaces cv and std are deliberately declared
global since the size of our code that is short enough to fit on a pc
screen. Bellow lines are some functions that we are going to use
referring to our header above:
...highgui.hpp:
namedWindow()
imread()
imshow()
...imgproc.hpp:
cvtColor()
equalizedHist():
rectangle()
…
and
other classes and member functions reside in objdetect.hpp file.
Within
main() function
The
first thing to do is to give our window a name and read an image
(lena.jpg)
namedWindow("face_detect");
Mat im = imread("../lena.jpg");
vector<Rect> faces;
Mat frame_gray;
cvtColor(im,frame_gray,COLOR_BGR2GRAY);
equalizeHist(frame_gray,frame_gray);
The
image that we give to CascadeClassifier instances latter need to be
in gray-scale mode. This is achieved by cvtColor() function above
-The first and the second argument are for input and output image
respectively, while the last argument is color space conversion code
flag.
To
be well detected, equalizeHist() function is usually used to equalize
the histogram for the frame / image given, decreasing ‘dark’
pixels value to balance all other pixels, or simply to brighten a
dark image.
The
image file ‘../lena.jpg’ - the ‘../’ indicates that our image
that is going to be compiled is outside of our buid directory.
Find
Face Location
This is where a face location in an image is found. In other words
the face detection process happens in these lines of code bellow:
CascadeClassifier face_cascade;
if( !face_cascade.load("../haarcascade_frontalface_alt.xml") )
{
cout<<"--(!)Error loading face cascade\n";
return -1;
}
face_cascade.detectMultiScale(frame_gray,faces);
The first thing we need to do, is to make an instance of
CascadeClassifier class, then continued to load our
haarcascade_frontalface_alt.xml file
using load() method of the
instance. The following code
is to check whether the file we load exists or not, the load() method
will be false if the file
exists or true
otherwise.
The next line is where face
detection happens by using detectMultiscale() method of the instance.
According to OpenCV reference manual, it states that the method detects
object of different size in the input image and the detected object
are returned as a list of rectangles.
For the first and the second argument of this methods are input and
output images respectively. Note that the output is in form of a list
of rectangle that we need to declare ‘face’ variable as
vector<Rect> above.
Signifying Face Detected
So far, we have detected the face object or the location of the pixel
has been found. Therefore it will be meaningless if the frame which
will be shown doesn’t give any information about where the pixel
(or face location) is in the image. The bellow code will give a red line rectangle that surrounds our lena.jpg face image, and then
showing the image with a face detected on computer screen.
for(size_t i = 0; i < faces.size(); i++ )
rectangle(im,faces[i],Scalar(0,0,255),2);
imshow("face_detect",im);
while(static_cast<unsigned char>(waitKey(0)) != 'q');
the for() loop expression above just counts and processes how many
face of the image detected. The face.size() return value is in
form of unsigned integer that indicates the number of face
detected on the image. Within the for() loop statement, we use
rectangle() function to draw a red rectangle of our
face-detected image. The first and the second arguments are for input
and output image respectively; the face[i] just states which
face is going to draw in the container (vector<Rect>) index,
because in this case we just have a single face in the image, the
for() loop just steps once, i.e., facep[0]. And the
last two arguments are for color of the rectangle line and the
‘thickness’ of the line respectively. For the Scalar(0,0,255)
will cause our rectangle color red, because the it is in BGR format.
You can try to experiment with other values with this function.
And for the last following two lines are to show the image on our
computer screen and wait a ‘q’ key to be pressed (to terminate
the program) respectively.
When the code is run, the output will be like on the figure 2.
Figure 2. Face detected surrounded by a red line (rectangle) |
For the complete code and cmake file, find it here:
Conclusion
Detecting a face in an image is relatively easy to do especially for
a beginner who just start to learn. Since almost all necessary
functions/methods and “stuffs” has been prepared by OpenCV
library, like one we use haarcascade_frontalface_alt.xml file
and some methods and classes that support it. There are also so many
trained cascade file that you can find out there, like on github,
such as banana, dog, cat many other else trained files detector. Just have fun with it.
0 Comments
Post a Comment