/* 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_aam [test_files] * * Example: * facemark_demo_aam ../face_cascade.xml ../eyes_cascade.xml ../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/lfpw.zip *--------------------------------------------------*/ #include #include #include #include "opencv2/core.hpp" #include "opencv2/highgui.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/face.hpp" #include #include #include using namespace std; using namespace cv; using namespace cv::face; bool myDetector( InputArray image, OutputArray ROIs, CascadeClassifier *face_cascade); bool getInitialFitting(Mat image, Rect face, std::vector s0, CascadeClassifier eyes_cascade, Mat & R, Point2f & Trans, float & scale); 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,eyes_cascade_path,images_path, annotations_path, test_images_path; if(!parseArguments(argc, argv, cascade_path,eyes_cascade_path,images_path, annotations_path, test_images_path)) return -1; //! [instance_creation] /*create the facemark instance*/ FacemarkAAM::Params params; params.scales.push_back(2.0); params.scales.push_back(4.0); params.model_filename = "AAM.yaml"; Ptr facemark = FacemarkAAM::create(params); //! [instance_creation] //! [load_dataset] /*Loads the dataset*/ std::vector images_train; std::vector landmarks_train; loadDatasetList(images_path,annotations_path,images_train,landmarks_train); //! [load_dataset] //! [add_samples] Mat image; std::vector facial_points; for(size_t i=0;iaddTrainingSample(image, facial_points); } //! [add_samples] //! [training] /* trained model will be saved to AAM.yml */ facemark->training(); //! [training] //! [load_test_images] /*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 images; std::vector facePoints; loadDatasetList(testFiles, testPts, images, facePoints); //! [load_test_images] //! [trainsformation_variables] float scale ; Point2f T; Mat R; //! [trainsformation_variables] //! [base_shape] FacemarkAAM::Data data; facemark->getData(&data); std::vector s0 = data.s0; //! [base_shape] //! [fitting] /*fitting process*/ std::vector faces; //! [load_cascade_models] CascadeClassifier face_cascade(cascade_path); CascadeClassifier eyes_cascade(eyes_cascade_path); //! [load_cascade_models] for(int i=0;i<(int)images.size();i++){ printf("image #%i ", i); //! [detect_face] image = imread(images[i]); myDetector(image, faces, &face_cascade); //! [detect_face] if(faces.size()>0){ //! [get_initialization] std::vector conf; std::vector faces_eyes; for(unsigned j=0;j0){ printf(" - face with eyes found %i ", (int)conf.size()); std::vector > landmarks; double newtime = (double)getTickCount(); facemark->fitConfig(image, faces_eyes, landmarks, conf); double fittime = ((getTickCount() - newtime)/getTickFrequency()); for(unsigned j=0;j 1) cvtColor(image, gray, COLOR_BGR2GRAY); else gray = image.getMat().clone(); equalizeHist(gray, gray); std::vector faces_; face_cascade->detectMultiScale(gray, faces_, 1.4, 2, CASCADE_SCALE_IMAGE, Size(30, 30)); Mat(faces_).copyTo(faces); return true; } bool getInitialFitting(Mat image, Rect face, std::vector s0 ,CascadeClassifier eyes_cascade, Mat & R, Point2f & Trans, float & scale){ std::vector mybase; std::vector T; std::vector base = Mat(Mat(s0)+Scalar(image.cols/2,image.rows/2)).reshape(2); std::vector base_shape,base_shape2 ; Point2f e1 = Point2f((float)((base[39].x+base[36].x)/2.0),(float)((base[39].y+base[36].y)/2.0)); //eye1 Point2f e2 = Point2f((float)((base[45].x+base[42].x)/2.0),(float)((base[45].y+base[42].y)/2.0)); //eye2 if(face.width==0 || face.height==0) return false; std::vector eye; bool found=false; Mat faceROI = image( face); std::vector eyes; //-- In each face, detect eyes eyes_cascade.detectMultiScale( faceROI, eyes, 1.1, 2, CASCADE_SCALE_IMAGE, Size(20, 20) ); if(eyes.size()==2){ found = true; int j=0; Point2f c1( (float)(face.x + eyes[j].x + eyes[j].width*0.5), (float)(face.y + eyes[j].y + eyes[j].height*0.5)); j=1; Point2f c2( (float)(face.x + eyes[j].x + eyes[j].width*0.5), (float)(face.y + eyes[j].y + eyes[j].height*0.5)); Point2f pivot; double a0,a1; if(c1.x("face-cascade")); model = String(parser.get("eyes-cascade")); images = String(parser.get("images")); annotations = String(parser.get("annotations")); test_images = String(parser.get("test-images")); if(cascade.empty() || model.empty() || images.empty() || annotations.empty()){ std::cerr << "one or more required arguments are not found" << '\n'; cout<<"face-cascade : "<