You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
6.1 KiB
182 lines
6.1 KiB
/* |
|
This file was part of GSoC Project: Facemark API for OpenCV |
|
Final report: https://gist.github.com/kurnianggoro/74de9121e122ad0bd825176751d47ecc |
|
Student: Laksono Kurnianggoro |
|
Mentor: Delia Passalacqua |
|
*/ |
|
|
|
/*---------------------------------------------- |
|
* Usage: |
|
* facemark_demo_lbf <face_cascade_model> <saved_model_filename> <training_images> <annotation_files> [test_files] |
|
* |
|
* Example: |
|
* facemark_demo_lbf ../face_cascade.xml ../LBF.model ../images_train.txt ../points_train.txt ../test.txt |
|
* |
|
* Notes: |
|
* the user should provides the list of training images_train |
|
* accompanied by their corresponding landmarks location in separated files. |
|
* example of contents for images_train.txt: |
|
* ../trainset/image_0001.png |
|
* ../trainset/image_0002.png |
|
* example of contents for points_train.txt: |
|
* ../trainset/image_0001.pts |
|
* ../trainset/image_0002.pts |
|
* where the image_xxxx.pts contains the position of each face landmark. |
|
* example of the contents: |
|
* version: 1 |
|
* n_points: 68 |
|
* { |
|
* 115.167660 220.807529 |
|
* 116.164839 245.721357 |
|
* 120.208690 270.389841 |
|
* ... |
|
* } |
|
* example of the dataset is available at https://ibug.doc.ic.ac.uk/download/annotations/ibug.zip |
|
*--------------------------------------------------*/ |
|
|
|
#include <stdio.h> |
|
#include <fstream> |
|
#include <sstream> |
|
#include <iostream> |
|
#include "opencv2/core.hpp" |
|
#include "opencv2/highgui.hpp" |
|
#include "opencv2/imgproc.hpp" |
|
#include "opencv2/face.hpp" |
|
|
|
using namespace std; |
|
using namespace cv; |
|
using namespace cv::face; |
|
|
|
static bool myDetector( InputArray image, OutputArray roi, CascadeClassifier *face_detector); |
|
static bool parseArguments(int argc, char** argv, String & cascade, |
|
String & model, String & images, String & annotations, String & testImages |
|
); |
|
|
|
int main(int argc, char** argv) |
|
{ |
|
String cascade_path,model_path,images_path, annotations_path, test_images_path; |
|
if(!parseArguments(argc, argv, cascade_path,model_path,images_path, annotations_path, test_images_path)) |
|
return -1; |
|
|
|
/*create the facemark instance*/ |
|
FacemarkLBF::Params params; |
|
params.model_filename = model_path; |
|
params.cascade_face = cascade_path; |
|
Ptr<FacemarkLBF> facemark = FacemarkLBF::create(params); |
|
|
|
CascadeClassifier face_cascade; |
|
face_cascade.load(params.cascade_face.c_str()); |
|
facemark->setFaceDetector((FN_FaceDetector)myDetector, &face_cascade); |
|
|
|
/*Loads the dataset*/ |
|
std::vector<String> images_train; |
|
std::vector<String> landmarks_train; |
|
loadDatasetList(images_path,annotations_path,images_train,landmarks_train); |
|
|
|
Mat image; |
|
std::vector<Point2f> facial_points; |
|
for(size_t i=0;i<images_train.size();i++){ |
|
printf("%i/%i :: %s\n", (int)(i+1), (int)images_train.size(),images_train[i].c_str()); |
|
image = imread(images_train[i].c_str()); |
|
loadFacePoints(landmarks_train[i],facial_points); |
|
facemark->addTrainingSample(image, facial_points); |
|
} |
|
|
|
/*train the Algorithm*/ |
|
facemark->training(); |
|
|
|
/*test using some images*/ |
|
String testFiles(images_path), testPts(annotations_path); |
|
if(!test_images_path.empty()){ |
|
testFiles = test_images_path; |
|
testPts = test_images_path; //unused |
|
} |
|
std::vector<String> images; |
|
std::vector<String> facePoints; |
|
loadDatasetList(testFiles, testPts, images, facePoints); |
|
|
|
std::vector<Rect> rects; |
|
CascadeClassifier cc(params.cascade_face.c_str()); |
|
for(size_t i=0;i<images.size();i++){ |
|
std::vector<std::vector<Point2f> > landmarks; |
|
cout<<images[i]; |
|
Mat img = imread(images[i]); |
|
facemark->getFaces(img, rects); |
|
facemark->fit(img, rects, landmarks); |
|
|
|
for(size_t j=0;j<rects.size();j++){ |
|
drawFacemarks(img, landmarks[j], Scalar(0,0,255)); |
|
rectangle(img, rects[j], Scalar(255,0,255)); |
|
} |
|
|
|
if(rects.size()>0){ |
|
cout<<endl; |
|
imshow("result", img); |
|
waitKey(0); |
|
}else{ |
|
cout<<"face not found"<<endl; |
|
} |
|
} |
|
} |
|
|
|
bool myDetector(InputArray image, OutputArray faces, CascadeClassifier *face_cascade) |
|
{ |
|
Mat gray; |
|
|
|
if (image.channels() > 1) |
|
cvtColor(image, gray, COLOR_BGR2GRAY); |
|
else |
|
gray = image.getMat().clone(); |
|
|
|
equalizeHist(gray, gray); |
|
|
|
std::vector<Rect> faces_; |
|
face_cascade->detectMultiScale(gray, faces_, 1.4, 2, CASCADE_SCALE_IMAGE, Size(30, 30)); |
|
Mat(faces_).copyTo(faces); |
|
return true; |
|
} |
|
|
|
bool parseArguments(int argc, char** argv, |
|
String & cascade, |
|
String & model, |
|
String & images, |
|
String & annotations, |
|
String & test_images |
|
){ |
|
const String keys = |
|
"{ @c cascade | | (required) path to the face cascade xml file fo the face detector }" |
|
"{ @i images | | (required) path of a text file contains the list of paths to all training images}" |
|
"{ @a annotations | | (required) Path of a text file contains the list of paths to all annotations files}" |
|
"{ @m model | | (required) path to save the trained model }" |
|
"{ t test-images | | Path of a text file contains the list of paths to the test images}" |
|
"{ help h usage ? | | facemark_demo_lbf -cascade -images -annotations -model [-t] \n" |
|
" example: facemark_demo_lbf ../face_cascade.xml ../images_train.txt ../points_train.txt ../lbf.model}" |
|
; |
|
CommandLineParser parser(argc, argv,keys); |
|
parser.about("hello"); |
|
|
|
if (parser.has("help")){ |
|
parser.printMessage(); |
|
return false; |
|
} |
|
|
|
cascade = String(parser.get<String>("cascade")); |
|
model = String(parser.get<string>("model")); |
|
images = String(parser.get<string>("images")); |
|
annotations = String(parser.get<string>("annotations")); |
|
test_images = String(parser.get<string>("t")); |
|
|
|
cout<<"cascade : "<<cascade.c_str()<<endl; |
|
cout<<"model : "<<model.c_str()<<endl; |
|
cout<<"images : "<<images.c_str()<<endl; |
|
cout<<"annotations : "<<annotations.c_str()<<endl; |
|
|
|
if(cascade.empty() || model.empty() || images.empty() || annotations.empty()){ |
|
std::cerr << "one or more required arguments are not found" << '\n'; |
|
|
|
parser.printMessage(); |
|
return false; |
|
} |
|
|
|
return true; |
|
}
|
|
|