From e8511cd10fa8c886e68ac08c1af3bfa9591dad29 Mon Sep 17 00:00:00 2001 From: Tadas Baltrusaitis Date: Wed, 8 Nov 2017 19:38:37 +0000 Subject: [PATCH] Working on SequenceCapture functionality. --- .gitignore | 2 + exe/FeatureExtraction/FeatureExtraction.cpp | 4 +- lib/local/Utilities/include/SequenceCapture.h | 15 +- lib/local/Utilities/src/SequenceCapture.cpp | 258 ++++++++++++++++++ 4 files changed, 271 insertions(+), 8 deletions(-) create mode 100644 lib/local/Utilities/src/SequenceCapture.cpp diff --git a/.gitignore b/.gitignore index fd4c176..05d549c 100644 --- a/.gitignore +++ b/.gitignore @@ -51,3 +51,5 @@ matlab_runners/Head Pose Experiments/experiments/ict_out/ OpenFace\.VC\.db matlab_version/face_validation/vlfeat-0.9.20/ matlab_version/face_validation/trained/intermediate/ +lib/local/GazeAnalyser/x64/ +lib/local/Utilities/x64/ diff --git a/exe/FeatureExtraction/FeatureExtraction.cpp b/exe/FeatureExtraction/FeatureExtraction.cpp index f22c59e..b07575f 100644 --- a/exe/FeatureExtraction/FeatureExtraction.cpp +++ b/exe/FeatureExtraction/FeatureExtraction.cpp @@ -317,8 +317,8 @@ int main (int argc, char **argv) fy = fx; } - Recorder::RecorderOpenFaceParameters recording_params(arguments, true, fps_vid_in); - Recorder::RecorderOpenFace open_face_rec(output_files[f_n], input_files[f_n], recording_params); + Utilities::RecorderOpenFaceParameters recording_params(arguments, true, fps_vid_in); + Utilities::RecorderOpenFace open_face_rec(output_files[f_n], input_files[f_n], recording_params); int frame_count = 0; diff --git a/lib/local/Utilities/include/SequenceCapture.h b/lib/local/Utilities/include/SequenceCapture.h index ffe61e5..553da0a 100644 --- a/lib/local/Utilities/include/SequenceCapture.h +++ b/lib/local/Utilities/include/SequenceCapture.h @@ -58,18 +58,23 @@ namespace Utilities SequenceCapture(); // Opening based on command line arguments - void Open(std::vector arguments); + bool Open(std::vector arguments); // Direct opening // Webcam - void OpenWebcam(int device_id); + bool OpenWebcam(int device_id, int image_width = 640, int image_height = 480, float fx = -1, float fy = -1, float cx = -1, float cy = -1); // Image sequence in the directory - void OpenImageSequence(std::string directory); + bool OpenImageSequence(std::string directory, float fx = -1, float fy = -1, float cx = -1, float cy = -1); // Video file - void OpenVideoFile(std::string video_file); + bool OpenVideoFile(std::string video_file, float fx = -1, float fy = -1, float cx = -1, float cy = -1); + + int frame_width; + int frame_height; + + float fx, fy, cx, cy; private: @@ -93,8 +98,6 @@ namespace Utilities // Length of video allowing to assess progress int vid_length; - // TODO fx and fy should be here - }; } #endif \ No newline at end of file diff --git a/lib/local/Utilities/src/SequenceCapture.cpp b/lib/local/Utilities/src/SequenceCapture.cpp new file mode 100644 index 0000000..f663701 --- /dev/null +++ b/lib/local/Utilities/src/SequenceCapture.cpp @@ -0,0 +1,258 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2017, Tadas Baltrusaitis, 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. +// +/////////////////////////////////////////////////////////////////////////////// + +#include "SequenceCapture.h" + +#include + +// Boost includes +#include +#include +#include + +using namespace Utilities; + +// TODO initialize defaults +SequenceCapture::SequenceCapture(): +{ + +} + +bool SequenceCapture::Open(std::vector arguments) +{ + + // Consuming the input arguments + bool* valid = new bool[arguments.size()]; + + for (size_t i = 0; i < arguments.size(); ++i) + { + valid[i] = true; + } + + std::string input_root = ""; + + std::string separator = std::string(1, boost::filesystem::path::preferred_separator); + + // First check if there is a root argument (so that videos and input directories could be defined more easily) + for (size_t i = 0; i < arguments.size(); ++i) + { + if (arguments[i].compare("-root") == 0) + { + input_root = arguments[i + 1] + separator; + i++; + } + if (arguments[i].compare("-inroot") == 0) + { + input_root = arguments[i + 1] + separator; + i++; + } + } + + std::string input_video_file; + std::string input_sequence_directory; + int device = -1; + + bool file_found = false; + + for (size_t i = 0; i < arguments.size(); ++i) + { + if (!file_found && arguments[i].compare("-f") == 0) + { + input_video_file = (input_root + arguments[i + 1]); + valid[i] = false; + valid[i + 1] = false; + i++; + file_found = true; + } + else if (!file_found && arguments[i].compare("-fdir") == 0) + { + input_sequence_directory = (input_root + arguments[i + 1]); + valid[i] = false; + valid[i + 1] = false; + i++; + file_found = true; + } + else if (arguments[i].compare("-fx") == 0) + { + std::stringstream data(arguments[i + 1]); + data >> fx; + i++; + } + else if (arguments[i].compare("-fy") == 0) + { + std::stringstream data(arguments[i + 1]); + data >> fy; + i++; + } + else if (arguments[i].compare("-cx") == 0) + { + std::stringstream data(arguments[i + 1]); + data >> cx; + i++; + } + else if (arguments[i].compare("-cy") == 0) + { + std::stringstream data(arguments[i + 1]); + data >> cy; + i++; + } + else if (arguments[i].compare("-device") == 0) + { + std::stringstream data(arguments[i + 1]); + data >> device; + valid[i] = false; + valid[i + 1] = false; + i++; + } + } + + for (int i = arguments.size() - 1; i >= 0; --i) + { + if (!valid[i]) + { + arguments.erase(arguments.begin() + i); + } + } + + // Based on what was read in open the sequence TODO + +} + +bool SequenceCapture::OpenWebcam(int device, int image_width, int image_height, float fx, float fy, float cx, float cy) +{ + + if (device < 0) + { + std::cout << "Specify a valid device" << std::endl; + return false; + } + + latest_frame = cv::Mat(); + latest_gray_frame = cv::Mat(); + + capture.open(device); + capture.set(CV_CAP_PROP_FRAME_WIDTH, image_width); + capture.set(CV_CAP_PROP_FRAME_HEIGHT, image_height); + + is_webcam = true; + is_image_seq = false; + + vid_length = 0; + frame_num = 0; + + this->frame_width = capture.get(CV_CAP_PROP_FRAME_WIDTH); + this->frame_height = capture.get(CV_CAP_PROP_FRAME_HEIGHT); + + if (!capture.isOpened()) + { + std::cout << "Failed to open the webcam" << std::endl; + return false; + } + if (frame_width != image_width || frame_height != image_height) + { + std::cout << "Failed to open the webcam with desired resolution" << std::endl; + std::cout << "Defaulting to " << frame_width << "x" << frame_height << std::endl; + } + + this->fps = capture.get(CV_CAP_PROP_FPS); + + // TODO estimate the fx, fy etc. + return true; + +} + +// TODO proper destructors and move constructors + +bool SequenceCapture::OpenVideoFile(std::string video_file, float fx, float fy, float cx, float cy) +{ + latest_frame = cv::Mat(); + latest_gray_frame = cv::Mat(); + + capture.open(video_file); + + this->fps = capture.get(CV_CAP_PROP_FPS); + + is_webcam = false; + is_image_seq = false; + + this->frame_width = capture.get(CV_CAP_PROP_FRAME_WIDTH); + this->frame_height = capture.get(CV_CAP_PROP_FRAME_HEIGHT); + + vid_length = capture.get(CV_CAP_PROP_FRAME_COUNT); + frame_num = 0; + + if (capture.isOpened()) + { + std::cout << "Failed to open the video file at location: " << video_file << std::endl; + return false; + } + + // TODO estimate the fx, fy etc. + + return true; + +} + +void SequenceCapture::OpenImageSequence(std::string directory, float fx, float fy, float cx, float cy) +{ + image_files.clear(); + + boost::filesystem::path image_directory(directory); + std::vector file_in_directory; + copy(boost::filesystem::directory_iterator(image_directory), boost::filesystem::directory_iterator(), back_inserter(file_in_directory)); + + // Sort the images in the directory first + sort(file_in_directory.begin(), file_in_directory.end()); + + std::vector curr_dir_files; + + for (std::vector::const_iterator file_iterator(file_in_directory.begin()); file_iterator != file_in_directory.end(); ++file_iterator) + { + // Possible image extension .jpg and .png + if (file_iterator->extension().string().compare(".jpg") == 0 || file_iterator->extension().string().compare(".png") == 0) + { + curr_dir_files.push_back(file_iterator->string()); + } + } + + image_files = curr_dir_files; + + if (image_files.empty()) + { + std::cout << "No images found in the directory: " << directory << std::endl; + return false; + } + + return true; + +}