OpenCV - Face Recognition using LBPH Classifier in C++

Hurry Up !! Check Out Todays Deal

OpenCV - Face Recognition using LBPH Classifier in C++

We learned HOW TO RECOGNIZE FACES in my OpenCV tutorial. Now, as shown below, we will gather and use our own data to recognize different faces using LBPH:

Face Recognition
Face Recognition

To complete a Face Recognition project, we must work on three distinct phases:

  • Face Recognition and data collection
  • Train the recognizer.
  • Recognition of Faces

The following block diagram summarises those phases:

facerecognition

Face Recognition and Data Collection

In our last tutorial we have seen how to recognize faces in the given photo using Cascade Classifier. In this tutorial we will go one step further.

That is we will give our algorithm different images and we will extract the faces from the images and store it in some variable for our next step.

Here the input image which we will provide will be out dataset. Here you can give any person images but in our case I have given images of famous celebrities Alexandra Daddario and Scarlett Johansson.

Directory Structure is as follows:

./datasets alexandra-daddari-0/ img1 img2 img3 scarlet-johansson-1/ img1 img2 img3

Extracting Faces from images:

cv::CascadeClassifier classifier; int extractfaces(cv::Mat &img, cv::Mat &face) { cv::Mat img_gray; cv::cvtColor(img, img_gray, cv::COLOR_BGR2GRAY); std::vector<cv::Rect> features; classifier.detectMultiScale(img, features); /* Under Assumption that image consist of only single face */ if (features.size() > 0) { face = img_gray(features[0]); return 1; } else return 0; }

Train the Recognizer

After extracting faces from the images we will train those images. For this Opencv provide us with a wonderfull algorithm called Local Binary Pattern Histogram(LBPH) Face-Recognition algorithm.It is well-known for its performance and ability to recognise a person's face from both the front and side faces.

To know how LBPH Face Algorihtm Work read this.

cv::Ptr<cv::face::LBPHFaceRecognizer> model = cv::face::LBPHFaceRecognizer::create(); void train_dataset(const std::string &in_dir) { std::cout << "Starting To Train Dataset...\n"; std::vector<int> faceIds; std::vector<cv::Mat> faceSamples; for (const auto &file : std::filesystem::directory_iterator(in_dir)) { std::string label = file.path().filename(); std::cout << "Images in directory: " << label << "...\n"; /*Directory Format: dir_name_0 ,dir_name_1 */ int faceID = std::stoi(label.substr(label.rfind("_") + 1, label.size())); for (const auto &f : std::filesystem::directory_iterator(file.path())) { cv::Mat src, face; std::cout << f << "\n"; src = cv::imread(f.path()); if (extractfaces(src, face)) { faceSamples.emplace_back(face); faceIds.emplace_back(faceID); } } model->train(faceSamples, faceIds); std::cout << "Done!!\n"; } std::cout << "Training Datasets Done !! \n"; }

Here faceSamples variable stores faces and faceID variable is refrence to whoes face it belongs to i.e. 0 means that face is of Alexandra Daddario and 1 means face is of Scarlett Johansson.

Recognition of Faces

After our classifier(LBPH) is trainned enough images it's time to test our model.

For this just create a test directory and put the images which you want to test. In testing phase once again we will extract faces from our test image and then feed it to our model for pridiction.

