/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2017, Carnegie Mellon University and University of Cambridge, // all rights reserved. // // ACADEMIC OR NON-PROFIT ORGANIZATION NONCOMMERCIAL RESEARCH USE ONLY // // BY USING OR DOWNLOADING THE SOFTWARE, YOU ARE AGREEING TO THE TERMS OF THIS LICENSE AGREEMENT. // IF YOU DO NOT AGREE WITH THESE TERMS, YOU MAY NOT USE OR DOWNLOAD THE SOFTWARE. // // License can be found in OpenFace-license.txt // * Any publications arising from the use of this software, including but // not limited to academic journal and conference publications, technical // reports and manuals, must cite at least one of the following works: // // OpenFace: an open source facial behavior analysis toolkit // Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency // in IEEE Winter Conference on Applications of Computer Vision, 2016 // // Rendering of Eyes for Eye-Shape Registration and Gaze Estimation // Erroll Wood, Tadas Baltrušaitis, Xucong Zhang, Yusuke Sugano, Peter Robinson, and Andreas Bulling // in IEEE International. Conference on Computer Vision (ICCV), 2015 // // Cross-dataset learning and person-speci?c normalisation for automatic Action Unit detection // Tadas Baltrušaitis, Marwa Mahmoud, and Peter Robinson // in Facial Expression Recognition and Analysis Challenge, // IEEE International Conference on Automatic Face and Gesture Recognition, 2015 // // Constrained Local Neural Fields for robust facial landmark detection in the wild. // Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency. // in IEEE Int. Conference on Computer Vision Workshops, 300 Faces in-the-Wild Challenge, 2013. // /////////////////////////////////////////////////////////////////////////////// // FaceLandmarkImg.cpp : Defines the entry point for the console application for detecting landmarks in images. #include "LandmarkCoreIncludes.h" // System includes #include // OpenCV includes #include #include #include // Boost includes #include #include #include #include #include #include #include #include #include #include #include #ifndef CONFIG_DIR #define CONFIG_DIR "~" #endif using namespace std; vector get_arguments(int argc, char **argv) { vector arguments; for(int i = 0; i < argc; ++i) { arguments.push_back(string(argv[i])); } return arguments; } int main (int argc, char **argv) { //Convert arguments to more convenient vector form vector arguments = get_arguments(argc, argv); // no arguments: output usage if (arguments.size() == 1) { cout << "For command line arguments see:" << endl; cout << " https://github.com/TadasBaltrusaitis/OpenFace/wiki/Command-line-arguments"; return 0; } // Prepare for image reading Utilities::ImageCapture image_reader; // The sequence reader chooses what to open based on command line arguments provided if (!image_reader.Open(arguments)) { cout << "Could not open any images" << endl; return 1; } // Load the models if images found LandmarkDetector::FaceModelParameters det_parameters(arguments); // The modules that are being used for tracking cout << "Loading the model" << endl; LandmarkDetector::CLNF face_model(det_parameters.model_location); cout << "Model loaded" << endl; // Load facial feature extractor and AU analyser (make sure it is static) FaceAnalysis::FaceAnalyserParameters face_analysis_params(arguments); face_analysis_params.OptimizeForImages(); FaceAnalysis::FaceAnalyser face_analyser(face_analysis_params); // If bounding boxes not provided, use a face detector cv::CascadeClassifier classifier(det_parameters.face_detector_location); dlib::frontal_face_detector face_detector_hog = dlib::get_frontal_face_detector(); // A utility for visualizing the results Utilities::Visualizer visualizer(arguments); cv::Mat captured_image; captured_image = image_reader.GetNextImage(); if (!face_model.eye_model) { cout << "WARNING: no eye model found" << endl; } if (face_analyser.GetAUClassNames().size() == 0 && face_analyser.GetAUClassNames().size() == 0) { cout << "WARNING: no Action Unit models found" << endl; } cout << "Starting tracking" << endl; while (!captured_image.empty()) { Utilities::RecorderOpenFaceParameters recording_params(arguments, false, false, image_reader.fx, image_reader.fy, image_reader.cx, image_reader.cy); if (!face_model.eye_model) { recording_params.setOutputGaze(false); } Utilities::RecorderOpenFace open_face_rec(image_reader.name, recording_params, arguments); visualizer.SetImage(captured_image, image_reader.fx, image_reader.fy, image_reader.cx, image_reader.cy); // Making sure the image is in uchar grayscale cv::Mat_ grayscale_image = image_reader.GetGrayFrame(); // Detect faces in an image vector > face_detections; if (image_reader.has_bounding_boxes) { face_detections = image_reader.GetBoundingBoxes(); } else { if (det_parameters.curr_face_detector == LandmarkDetector::FaceModelParameters::HOG_SVM_DETECTOR) { vector confidences; LandmarkDetector::DetectFacesHOG(face_detections, grayscale_image, face_detector_hog, confidences); } else { LandmarkDetector::DetectFaces(face_detections, grayscale_image, classifier); } } // Detect landmarks around detected faces int face_det = 0; // perform landmark detection for every face detected for (size_t face = 0; face < face_detections.size(); ++face) { // if there are multiple detections go through them bool success = LandmarkDetector::DetectLandmarksInImage(grayscale_image, face_detections[face], face_model, det_parameters); // Estimate head pose and eye gaze cv::Vec6d pose_estimate = LandmarkDetector::GetPose(face_model, image_reader.fx, image_reader.fy, image_reader.cx, image_reader.cy); // Gaze tracking, absolute gaze direction cv::Point3f gaze_direction0(0, 0, -1); cv::Point3f gaze_direction1(0, 0, -1); cv::Vec2d gaze_angle(0, 0); if (face_model.eye_model) { GazeAnalysis::EstimateGaze(face_model, gaze_direction0, image_reader.fx, image_reader.fy, image_reader.cx, image_reader.cy, true); GazeAnalysis::EstimateGaze(face_model, gaze_direction1, image_reader.fx, image_reader.fy, image_reader.cx, image_reader.cy, false); gaze_angle = GazeAnalysis::GetGazeAngle(gaze_direction0, gaze_direction1); } cv::Mat sim_warped_img; cv::Mat_ hog_descriptor; int num_hog_rows = 0, num_hog_cols = 0; // Perform AU detection and HOG feature extraction, as this can be expensive only compute it if needed by output or visualization if (recording_params.outputAlignedFaces() || recording_params.outputHOG() || recording_params.outputAUs() || visualizer.vis_align || visualizer.vis_hog) { face_analyser.PredictStaticAUsAndComputeFeatures(captured_image, face_model.detected_landmarks); face_analyser.GetLatestAlignedFace(sim_warped_img); face_analyser.GetLatestHOG(hog_descriptor, num_hog_rows, num_hog_cols); } // Displaying the tracking visualizations visualizer.SetObservationFaceAlign(sim_warped_img); visualizer.SetObservationHOG(hog_descriptor, num_hog_rows, num_hog_cols); visualizer.SetObservationLandmarks(face_model.detected_landmarks, 1.0, face_model.GetVisibilities()); // Set confidence to high to make sure we always visualize visualizer.SetObservationPose(pose_estimate, 1.0); visualizer.SetObservationGaze(gaze_direction0, gaze_direction1, LandmarkDetector::CalculateAllEyeLandmarks(face_model), LandmarkDetector::Calculate3DEyeLandmarks(face_model, image_reader.fx, image_reader.fy, image_reader.cx, image_reader.cy), face_model.detection_certainty); visualizer.SetObservationActionUnits(face_analyser.GetCurrentAUsReg(), face_analyser.GetCurrentAUsClass()); // Setting up the recorder output open_face_rec.SetObservationHOG(face_model.detection_success, hog_descriptor, num_hog_rows, num_hog_cols, 31); // The number of channels in HOG is fixed at the moment, as using FHOG open_face_rec.SetObservationVisualization(visualizer.GetVisImage()); open_face_rec.SetObservationActionUnits(face_analyser.GetCurrentAUsReg(), face_analyser.GetCurrentAUsClass()); open_face_rec.SetObservationLandmarks(face_model.detected_landmarks, face_model.GetShape(image_reader.fx, image_reader.fy, image_reader.cx, image_reader.cy), face_model.params_global, face_model.params_local, face_model.detection_certainty, face_model.detection_success); open_face_rec.SetObservationPose(pose_estimate); open_face_rec.SetObservationGaze(gaze_direction0, gaze_direction1, gaze_angle, LandmarkDetector::CalculateAllEyeLandmarks(face_model), LandmarkDetector::Calculate3DEyeLandmarks(face_model, image_reader.fx, image_reader.fy, image_reader.cx, image_reader.cy)); open_face_rec.SetObservationFaceAlign(sim_warped_img); open_face_rec.SetObservationFaceID(face); open_face_rec.WriteObservation(); } if(face_detections.size() > 0) { visualizer.ShowObservation(); } // Grabbing the next frame in the sequence captured_image = image_reader.GetNextImage(); } return 0; }