/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2017, Tadas Baltrusaitis. // // 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. // /////////////////////////////////////////////////////////////////////////////// // Camera_Interop.h #pragma once #pragma unmanaged // Include all the unmanaged things we need. #include "RecorderOpenFace.h" #pragma managed #include #include namespace UtilitiesOF { public ref class RecorderOpenFaceParameters { private: Utilities::RecorderOpenFaceParameters *m_params; public: RecorderOpenFaceParameters(bool sequence, bool is_from_webcam, bool output_2D_landmarks, bool output_3D_landmarks, bool output_model_params, bool output_pose, bool output_AUs, bool output_gaze, bool output_hog, bool output_tracked, bool output_aligned_faces, float fx, float fy, float cx, float cy, double fps_vid_out) { m_params = new Utilities::RecorderOpenFaceParameters(sequence, is_from_webcam, output_2D_landmarks, output_3D_landmarks, output_model_params, output_pose, output_AUs, output_gaze, output_hog, output_tracked, output_aligned_faces, fx, fy, cx, cy, fps_vid_out); } Utilities::RecorderOpenFaceParameters * GetParams() { return m_params; } !RecorderOpenFaceParameters() { // Automatically closes capture object before freeing memory. if (m_params != nullptr) { delete m_params; } } // Destructor. Called on explicit Dispose() only. ~RecorderOpenFaceParameters() { this->!RecorderOpenFaceParameters(); } }; public ref class RecorderOpenFace { private: // OpenCV based video capture for reading from files Utilities::RecorderOpenFace* m_recorder; public: // Can provide a directory, or a list of files RecorderOpenFace(System::String^ in_filename, UtilitiesOF::RecorderOpenFaceParameters^ parameters, System::String^ output_directory) { std::string in_filename_std = msclr::interop::marshal_as(in_filename); std::string output_directory_std = msclr::interop::marshal_as(output_directory); m_recorder = new Utilities::RecorderOpenFace(in_filename_std, *parameters->GetParams(), output_directory_std); } void Close() { m_recorder->Close(); } void WriteObservation() { m_recorder->WriteObservation(); } void SetObservationGaze(System::Tuple^ gaze_direction0, System::Tuple^ gaze_direction1, System::Tuple^ gaze_angle, List^>^ landmarks_2D, List^>^ landmarks_3D) { cv::Point3f gaze_direction0_cv(gaze_direction0->Item1, gaze_direction0->Item2, gaze_direction0->Item3); cv::Point3f gaze_direction1_cv(gaze_direction1->Item1, gaze_direction1->Item2, gaze_direction1->Item3); cv::Vec2d gaze_angle_cv(gaze_angle->Item1, gaze_angle->Item2); // Construct an OpenCV matrix from the landmarks std::vector landmarks_2D_cv; for (int i = 0; i < landmarks_2D->Count; ++i) { landmarks_2D_cv.push_back(cv::Point2d(landmarks_2D[i]->Item1, landmarks_2D[i]->Item2)); } // Construct an OpenCV matrix from the landmarks std::vector landmarks_3D_cv; for (int i = 0; i < landmarks_3D->Count; ++i) { landmarks_3D_cv.push_back(cv::Point3d(landmarks_3D[i]->Item1, landmarks_3D[i]->Item2, landmarks_3D[i]->Item3)); } m_recorder->SetObservationGaze(gaze_direction0_cv, gaze_direction1_cv, gaze_angle_cv, landmarks_2D_cv, landmarks_3D_cv); } System::String^ GetCSVFile() { return gcnew System::String(m_recorder->GetCSVFile().c_str()); } // Setting the observations void SetObservationTimestamp(double timestamp) { m_recorder->SetObservationTimestamp(timestamp); } void SetObservationPose(List^ pose) { cv::Vec6d pose_vec(pose[0], pose[1], pose[2], pose[3], pose[4], pose[5]); m_recorder->SetObservationPose(pose_vec); } void SetObservationActionUnits(Dictionary^ au_regs, Dictionary^ au_class) { std::vector > au_regs_std; auto enum_reg = au_regs->GetEnumerator(); while (enum_reg.MoveNext()) { std::string au_name = msclr::interop::marshal_as(enum_reg.Current.Key); double value = (double)enum_reg.Current.Value; au_regs_std.push_back(std::pair(au_name, value)); } std::vector > au_class_std; auto enum_class = au_class->GetEnumerator(); while (enum_class.MoveNext()) { std::string au_name = msclr::interop::marshal_as(enum_class.Current.Key); double value = (double)enum_class.Current.Value; au_class_std.push_back(std::pair(au_name, value)); } m_recorder->SetObservationActionUnits(au_regs_std, au_class_std); } void SetObservationFaceAlign(OpenCVWrappers::RawImage^ aligned_face_image) { m_recorder->SetObservationFaceAlign(aligned_face_image->Mat); } void SetObservationVisualization(OpenCVWrappers::RawImage^ vis_image) { m_recorder->SetObservationVisualization(vis_image->Mat); } void SetObservationHOG(bool success, OpenCVWrappers::RawImage^ aligned_face_image, int num_cols, int num_rows, int num_channels) { m_recorder->SetObservationHOG(success, aligned_face_image->Mat, num_cols, num_rows, num_channels); } void SetObservationLandmarks(List^>^ landmarks_2D, List^>^ landmarks_3D, List^ params_global, List^ params_local, double confidence, bool success) { // Construct an OpenCV matrix from the landmarks cv::Mat_ landmarks_2D_mat(landmarks_2D->Count * 2, 1, 0.0); for (int i = 0; i < landmarks_2D->Count; ++i) { landmarks_2D_mat.at(i, 0) = landmarks_2D[i]->Item1; landmarks_2D_mat.at(i + landmarks_2D->Count, 0) = landmarks_2D[i]->Item2; } // Construct an OpenCV matrix from the landmarks cv::Mat_ landmarks_3D_mat(landmarks_3D->Count * 3, 1, 0.0); for (int i = 0; i < landmarks_3D->Count; ++i) { landmarks_3D_mat.at(i, 0) = landmarks_3D[i]->Item1; landmarks_3D_mat.at(i + landmarks_3D->Count, 0) = landmarks_3D[i]->Item2; landmarks_3D_mat.at(i + 2 * landmarks_3D->Count, 0) = landmarks_3D[i]->Item3; } cv::Vec6d params_global_vec(params_global[0], params_global[1], params_global[2], params_global[3], params_global[4], params_global[5]); cv::Mat_ params_local_vec(params_local->Count, 1, 0.0); for (int i = 0; i < params_local->Count; ++i) { params_local_vec.at(i, 0) = params_local[i]; } m_recorder->SetObservationLandmarks(landmarks_2D_mat, landmarks_3D_mat, params_global_vec, params_local_vec, confidence, success); } // Finalizer. Definitely called before Garbage Collection, // but not automatically called on explicit Dispose(). // May be called multiple times. !RecorderOpenFace() { // Automatically closes capture object before freeing memory. if (m_recorder != nullptr) { delete m_recorder; } } // Destructor. Called on explicit Dispose() only. ~RecorderOpenFace() { this->!RecorderOpenFace(); } }; }