void test_dataset(const std::string &in_dir) { std::cout << "Testing Datasets... \n"; const std::vector<std::string> names = { "Alexender Dadario", "Scarlet Johanson"}; // Arrange name according to // directory in train_dataset for (const auto &file : std::filesystem::directory_iterator(in_dir)) { cv::Mat src = cv::imread(file.path()); cv::Mat face; extractfaces(src, face); int predictedLabel = -1; double confidence = 0.0; model->predict(face, predictedLabel, confidence); std::cout << predictedLabel << "\n"; /* If No Match Found prediction will be -1 */ if (predictedLabel != -1) { cv::putText(src, names[predictedLabel], cv::Point(10, src.rows / 2), cv::FONT_HERSHEY_DUPLEX, 1.0, CV_RGB(118, 185, 0), 1); cv::imshow(file.path().filename(), src); std::cout << "File: " << file.path().filename() << "\nPrediction: " << names[predictedLabel] << "\nConfidence: " << confidence << "\n\n\n"; } else { cv::putText(src, "Match Not Found", cv::Point(10, src.rows / 2), cv::FONT_HERSHEY_DUPLEX, 1.0, CV_RGB(118, 185, 0), 1); cv::imshow(file.path().filename(), src); std::cout << "File: " << file.path().filename() << "Prediction: Unknown To Model" << "\n"; } } }

Output

Output 1
Output 1

Output 2
Output 2

References

Code

#include "opencv2/face.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" #include <cassert> #include <filesystem> #include <iostream> #include <vector> cv::CascadeClassifier classifier; cv::Ptr<cv::face::LBPHFaceRecognizer> model = cv::face::LBPHFaceRecognizer::create(); int extractfaces(cv::Mat &img, cv::Mat &face) { cv::Mat img_gray; cv::cvtColor(img, img_gray, cv::COLOR_BGR2GRAY); std::vector<cv::Rect> features; classifier.detectMultiScale(img, features); /* Under Assumption that image consist of only single face */ if (features.size() > 0) { face = img_gray(features[0]); return 1; } else return 0; } void train_dataset(const std::string &in_dir) { std::cout << "Starting To Train Dataset...\n"; std::vector<int> faceIds; std::vector<cv::Mat> faceSamples; for (const auto &file : std::filesystem::directory_iterator(in_dir)) { std::string label = file.path().filename(); std::cout << "Images in directory: " << label << "...\n"; /*Directory Format: dir_name_0 ,dir_name_1 */ int faceID = std::stoi(label.substr(label.rfind("_") + 1, label.size())); for (const auto &f : std::filesystem::directory_iterator(file.path())) { cv::Mat src, face; std::cout << f << "\n"; src = cv::imread(f.path()); if (extractfaces(src, face)) { faceSamples.emplace_back(face); faceIds.emplace_back(faceID); } } model->train(faceSamples, faceIds); std::cout << "Done!!\n"; } std::cout << "Training Datasets Done !! \n"; } void test_dataset(const std::string &in_dir) { std::cout << "Testing Datasets... \n"; const std::vector<std::string> names = { "Alexender Dadario", "Scarlet Johanson"}; // Arrange name according to // directory in train_dataset for (const auto &file : std::filesystem::directory_iterator(in_dir)) { cv::Mat src = cv::imread(file.path()); cv::Mat face; extractfaces(src, face); int predictedLabel = -1; double confidence = 0.0; model->predict(face, predictedLabel, confidence); std::cout << predictedLabel << "\n"; /* If No Match Found prediction will be -1 */ if (predictedLabel != -1) { cv::putText(src, names[predictedLabel], cv::Point(10, src.rows / 2), cv::FONT_HERSHEY_DUPLEX, 1.0, CV_RGB(118, 185, 0), 1); cv::imshow(file.path().filename(), src); std::cout << "File: " << file.path().filename() << "\nPrediction: " << names[predictedLabel] << "\nConfidence: " << confidence << "\n\n\n"; } else { cv::putText(src, "Match Not Found", cv::Point(10, src.rows / 2), cv::FONT_HERSHEY_DUPLEX, 1.0, CV_RGB(118, 185, 0), 1); cv::imshow(file.path().filename(), src); std::cout << "File: " << file.path().filename() << "Prediction: Unknown To Model" << "\n"; } } } int main(int argc, char **argv) { if (argc < 3) { std::cout << "!! ERROR !!!\n"; std::cout << "<Program> <DatasetFolder> <Test Folder>\n"; return -1; } std::cout << "Loading Haarcascade File ...\n"; assert(classifier.load("haarcascade_frontalface_alt.xml")); std::cout << "Done!!\n"; train_dataset(argv[1]); test_dataset(argv[2]); cv::waitKey(0); return 0; }

Realate Post


OpenCV - Understanding Convex Hull using C++

OpenCV - Understanding Convex Hull using C++

A tutorial on determining a shape's or a group of points' Convex Hull. The OpenCV code implementation in C++ and Python is shared.


Javascript String Methods Cheat Sheet 2021

Javascript String Methods Cheat Sheet 2021

When programming in JavaScript, you often come across scenarios that require string manipulation. For example, when retrieving email , you may need to convert all characters to lowercase or use regular expressions to check if the entered password meets conditions.


OpenCV - Removing Background from an image using GrabCut algorithm(C++)

Understand React Stateful and Stateless components

Understand React Stateful and Stateless components

It this blog we will look at difference between react stateful and stateless components


OpenCV - Fill Contour using C++

OpenCV - Fill Contour using C++

Fill contour using c++


Another Techs


© 2022 Another Techs. All rights reserved.