diff --git a/exe/FeatureExtraction/FeatureExtraction.cpp b/exe/FeatureExtraction/FeatureExtraction.cpp index a2e64f9..a6c147e 100644 --- a/exe/FeatureExtraction/FeatureExtraction.cpp +++ b/exe/FeatureExtraction/FeatureExtraction.cpp @@ -300,7 +300,7 @@ int main (int argc, char **argv) vector output_similarity_align; vector output_hog_align_files; - double sim_scale = 0.7; + double sim_scale = -1; int sim_size = 112; bool grayscale = false; bool video_output = false; @@ -320,6 +320,7 @@ int main (int argc, char **argv) get_output_feature_params(output_similarity_align, output_hog_align_files, sim_scale, sim_size, grayscale, verbose, dynamic, output_2D_landmarks, output_3D_landmarks, output_model_params, output_pose, output_AUs, output_gaze, arguments); + // Used for image masking string tri_loc; @@ -339,11 +340,6 @@ int main (int argc, char **argv) } } - // Will warp to scaled mean shape - cv::Mat_ similarity_normalised_shape = face_model.pdm.mean_shape * sim_scale; - // Discard the z component - similarity_normalised_shape = similarity_normalised_shape(cv::Rect(0, 0, 1, 2*similarity_normalised_shape.rows/3)).clone(); - // If multiple video files are tracked, use this to indicate if we are done bool done = false; int f_n = -1; @@ -381,7 +377,11 @@ int main (int argc, char **argv) } // Creating a face analyser that will be used for AU extraction - FaceAnalysis::FaceAnalyser face_analyser(vector(), 0.7, 112, 112, au_loc, tri_loc); + + // Make sure sim_scale is proportional to sim_size if not set + if (sim_scale == -1) sim_scale = sim_size * (0.7 / 112.0); + + FaceAnalysis::FaceAnalyser face_analyser(vector(), sim_scale, sim_size, sim_size, au_loc, tri_loc); while(!done) // this is not a for loop as we might also be reading from a webcam { @@ -588,7 +588,7 @@ int main (int argc, char **argv) } if(hog_output_file.is_open()) { - FaceAnalysis::Extract_FHOG_descriptor(hog_descriptor, sim_warped_img, num_hog_rows, num_hog_cols); + face_analyser.GetLatestHOG(hog_descriptor, num_hog_rows, num_hog_cols); if(visualise_hog && !det_parameters.quiet_mode) { diff --git a/gui/OpenFaceDemo/MainWindow.xaml.cs b/gui/OpenFaceDemo/MainWindow.xaml.cs index a73e78c..d198234 100644 --- a/gui/OpenFaceDemo/MainWindow.xaml.cs +++ b/gui/OpenFaceDemo/MainWindow.xaml.cs @@ -88,7 +88,7 @@ namespace OpenFaceDemo clnf_params = new FaceModelParameters(root, true); clnf_model = new CLNF(clnf_params); - face_analyser = new FaceAnalyserManaged(root, true); + face_analyser = new FaceAnalyserManaged(root, true, 112); Dispatcher.Invoke(DispatcherPriority.Render, new TimeSpan(0, 0, 0, 0, 200), (Action)(() => { diff --git a/gui/OpenFaceOffline/MainWindow.xaml b/gui/OpenFaceOffline/MainWindow.xaml index 9049955..09d6dcb 100644 --- a/gui/OpenFaceOffline/MainWindow.xaml +++ b/gui/OpenFaceOffline/MainWindow.xaml @@ -29,7 +29,7 @@ - + @@ -41,6 +41,10 @@ + + + + diff --git a/gui/OpenFaceOffline/MainWindow.xaml.cs b/gui/OpenFaceOffline/MainWindow.xaml.cs index f1c0182..9d53758 100644 --- a/gui/OpenFaceOffline/MainWindow.xaml.cs +++ b/gui/OpenFaceOffline/MainWindow.xaml.cs @@ -148,6 +148,8 @@ namespace OpenFaceOffline bool show_geometry = true; bool show_aus = true; + int image_output_size = 112; + // TODO classifiers converted to regressors // TODO indication that track is done @@ -166,7 +168,7 @@ namespace OpenFaceOffline bool dynamic_AU_shift = true; bool dynamic_AU_scale = false; bool use_dynamic_models = true; - + public MainWindow() { InitializeComponent(); @@ -196,7 +198,7 @@ namespace OpenFaceOffline clnf_params = new FaceModelParameters(root, false); clnf_model = new CLNF(clnf_params); - face_analyser = new FaceAnalyserManaged(root, use_dynamic_models); + face_analyser = new FaceAnalyserManaged(root, use_dynamic_models, image_output_size); } @@ -234,7 +236,7 @@ namespace OpenFaceOffline // Prepare recording if any based on the directory String file_no_ext = System.IO.Path.GetDirectoryName(filenames[0]); file_no_ext = System.IO.Path.GetFileName(file_no_ext); - + SetupRecording(record_root, file_no_ext, capture.width, capture.height, record_2D_landmarks, record_2D_landmarks, record_model_params, record_pose, record_AUs, record_gaze); // Start the actual processing @@ -304,7 +306,7 @@ namespace OpenFaceOffline { // Prepare recording if any String file_no_ext = System.IO.Path.GetFileNameWithoutExtension(filename); - + SetupRecording(record_root, file_no_ext, capture.width, capture.height, record_2D_landmarks, record_3D_landmarks, record_model_params, record_pose, record_AUs, record_gaze); // Start the actual processing @@ -445,7 +447,7 @@ namespace OpenFaceOffline ////////////////////////////////////////////// RawImage frame = null; double progress = -1; - + frame = new RawImage(capture.GetNextFrame(false)); progress = capture.GetProgress(); @@ -505,7 +507,7 @@ namespace OpenFaceOffline List> landmarks = null; List> eye_landmarks = null; List> gaze_lines = null; - Tuple gaze_angle = new Tuple(0,0); + Tuple gaze_angle = new Tuple(0, 0); if (detectionSucceeding) { @@ -556,7 +558,7 @@ namespace OpenFaceOffline nonRigidGraph.Update(non_rigid_params); // Update eye gaze - GazeXLabel.Content = gaze_angle.Item1 * (180.0/ Math.PI); + GazeXLabel.Content = gaze_angle.Item1 * (180.0 / Math.PI); GazeYLabel.Content = gaze_angle.Item2 * (180.0 / Math.PI); } @@ -625,7 +627,7 @@ namespace OpenFaceOffline })); // Recording the tracked model - RecordFrame(clnf_model, detectionSucceeding, frame_id + 1, frame, grayFrame, ((double)frame_id)/fps, + RecordFrame(clnf_model, detectionSucceeding, frame_id + 1, frame, grayFrame, ((double)frame_id) / fps, record_2D_landmarks, record_2D_landmarks, record_model_params, record_pose, record_AUs, record_gaze, fx, fy, cx, cy); if (reset) @@ -694,7 +696,7 @@ namespace OpenFaceOffline // ---------------------------------------------------------- // Recording helpers (TODO simplify) - private void SetupRecording(String root, String filename, int width, int height, bool output_2D_landmarks, bool output_3D_landmarks, + private void SetupRecording(String root, String filename, int width, int height, bool output_2D_landmarks, bool output_3D_landmarks, bool output_model_params, bool output_pose, bool output_AUs, bool output_gaze) { // Disallow changing recording settings when the recording starts, TODO move this up a bit @@ -810,7 +812,7 @@ namespace OpenFaceOffline if (record_tracked_vid) face_analyser.StopTrackingRecording(); - + Dispatcher.Invoke(DispatcherPriority.Render, new TimeSpan(0, 0, 0, 0, 200), (Action)(() => { RecordingMenu.IsEnabled = true; @@ -834,7 +836,7 @@ namespace OpenFaceOffline List pose = new List(); clnf_model.GetPose(pose, fx, fy, cx, cy); - + output_features_file.Write(String.Format("{0}, {1}, {2:F3}, {3}", frame_ind, time_stamp, confidence, success ? 1 : 0)); if (output_gaze) @@ -852,7 +854,7 @@ namespace OpenFaceOffline if (output_2D_landmarks) { List> landmarks_2d = clnf_model.CalculateLandmarks(); - + for (int i = 0; i < landmarks_2d.Count; ++i) output_features_file.Write(", {0:F2}", landmarks_2d[i].Item1); @@ -863,7 +865,7 @@ namespace OpenFaceOffline if (output_3D_landmarks) { List landmarks_3d = clnf_model.Calculate3DLandmarks(fx, fy, cx, cy); - + for (int i = 0; i < landmarks_3d.Count; ++i) output_features_file.Write(", {0:F2}", landmarks_3d[i].X); @@ -892,8 +894,8 @@ namespace OpenFaceOffline var au_classes = face_analyser.GetCurrentAUsClass(); foreach (var name_class in au_class_names) - output_features_file.Write(", {0:F0}", au_classes[name_class]); - + output_features_file.Write(", {0:F0}", au_classes[name_class]); + } output_features_file.WriteLine(); @@ -1206,10 +1208,26 @@ namespace OpenFaceOffline { // Change the face analyser, this should be safe as the model is only allowed to change when not running String root = AppDomain.CurrentDomain.BaseDirectory; - face_analyser = new FaceAnalyserManaged(root, UseDynamicModelsCheckBox.IsChecked); + face_analyser = new FaceAnalyserManaged(root, UseDynamicModelsCheckBox.IsChecked, image_output_size); } use_dynamic_models = UseDynamicModelsCheckBox.IsChecked; } + private void setOutputImageSize_Click(object sender, RoutedEventArgs e) + { + + NumberEntryWindow number_entry_window = new NumberEntryWindow(); + number_entry_window.Icon = this.Icon; + + number_entry_window.WindowStartupLocation = WindowStartupLocation.CenterScreen; + + if (number_entry_window.ShowDialog() == true) + { + image_output_size = number_entry_window.OutputInt; + String root = AppDomain.CurrentDomain.BaseDirectory; + face_analyser = new FaceAnalyserManaged(root, use_dynamic_models, image_output_size); + + } + } } } diff --git a/gui/OpenFaceOffline/OpenFaceOffline.csproj b/gui/OpenFaceOffline/OpenFaceOffline.csproj index f66b34d..1e0cd55 100644 --- a/gui/OpenFaceOffline/OpenFaceOffline.csproj +++ b/gui/OpenFaceOffline/OpenFaceOffline.csproj @@ -91,6 +91,9 @@ MultiBarGraphHorz.xaml + + NumberEntryWindow.xaml + OverlayImage.xaml @@ -125,6 +128,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/gui/OpenFaceOffline/UI_items/NumberEntryWindow.xaml b/gui/OpenFaceOffline/UI_items/NumberEntryWindow.xaml new file mode 100644 index 0000000..a9736f5 --- /dev/null +++ b/gui/OpenFaceOffline/UI_items/NumberEntryWindow.xaml @@ -0,0 +1,17 @@ + + + + + + + +