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, Java programming language will be used to detect a face in an image.


Prerequisites
In this post, bellow prerequisites are assumed have been installed on your system

  • OpenCV 4.1.1 library or latter
  • Java – JDK 1.8
  • Your favorite text editor or IDE, such as Eclipse, Netbeans, or etc. Here Vim text editor with Ant to coplile

Codes
Before going through the code, we need to prepare these files first:
lena.jpg (the image that we use to test our program), 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)

After the files above we have, the next thing to do is to make a file named FaceDetect.java and followed by the steps bellow.

Note that in this post, I am going to explain the code by parts, which means you can copy the code per parts until the end, and therefore can compile all parts in a file named FaceDetect.java.

Post related:


Modules Imported
So here we go, in the file that we have made above just copy the following imported module to the file. In Java, any module name – where any class resides in the module - is usually ‘imported’ first before we can use the class. Hence Bellow are modules we need to import:
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.highgui.HighGui;
import org.opencv.core.MatOfByte;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.core.MatOfRect;
import org.opencv.core.Rect;
import org.opencv.core.Point;
import org.opencv.core.Scalar;

All the module reside in org.opencv.


Main Class
The next step is to provide our main class.

public class FaceDetect{

… //our next code lines continue here

}

note that the class name must be the same name as the file name. A compilation error for this type of different name


Within FaceDetect Class
To be able to use OpenCV library in java, the first thing we need to do is to load all the native libraries with this line of code:


static{ System.loadLibrary(Core.NATIVE_LIBRARY_NAME); }

this line of code can be put inside or outside main() function. For this case, I prefer the former, putting it outside the main function.

public static void main(String[] args){

… //our next code lines continue here

}



Within main() Function
The first thing to do is to give our window a name and read an image (lena.jpg)

String image_path = new String(“/path/to/lena.jpg”);
Mat im = Imgcodecs.imread(image_path);
Mat im_gray = new Mat();
Imgproc.cvtColor(im,im_gray, Imgproc.COLOR_BGR2GRAY);
Imgproc.equalizeHist(im_gray,im_gray);

The image that we give to CascadeClassifier instance latter needs 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.


Finding Face Location
This is where face location in an image is found. In other words the face detection process happens in these lines of code bellow:

String cascade_path = new String(“/path/to/haarcascade_frontalface_alt.xml”);
CascadeClassifier classifier = new CascadeClassifier(cascade_path);
MatOfRect faceDetections = new MatOfRect();
classifier.detectMultiScale(im_gray, faceDetections);

First we need to identify the haarcascade_frontalface_alt.xml file path tusing String instance, here the name of the instance is cascade_path where we pass the path directly through the String constructor.

Next, we make an instance of CascadeClassifier class by passing a constructor argument cascade_path that we have declared above. By doing that, the haarcascade_frontalface_alt.xml file is automatically loaded.

The next two lines are where face detection happens by using detectMultiscale() method of the instance. According to OpenCV reference manual, it state that the method detects object of different size in the input image and the detected object are returned as a list of rectangles. Therefore, we need the MatOfRect instance to be able to do that.

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 have provided it by faceDetections instance.


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 blue line rectangle that surrounds our lena.jpg face image, and then showing the image with a face detected on computer screen.

for (Rect rect : faceDetections.toArray()) {
   Point blPoint = new Point(rect.x,rect.y);    //bottom-left point
   Point trPoint = new Point(rect.x + rect.width,rect.y + rect.height); //top-ri
   Scalar imgColor = new Scalar(255,0,0,0);     //green color

   Imgproc.rectangle(im,blPoint,trPoint,imgColor,3); 
}

the for() loop expression above just counts and processes how many face of the image detected. Within the for() loop statement, we use rectangle() function to draw a blue rectangle of our face-detected image. The first im argument is for input image, the next second and third arguments, blPoint and trPoint are for bottom-left point and top-right point respectively. These two arguments are for area of our rectangle with its start and end point. The last two arguments (but not least), imgColor and 3 are for color and line size of a rectangle surrounding the face.

Note that for the Scalar(0,0,255) will cause our rectangle blue, because the it is in BGR format. You can try to experiment with other values with this function.


Showing the Image Result and Waiting for a ‘Q’ Key
As all the face detecting operation is done, the next thing is to show the result using the imshow() method and waiting ‘Q’ key to be pressed to exit the program and closing the window.

HighGui.imshow("FaceDetect",im);
while((char)HighGui.waitKey(0) != 'Q');
HighGui.destroyAllWindows();
System.exit(0);

When the code is run, the output will be like on the figure 2.
Figure 2. Face detected surrounded by a red line (rectangle)


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 them.