2016-04-28 15:40:36 -04:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
2017-05-08 21:36:23 -04:00
|
|
|
// Copyright (C) 2017, Carnegie Mellon University and University of Cambridge,
|
2016-04-28 15:40:36 -04:00
|
|
|
// all rights reserved.
|
|
|
|
|
//
|
2017-05-08 21:36:23 -04:00
|
|
|
// 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
|
2016-04-28 15:40:36 -04:00
|
|
|
//
|
|
|
|
|
// * 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:
|
|
|
|
|
//
|
2018-05-29 18:03:26 +01:00
|
|
|
// OpenFace 2.0: Facial Behavior Analysis Toolkit
|
|
|
|
|
// Tadas Baltrušaitis, Amir Zadeh, Yao Chong Lim, and Louis-Philippe Morency
|
|
|
|
|
// in IEEE International Conference on Automatic Face and Gesture Recognition, 2018
|
|
|
|
|
//
|
|
|
|
|
// Convolutional experts constrained local model for facial landmark detection.
|
|
|
|
|
// A. Zadeh, T. Baltrušaitis, and Louis-Philippe Morency,
|
|
|
|
|
// in Computer Vision and Pattern Recognition Workshops, 2017.
|
2016-04-28 15:40:36 -04:00
|
|
|
//
|
|
|
|
|
// Rendering of Eyes for Eye-Shape Registration and Gaze Estimation
|
2017-02-23 13:45:09 -05:00
|
|
|
// Erroll Wood, Tadas Baltrušaitis, Xucong Zhang, Yusuke Sugano, Peter Robinson, and Andreas Bulling
|
2016-04-28 15:40:36 -04:00
|
|
|
// in IEEE International. Conference on Computer Vision (ICCV), 2015
|
|
|
|
|
//
|
2018-05-29 18:03:26 +01:00
|
|
|
// Cross-dataset learning and person-specific normalisation for automatic Action Unit detection
|
2017-02-23 13:45:09 -05:00
|
|
|
// Tadas Baltrušaitis, Marwa Mahmoud, and Peter Robinson
|
2016-04-28 15:40:36 -04:00
|
|
|
// in Facial Expression Recognition and Analysis Challenge,
|
|
|
|
|
// IEEE International Conference on Automatic Face and Gesture Recognition, 2015
|
|
|
|
|
//
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
#ifndef __LANDMARK_DETECTOR_MODEL_h_
|
|
|
|
|
#define __LANDMARK_DETECTOR_MODEL_h_
|
|
|
|
|
|
|
|
|
|
// OpenCV dependencies
|
|
|
|
|
#include <opencv2/core/core.hpp>
|
|
|
|
|
#include <opencv2/objdetect.hpp>
|
|
|
|
|
|
2018-05-08 19:44:34 +01:00
|
|
|
// OpenBLAS
|
|
|
|
|
#include <cblas.h>
|
|
|
|
|
|
2016-04-28 15:40:36 -04:00
|
|
|
// dlib dependencies for face detection
|
|
|
|
|
#include <dlib/image_processing/frontal_face_detector.h>
|
|
|
|
|
#include <dlib/opencv.h>
|
|
|
|
|
|
|
|
|
|
#include "PDM.h"
|
|
|
|
|
#include "Patch_experts.h"
|
|
|
|
|
#include "LandmarkDetectionValidator.h"
|
|
|
|
|
#include "LandmarkDetectorParameters.h"
|
2018-05-06 08:19:09 +01:00
|
|
|
#include "FaceDetectorMTCNN.h"
|
2016-04-28 15:40:36 -04:00
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
namespace LandmarkDetector
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
// A main class containing all the modules required for landmark detection
|
|
|
|
|
// Face shape model
|
|
|
|
|
// Patch experts
|
|
|
|
|
// Optimization techniques
|
|
|
|
|
class CLNF{
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
|
// Member variables that contain the model description
|
|
|
|
|
|
|
|
|
|
// The linear 3D Point Distribution Model
|
|
|
|
|
PDM pdm;
|
|
|
|
|
// The set of patch experts
|
|
|
|
|
Patch_experts patch_experts;
|
|
|
|
|
|
|
|
|
|
// The local and global parameters describing the current model instance (current landmark detections)
|
|
|
|
|
|
|
|
|
|
// Local parameters describing the non-rigid shape
|
2018-05-06 08:19:09 +01:00
|
|
|
cv::Mat_<float> params_local;
|
2016-04-28 15:40:36 -04:00
|
|
|
|
|
|
|
|
// Global parameters describing the rigid shape [scale, euler_x, euler_y, euler_z, tx, ty]
|
2018-05-06 08:19:09 +01:00
|
|
|
cv::Vec6f params_global;
|
2016-04-28 15:40:36 -04:00
|
|
|
|
|
|
|
|
// A collection of hierarchical CLNF models that can be used for refinement
|
|
|
|
|
vector<CLNF> hierarchical_models;
|
|
|
|
|
vector<string> hierarchical_model_names;
|
|
|
|
|
vector<vector<pair<int,int>>> hierarchical_mapping;
|
|
|
|
|
vector<FaceModelParameters> hierarchical_params;
|
|
|
|
|
|
|
|
|
|
//==================== Helpers for face detection and landmark detection validation =========================================
|
|
|
|
|
|
2018-05-06 08:19:09 +01:00
|
|
|
// TODO these should be static, and loading should be made easier
|
|
|
|
|
|
2016-04-28 15:40:36 -04:00
|
|
|
// Haar cascade classifier for face detection
|
|
|
|
|
cv::CascadeClassifier face_detector_HAAR;
|
2018-05-06 08:19:09 +01:00
|
|
|
string haar_face_detector_location;
|
|
|
|
|
|
2016-04-28 15:40:36 -04:00
|
|
|
// A HOG SVM-struct based face detector
|
|
|
|
|
dlib::frontal_face_detector face_detector_HOG;
|
|
|
|
|
|
2018-05-06 08:19:09 +01:00
|
|
|
FaceDetectorMTCNN face_detector_MTCNN;
|
|
|
|
|
string mtcnn_face_detector_location;
|
2016-04-28 15:40:36 -04:00
|
|
|
|
2018-05-06 08:19:09 +01:00
|
|
|
// Validate if the detected landmarks are correct using an SVR regressor
|
2016-04-28 15:40:36 -04:00
|
|
|
DetectionValidator landmark_validator;
|
|
|
|
|
|
2018-05-06 08:19:09 +01:00
|
|
|
// Indicating if landmark detection succeeded (based on SVR validator)
|
2016-04-28 15:40:36 -04:00
|
|
|
bool detection_success;
|
|
|
|
|
|
2018-05-06 08:19:09 +01:00
|
|
|
// Indicating if the tracking has been initialised (for video based tracking)
|
|
|
|
|
bool tracking_initialised;
|
|
|
|
|
|
|
|
|
|
// The actual output of the regressor (-1 is perfect detection 1 is worst detection)
|
|
|
|
|
float detection_certainty;
|
2016-04-28 15:40:36 -04:00
|
|
|
|
|
|
|
|
// Indicator if eye model is there for eye detection
|
2017-02-23 13:45:09 -05:00
|
|
|
bool eye_model;
|
2016-04-28 15:40:36 -04:00
|
|
|
|
|
|
|
|
// the triangulation per each view (for drawing purposes only)
|
|
|
|
|
vector<cv::Mat_<int> > triangulations;
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
|
// Member variables that retain the state of the tracking (reflecting the state of the lastly tracked (detected) image
|
|
|
|
|
|
|
|
|
|
// Lastly detect 2D model shape [x1,x2,...xn,y1,...yn]
|
2018-05-06 08:19:09 +01:00
|
|
|
cv::Mat_<float> detected_landmarks;
|
2016-04-28 15:40:36 -04:00
|
|
|
|
|
|
|
|
// The landmark detection likelihoods (combined and per patch expert)
|
2018-05-06 08:19:09 +01:00
|
|
|
float model_likelihood;
|
|
|
|
|
cv::Mat_<float> landmark_likelihoods;
|
2016-04-28 15:40:36 -04:00
|
|
|
|
|
|
|
|
// Keeping track of how many frames the tracker has failed in so far when tracking in videos
|
|
|
|
|
// This is useful for knowing when to initialise and reinitialise tracking
|
|
|
|
|
int failures_in_a_row;
|
|
|
|
|
|
|
|
|
|
// A template of a face that last succeeded with tracking (useful for large motions in video)
|
|
|
|
|
cv::Mat_<uchar> face_template;
|
|
|
|
|
|
|
|
|
|
// Useful when resetting or initialising the model closer to a specific location (when multiple faces are present)
|
|
|
|
|
cv::Point_<double> preference_det;
|
2018-05-06 08:19:09 +01:00
|
|
|
|
|
|
|
|
// Tracking which view was used last
|
|
|
|
|
int view_used;
|
|
|
|
|
|
|
|
|
|
// See if the model was read in correctly
|
|
|
|
|
bool loaded_successfully;
|
|
|
|
|
|
2016-04-28 15:40:36 -04:00
|
|
|
// A default constructor
|
|
|
|
|
CLNF();
|
|
|
|
|
|
|
|
|
|
// Constructor from a model file
|
|
|
|
|
CLNF(string fname);
|
|
|
|
|
|
|
|
|
|
// Copy constructor (makes a deep copy of the detector)
|
|
|
|
|
CLNF(const CLNF& other);
|
|
|
|
|
|
|
|
|
|
// Assignment operator for lvalues (makes a deep copy of the detector)
|
|
|
|
|
CLNF & operator= (const CLNF& other);
|
|
|
|
|
|
|
|
|
|
// Empty Destructor as the memory of every object will be managed by the corresponding libraries (no pointers)
|
|
|
|
|
~CLNF(){}
|
|
|
|
|
|
|
|
|
|
// Move constructor
|
|
|
|
|
CLNF(const CLNF&& other);
|
|
|
|
|
|
|
|
|
|
// Assignment operator for rvalues
|
|
|
|
|
CLNF & operator= (const CLNF&& other);
|
|
|
|
|
|
|
|
|
|
// Does the actual work - landmark detection
|
2017-08-01 17:11:02 -04:00
|
|
|
bool DetectLandmarks(const cv::Mat_<uchar> &image, FaceModelParameters& params);
|
2016-04-28 15:40:36 -04:00
|
|
|
|
|
|
|
|
// Gets the shape of the current detected landmarks in camera space (given camera calibration)
|
|
|
|
|
// Can only be called after a call to DetectLandmarksInVideo or DetectLandmarksInImage
|
2018-05-06 08:19:09 +01:00
|
|
|
cv::Mat_<float> GetShape(float fx, float fy, float cx, float cy) const;
|
2016-04-28 15:40:36 -04:00
|
|
|
|
|
|
|
|
// A utility bounding box function
|
2018-05-06 08:19:09 +01:00
|
|
|
cv::Rect_<float> GetBoundingBox() const;
|
2016-04-28 15:40:36 -04:00
|
|
|
|
2018-01-31 08:23:48 +00:00
|
|
|
// Get the currently non-self occluded landmarks
|
|
|
|
|
cv::Mat_<int> GetVisibilities() const;
|
|
|
|
|
|
2016-04-28 15:40:36 -04:00
|
|
|
// Reset the model (useful if we want to completelly reinitialise, or we want to track another video)
|
|
|
|
|
void Reset();
|
|
|
|
|
|
|
|
|
|
// Reset the model, choosing the face nearest (x,y) where x and y are between 0 and 1.
|
|
|
|
|
void Reset(double x, double y);
|
|
|
|
|
|
|
|
|
|
// Reading the model in
|
|
|
|
|
void Read(string name);
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
2018-05-06 08:19:09 +01:00
|
|
|
// Helper reading function
|
|
|
|
|
bool Read_CLNF(string clnf_location);
|
2017-12-06 15:43:55 +00:00
|
|
|
|
2016-04-28 15:40:36 -04:00
|
|
|
// the speedup of RLMS using precalculated KDE responses (described in Saragih 2011 RLMS paper)
|
|
|
|
|
map<int, cv::Mat_<float> > kde_resp_precalc;
|
|
|
|
|
|
|
|
|
|
// The model fitting: patch response computation and optimisation steps
|
2018-05-19 23:32:39 +08:00
|
|
|
bool Fit(const cv::Mat_<float>& intensity_image, const std::vector<int>& window_sizes, const FaceModelParameters& parameters);
|
2016-04-28 15:40:36 -04:00
|
|
|
|
|
|
|
|
// Mean shift computation that uses precalculated kernel density estimators (the one actually used)
|
|
|
|
|
void NonVectorisedMeanShift_precalc_kde(cv::Mat_<float>& out_mean_shifts, const vector<cv::Mat_<float> >& patch_expert_responses, const cv::Mat_<float> &dxs, const cv::Mat_<float> &dys, int resp_size, float a, int scale, int view_id, map<int, cv::Mat_<float> >& mean_shifts);
|
|
|
|
|
|
|
|
|
|
// The actual model optimisation (update step), returns the model likelihood
|
2018-05-06 08:19:09 +01:00
|
|
|
float NU_RLMS(cv::Vec6f& final_global, cv::Mat_<float>& final_local, const vector<cv::Mat_<float> >& patch_expert_responses, const cv::Vec6f& initial_global, const cv::Mat_<float>& initial_local,
|
|
|
|
|
const cv::Mat_<float>& base_shape, const cv::Matx22f& sim_img_to_ref, const cv::Matx22f& sim_ref_to_img, int resp_size, int view_idx, bool rigid, int scale, cv::Mat_<float>& landmark_lhoods, const FaceModelParameters& parameters, bool compute_lhood);
|
2016-04-28 15:40:36 -04:00
|
|
|
|
|
|
|
|
// Generating the weight matrix for the Weighted least squares
|
|
|
|
|
void GetWeightMatrix(cv::Mat_<float>& WeightMatrix, int scale, int view_id, const FaceModelParameters& parameters);
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
//===========================================================================
|
|
|
|
|
}
|
|
|
|
|
#endif
|