Some plumbing:
- support for 16 bit images - preventing copy constructors for certain utilities classes
This commit is contained in:
parent
45548b097a
commit
7d58b86020
20 changed files with 197 additions and 181 deletions
|
@ -80,5 +80,5 @@ For inquiries about the commercial licensing of the OpenFace toolkit please cont
|
||||||
|
|
||||||
# Final remarks
|
# Final remarks
|
||||||
|
|
||||||
I did my best to make sure that the code runs out of the box but there are always issues and I would be grateful for your understanding that this is research code and not full fledged product. However, if you encounter any problems/bugs/issues please contact me on github or by emailing me at Tadas.Baltrusaitis@cl.cam.ac.uk for any bug reports/questions/suggestions.
|
I did my best to make sure that the code runs out of the box but there are always issues and I would be grateful for your understanding that this is research code and not full fledged product. However, if you encounter any problems/bugs/issues please contact me on github or by emailing me at Tadas.Baltrusaitis@cl.cam.ac.uk for any bug reports/questions/suggestions. I prefer questions and bug reports on github as that provides visibility to others who might be encountering same issues or who have the same questions.
|
||||||
|
|
||||||
|
|
|
@ -79,69 +79,6 @@ vector<string> get_arguments(int argc, char **argv)
|
||||||
return arguments;
|
return arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO rem
|
|
||||||
void create_display_image(const cv::Mat& orig, cv::Mat& display_image, LandmarkDetector::CLNF& clnf_model)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Draw head pose if present and draw eye gaze as well
|
|
||||||
|
|
||||||
// preparing the visualisation image
|
|
||||||
display_image = orig.clone();
|
|
||||||
|
|
||||||
// Creating a display image
|
|
||||||
cv::Mat xs = clnf_model.detected_landmarks(cv::Rect(0, 0, 1, clnf_model.detected_landmarks.rows/2));
|
|
||||||
cv::Mat ys = clnf_model.detected_landmarks(cv::Rect(0, clnf_model.detected_landmarks.rows/2, 1, clnf_model.detected_landmarks.rows/2));
|
|
||||||
double min_x, max_x, min_y, max_y;
|
|
||||||
|
|
||||||
cv::minMaxLoc(xs, &min_x, &max_x);
|
|
||||||
cv::minMaxLoc(ys, &min_y, &max_y);
|
|
||||||
|
|
||||||
double width = max_x - min_x;
|
|
||||||
double height = max_y - min_y;
|
|
||||||
|
|
||||||
int minCropX = max((int)(min_x-width/3.0),0);
|
|
||||||
int minCropY = max((int)(min_y-height/3.0),0);
|
|
||||||
|
|
||||||
int widthCrop = min((int)(width*5.0/3.0), display_image.cols - minCropX - 1);
|
|
||||||
int heightCrop = min((int)(height*5.0/3.0), display_image.rows - minCropY - 1);
|
|
||||||
|
|
||||||
double scaling = 350.0/widthCrop;
|
|
||||||
|
|
||||||
// first crop the image
|
|
||||||
display_image = display_image(cv::Rect((int)(minCropX), (int)(minCropY), (int)(widthCrop), (int)(heightCrop)));
|
|
||||||
|
|
||||||
// now scale it
|
|
||||||
cv::resize(display_image.clone(), display_image, cv::Size(), scaling, scaling);
|
|
||||||
|
|
||||||
// Make the adjustments to points
|
|
||||||
xs = (xs - minCropX)*scaling;
|
|
||||||
ys = (ys - minCropY)*scaling;
|
|
||||||
|
|
||||||
cv::Mat shape = clnf_model.detected_landmarks.clone();
|
|
||||||
|
|
||||||
xs.copyTo(shape(cv::Rect(0, 0, 1, clnf_model.detected_landmarks.rows/2)));
|
|
||||||
ys.copyTo(shape(cv::Rect(0, clnf_model.detected_landmarks.rows/2, 1, clnf_model.detected_landmarks.rows/2)));
|
|
||||||
|
|
||||||
// Do the shifting for the hierarchical models as well
|
|
||||||
for (size_t part = 0; part < clnf_model.hierarchical_models.size(); ++part)
|
|
||||||
{
|
|
||||||
cv::Mat xs = clnf_model.hierarchical_models[part].detected_landmarks(cv::Rect(0, 0, 1, clnf_model.hierarchical_models[part].detected_landmarks.rows / 2));
|
|
||||||
cv::Mat ys = clnf_model.hierarchical_models[part].detected_landmarks(cv::Rect(0, clnf_model.hierarchical_models[part].detected_landmarks.rows / 2, 1, clnf_model.hierarchical_models[part].detected_landmarks.rows / 2));
|
|
||||||
|
|
||||||
xs = (xs - minCropX)*scaling;
|
|
||||||
ys = (ys - minCropY)*scaling;
|
|
||||||
|
|
||||||
cv::Mat shape = clnf_model.hierarchical_models[part].detected_landmarks.clone();
|
|
||||||
|
|
||||||
xs.copyTo(shape(cv::Rect(0, 0, 1, clnf_model.hierarchical_models[part].detected_landmarks.rows / 2)));
|
|
||||||
ys.copyTo(shape(cv::Rect(0, clnf_model.hierarchical_models[part].detected_landmarks.rows / 2, 1, clnf_model.hierarchical_models[part].detected_landmarks.rows / 2)));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//LandmarkDetector::Draw(display_image, clnf_model);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int main (int argc, char **argv)
|
int main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -271,7 +208,10 @@ int main (int argc, char **argv)
|
||||||
open_face_rec.WriteObservation();
|
open_face_rec.WriteObservation();
|
||||||
|
|
||||||
}
|
}
|
||||||
visualizer.ShowObservation();
|
if(face_detections.size() > 0)
|
||||||
|
{
|
||||||
|
visualizer.ShowObservation();
|
||||||
|
}
|
||||||
|
|
||||||
// Grabbing the next frame in the sequence
|
// Grabbing the next frame in the sequence
|
||||||
captured_image = image_reader.GetNextImage();
|
captured_image = image_reader.GetNextImage();
|
||||||
|
|
|
@ -159,6 +159,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="include\ImageCapture.h" />
|
<ClInclude Include="include\ImageCapture.h" />
|
||||||
|
<ClInclude Include="include\ImageManipulationHelpers.h" />
|
||||||
<ClInclude Include="include\RecorderCSV.h" />
|
<ClInclude Include="include\RecorderCSV.h" />
|
||||||
<ClInclude Include="include\RecorderHOG.h" />
|
<ClInclude Include="include\RecorderHOG.h" />
|
||||||
<ClInclude Include="include\RecorderOpenFace.h" />
|
<ClInclude Include="include\RecorderOpenFace.h" />
|
||||||
|
|
|
@ -68,5 +68,8 @@
|
||||||
<ClInclude Include="include\ImageCapture.h">
|
<ClInclude Include="include\ImageCapture.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\ImageManipulationHelpers.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -57,8 +57,6 @@ namespace Utilities
|
||||||
// Default constructor
|
// Default constructor
|
||||||
ImageCapture() {};
|
ImageCapture() {};
|
||||||
|
|
||||||
// TODO block copy, move etc.
|
|
||||||
|
|
||||||
// Opening based on command line arguments
|
// Opening based on command line arguments
|
||||||
bool Open(std::vector<std::string>& arguments);
|
bool Open(std::vector<std::string>& arguments);
|
||||||
|
|
||||||
|
@ -94,9 +92,15 @@ namespace Utilities
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
// Blocking copy and move, as it doesn't make sense to have several readers pointed at the same source
|
||||||
|
ImageCapture & operator= (const ImageCapture& other);
|
||||||
|
ImageCapture & operator= (const ImageCapture&& other);
|
||||||
|
ImageCapture(const ImageCapture&& other);
|
||||||
|
ImageCapture(const ImageCapture& other);
|
||||||
|
|
||||||
// Storing the latest captures
|
// Storing the latest captures
|
||||||
cv::Mat latest_frame;
|
cv::Mat latest_frame;
|
||||||
cv::Mat latest_gray_frame;
|
cv::Mat_<uchar> latest_gray_frame;
|
||||||
|
|
||||||
// Keeping track of how many files are read and the filenames
|
// Keeping track of how many files are read and the filenames
|
||||||
size_t frame_num;
|
size_t frame_num;
|
||||||
|
@ -110,7 +114,6 @@ namespace Utilities
|
||||||
bool image_focal_length_set;
|
bool image_focal_length_set;
|
||||||
bool image_optical_center_set;
|
bool image_optical_center_set;
|
||||||
|
|
||||||
// TODO make sure the error message makes sense
|
|
||||||
bool no_input_specified;
|
bool no_input_specified;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
124
lib/local/Utilities/include/ImageManipulationHelpers.h
Normal file
124
lib/local/Utilities/include/ImageManipulationHelpers.h
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef __IMAGE_MANIPULATION_HELPERS_h_
|
||||||
|
#define __IMAGE_MANIPULATION_HELPERS_h_
|
||||||
|
|
||||||
|
#include <opencv2/core/core.hpp>
|
||||||
|
#include <opencv2/imgproc.hpp>
|
||||||
|
|
||||||
|
namespace Utilities
|
||||||
|
{
|
||||||
|
//===========================================================================
|
||||||
|
// Converting between color spaces and bit depths
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
// Perform the conversion inplace
|
||||||
|
static void ConvertToRGB_8bit(cv::Mat& in_out)
|
||||||
|
{
|
||||||
|
if (in_out.channels() == 3 && in_out.depth() == CV_16U)
|
||||||
|
{
|
||||||
|
in_out = in_out / 256;
|
||||||
|
}
|
||||||
|
else if (in_out.channels() == 4)
|
||||||
|
{
|
||||||
|
if (in_out.depth() == CV_16U)
|
||||||
|
{
|
||||||
|
in_out = in_out / 256;
|
||||||
|
cv::cvtColor(in_out, in_out, CV_BGRA2BGR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cv::cvtColor(in_out, in_out, CV_BGRA2BGR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (in_out.channels() == 1)
|
||||||
|
{
|
||||||
|
if (in_out.depth() == CV_16U)
|
||||||
|
{
|
||||||
|
in_out = in_out / 256;
|
||||||
|
cv::cvtColor(in_out, in_out, CV_GRAY2BGR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cv::cvtColor(in_out, in_out, CV_GRAY2BGR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ConvertToGrayscale_8bit(const cv::Mat& in, cv::Mat& out)
|
||||||
|
{
|
||||||
|
if (in.channels() == 3)
|
||||||
|
{
|
||||||
|
// Make sure it's in a correct format
|
||||||
|
if (in.depth() == CV_16U)
|
||||||
|
{
|
||||||
|
cv::Mat tmp = in / 256;
|
||||||
|
tmp.convertTo(out, CV_8U);
|
||||||
|
cv::cvtColor(out, out, CV_BGR2GRAY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cv::cvtColor(in, out, CV_BGR2GRAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (in.channels() == 4)
|
||||||
|
{
|
||||||
|
if (in.depth() == CV_16U)
|
||||||
|
{
|
||||||
|
cv::Mat tmp = in / 256;
|
||||||
|
tmp.convertTo(out, CV_8U);
|
||||||
|
cv::cvtColor(out, out, CV_BGRA2GRAY);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cv::cvtColor(in, out, CV_BGRA2GRAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (in.depth() == CV_16U)
|
||||||
|
{
|
||||||
|
cv::Mat tmp = in / 256;
|
||||||
|
tmp.convertTo(out, CV_8U);
|
||||||
|
}
|
||||||
|
else if (in.depth() == CV_8U)
|
||||||
|
{
|
||||||
|
out = in.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -68,10 +68,14 @@ namespace Utilities
|
||||||
const cv::Point3f& gazeDirection0, const cv::Point3f& gazeDirection1, const cv::Vec2d& gaze_angle, const std::vector<cv::Point2d>& eye_landmarks2d, const std::vector<cv::Point3d>& eye_landmarks3d,
|
const cv::Point3f& gazeDirection0, const cv::Point3f& gazeDirection1, const cv::Vec2d& gaze_angle, const std::vector<cv::Point2d>& eye_landmarks2d, const std::vector<cv::Point3d>& eye_landmarks3d,
|
||||||
const std::vector<std::pair<std::string, double> >& au_intensities, const std::vector<std::pair<std::string, double> >& au_occurences);
|
const std::vector<std::pair<std::string, double> >& au_intensities, const std::vector<std::pair<std::string, double> >& au_occurences);
|
||||||
|
|
||||||
// TODO have set functions?
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
// Blocking copy and move, as it doesn't make sense to read to write to the same file
|
||||||
|
RecorderCSV & operator= (const RecorderCSV& other);
|
||||||
|
RecorderCSV & operator= (const RecorderCSV&& other);
|
||||||
|
RecorderCSV(const RecorderCSV&& other);
|
||||||
|
RecorderCSV(const RecorderCSV& other);
|
||||||
|
|
||||||
// The actual output file stream that will be written
|
// The actual output file stream that will be written
|
||||||
std::ofstream output_file;
|
std::ofstream output_file;
|
||||||
|
|
||||||
|
|
|
@ -68,6 +68,12 @@ namespace Utilities
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
// Blocking copy and move, as it doesn't make sense to read to write to the same file
|
||||||
|
RecorderHOG & operator= (const RecorderHOG& other);
|
||||||
|
RecorderHOG & operator= (const RecorderHOG&& other);
|
||||||
|
RecorderHOG(const RecorderHOG&& other);
|
||||||
|
RecorderHOG(const RecorderHOG& other);
|
||||||
|
|
||||||
std::ofstream hog_file;
|
std::ofstream hog_file;
|
||||||
|
|
||||||
// Internals for recording
|
// Internals for recording
|
||||||
|
|
|
@ -61,8 +61,6 @@ namespace Utilities
|
||||||
|
|
||||||
~RecorderOpenFace();
|
~RecorderOpenFace();
|
||||||
|
|
||||||
// TODO copy, assignment and move operators? Do not allow
|
|
||||||
|
|
||||||
// Closing and cleaning up the recorder
|
// Closing and cleaning up the recorder
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
|
@ -100,6 +98,12 @@ namespace Utilities
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
// Blocking copy, assignment and move operators, as it does not make sense to save to the same location
|
||||||
|
RecorderOpenFace & operator= (const RecorderOpenFace& other);
|
||||||
|
RecorderOpenFace & operator= (const RecorderOpenFace&& other);
|
||||||
|
RecorderOpenFace(const RecorderOpenFace&& other);
|
||||||
|
RecorderOpenFace(const RecorderOpenFace& other);
|
||||||
|
|
||||||
// Keeping track of what to output and how to output it
|
// Keeping track of what to output and how to output it
|
||||||
const RecorderOpenFaceParameters params;
|
const RecorderOpenFaceParameters params;
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,8 @@ namespace Utilities
|
||||||
// Default constructor
|
// Default constructor
|
||||||
SequenceCapture() {};
|
SequenceCapture() {};
|
||||||
|
|
||||||
// TODO block copy, move etc.
|
// Destructor
|
||||||
|
~SequenceCapture();
|
||||||
|
|
||||||
// Opening based on command line arguments
|
// Opening based on command line arguments
|
||||||
bool Open(std::vector<std::string>& arguments);
|
bool Open(std::vector<std::string>& arguments);
|
||||||
|
@ -104,12 +105,18 @@ namespace Utilities
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
// Blocking copy and move, as it doesn't make sense to have several readers pointed at the same source, and this would cause issues, especially with webcams
|
||||||
|
SequenceCapture & operator= (const SequenceCapture& other);
|
||||||
|
SequenceCapture & operator= (const SequenceCapture&& other);
|
||||||
|
SequenceCapture(const SequenceCapture&& other);
|
||||||
|
SequenceCapture(const SequenceCapture& other);
|
||||||
|
|
||||||
// Used for capturing webcam and video
|
// Used for capturing webcam and video
|
||||||
cv::VideoCapture capture;
|
cv::VideoCapture capture;
|
||||||
|
|
||||||
// Storing the latest captures
|
// Storing the latest captures
|
||||||
cv::Mat latest_frame;
|
cv::Mat latest_frame;
|
||||||
cv::Mat latest_gray_frame;
|
cv::Mat_<uchar> latest_gray_frame;
|
||||||
|
|
||||||
// Keeping track of frame number and the files in the image sequence
|
// Keeping track of frame number and the files in the image sequence
|
||||||
size_t frame_num;
|
size_t frame_num;
|
||||||
|
|
|
@ -55,11 +55,7 @@ namespace Utilities
|
||||||
// The constructor for the visualizer that specifies what to visualize
|
// The constructor for the visualizer that specifies what to visualize
|
||||||
Visualizer(std::vector<std::string> arguments);
|
Visualizer(std::vector<std::string> arguments);
|
||||||
Visualizer(bool vis_track, bool vis_hog, bool vis_align);
|
Visualizer(bool vis_track, bool vis_hog, bool vis_align);
|
||||||
|
|
||||||
//~Visualizer();
|
|
||||||
|
|
||||||
// TODO copy, assignment and move operators? Do not allow
|
|
||||||
|
|
||||||
// Adding observations to the visualizer
|
// Adding observations to the visualizer
|
||||||
|
|
||||||
// Pose related observations
|
// Pose related observations
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "ImageCapture.h"
|
#include "ImageCapture.h"
|
||||||
|
#include "ImageManipulationHelpers.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
// Boost includes
|
// Boost includes
|
||||||
|
@ -177,8 +177,6 @@ bool ImageCapture::Open(std::vector<std::string>& arguments)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO proper destructors and move constructors
|
|
||||||
|
|
||||||
bool ImageCapture::OpenImageFiles(const std::vector<std::string>& image_files, float fx, float fy, float cx, float cy)
|
bool ImageCapture::OpenImageFiles(const std::vector<std::string>& image_files, float fx, float fy, float cx, float cy)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -318,48 +316,6 @@ bool ImageCapture::OpenDirectory(std::string directory, std::string bbox_directo
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO this should be shared somewhere
|
|
||||||
void convertToGrayscale(const cv::Mat& in, cv::Mat& out)
|
|
||||||
{
|
|
||||||
if (in.channels() == 3)
|
|
||||||
{
|
|
||||||
// Make sure it's in a correct format
|
|
||||||
if (in.depth() != CV_8U)
|
|
||||||
{
|
|
||||||
if (in.depth() == CV_16U)
|
|
||||||
{
|
|
||||||
cv::Mat tmp = in / 256;
|
|
||||||
tmp.convertTo(tmp, CV_8U);
|
|
||||||
cv::cvtColor(tmp, out, CV_BGR2GRAY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cv::cvtColor(in, out, CV_BGR2GRAY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (in.channels() == 4)
|
|
||||||
{
|
|
||||||
cv::cvtColor(in, out, CV_BGRA2GRAY);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (in.depth() == CV_16U)
|
|
||||||
{
|
|
||||||
cv::Mat tmp = in / 256;
|
|
||||||
out = tmp.clone();
|
|
||||||
}
|
|
||||||
else if (in.depth() != CV_8U)
|
|
||||||
{
|
|
||||||
in.convertTo(out, CV_8U);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
out = in.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImageCapture::SetCameraIntrinsics(float fx, float fy, float cx, float cy)
|
void ImageCapture::SetCameraIntrinsics(float fx, float fy, float cx, float cy)
|
||||||
{
|
{
|
||||||
// If optical centers are not defined just use center of image
|
// If optical centers are not defined just use center of image
|
||||||
|
@ -389,6 +345,7 @@ void ImageCapture::SetCameraIntrinsics(float fx, float fy, float cx, float cy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns a read image in 3 channel RGB format, also prepares a grayscale frame if needed
|
||||||
cv::Mat ImageCapture::GetNextImage()
|
cv::Mat ImageCapture::GetNextImage()
|
||||||
{
|
{
|
||||||
if (image_files.empty() || frame_num >= image_files.size())
|
if (image_files.empty() || frame_num >= image_files.size())
|
||||||
|
@ -398,14 +355,18 @@ cv::Mat ImageCapture::GetNextImage()
|
||||||
return latest_frame;
|
return latest_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
latest_frame = cv::imread(image_files[frame_num], -1);
|
// Load the image as an 8 bit RGB
|
||||||
|
latest_frame = cv::imread(image_files[frame_num], CV_LOAD_IMAGE_COLOR);
|
||||||
|
|
||||||
if (latest_frame.empty())
|
if (latest_frame.empty())
|
||||||
{
|
{
|
||||||
ERROR_STREAM("Could not open the image: " + image_files[frame_num - 1]);
|
ERROR_STREAM("Could not open the image: " + image_files[frame_num]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Convert the latest frame to 3 channel 8 bit format if it is not in it already
|
||||||
|
//ConvertToRGB_8bit(latest_frame); TODO check
|
||||||
|
|
||||||
image_height = latest_frame.size().height;
|
image_height = latest_frame.size().height;
|
||||||
image_width = latest_frame.size().width;
|
image_width = latest_frame.size().width;
|
||||||
|
|
||||||
|
@ -431,7 +392,7 @@ cv::Mat ImageCapture::GetNextImage()
|
||||||
SetCameraIntrinsics(_fx, _fy, _cx, _cy);
|
SetCameraIntrinsics(_fx, _fy, _cx, _cy);
|
||||||
|
|
||||||
// Set the grayscale frame
|
// Set the grayscale frame
|
||||||
convertToGrayscale(latest_frame, latest_gray_frame);
|
ConvertToGrayscale_8bit(latest_frame, latest_gray_frame);
|
||||||
|
|
||||||
this->name = image_files[frame_num];
|
this->name = image_files[frame_num];
|
||||||
|
|
||||||
|
|
|
@ -46,8 +46,6 @@ using namespace Utilities;
|
||||||
// Default constructor initializes the variables
|
// Default constructor initializes the variables
|
||||||
RecorderCSV::RecorderCSV():output_file(){};
|
RecorderCSV::RecorderCSV():output_file(){};
|
||||||
|
|
||||||
// TODO the other 4 constructors + destructors?
|
|
||||||
|
|
||||||
// Making sure full stop is used for decimal point separation
|
// Making sure full stop is used for decimal point separation
|
||||||
struct fullstop : std::numpunct<char> {
|
struct fullstop : std::numpunct<char> {
|
||||||
char do_decimal_point() const { return '.'; }
|
char do_decimal_point() const { return '.'; }
|
||||||
|
@ -178,7 +176,6 @@ bool RecorderCSV::Open(std::string output_file_name, bool is_sequence, bool outp
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO check if the stream is open
|
|
||||||
void RecorderCSV::WriteLine(int observation_count, double time_stamp, bool landmark_detection_success, double landmark_confidence,
|
void RecorderCSV::WriteLine(int observation_count, double time_stamp, bool landmark_detection_success, double landmark_confidence,
|
||||||
const cv::Mat_<double>& landmarks_2D, const cv::Mat_<double>& landmarks_3D, const cv::Mat_<double>& pdm_model_params, const cv::Vec6d& rigid_shape_params, cv::Vec6d& pose_estimate,
|
const cv::Mat_<double>& landmarks_2D, const cv::Mat_<double>& landmarks_3D, const cv::Mat_<double>& pdm_model_params, const cv::Vec6d& rigid_shape_params, cv::Vec6d& pose_estimate,
|
||||||
const cv::Point3f& gazeDirection0, const cv::Point3f& gazeDirection1, const cv::Vec2d& gaze_angle, const std::vector<cv::Point2d>& eye_landmarks2d, const std::vector<cv::Point3d>& eye_landmarks3d,
|
const cv::Point3f& gazeDirection0, const cv::Point3f& gazeDirection1, const cv::Vec2d& gaze_angle, const std::vector<cv::Point2d>& eye_landmarks2d, const std::vector<cv::Point3d>& eye_landmarks3d,
|
||||||
|
@ -187,7 +184,8 @@ void RecorderCSV::WriteLine(int observation_count, double time_stamp, bool landm
|
||||||
|
|
||||||
if (!output_file.is_open())
|
if (!output_file.is_open())
|
||||||
{
|
{
|
||||||
std::cout << "The output CSV file is not open" << std::endl;
|
std::cout << "The output CSV file is not open, exiting" << std::endl;
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Making sure fixed and not scientific notation is used
|
// Making sure fixed and not scientific notation is used
|
||||||
|
|
|
@ -40,8 +40,6 @@ using namespace Utilities;
|
||||||
// Default constructor initializes the variables
|
// Default constructor initializes the variables
|
||||||
RecorderHOG::RecorderHOG() :hog_file() {};
|
RecorderHOG::RecorderHOG() :hog_file() {};
|
||||||
|
|
||||||
// TODO the other 4 constructors + destructors?
|
|
||||||
|
|
||||||
// Opening the file and preparing the header for it
|
// Opening the file and preparing the header for it
|
||||||
bool RecorderHOG::Open(std::string output_file_name)
|
bool RecorderHOG::Open(std::string output_file_name)
|
||||||
{
|
{
|
||||||
|
|
|
@ -187,7 +187,7 @@ RecorderOpenFace::RecorderOpenFace(const std::string in_filename, RecorderOpenFa
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->media_filename = path(filename).concat(".jpg").string();
|
this->media_filename = path(filename).concat(".bmp").string(); // TODO change back to jpg
|
||||||
metadata_file << "Output image:" << this->media_filename << endl;
|
metadata_file << "Output image:" << this->media_filename << endl;
|
||||||
this->media_filename = (path(record_root) / this->media_filename).string();
|
this->media_filename = (path(record_root) / this->media_filename).string();
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "SequenceCapture.h"
|
#include "SequenceCapture.h"
|
||||||
|
#include "ImageManipulationHelpers.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
@ -248,7 +249,12 @@ bool SequenceCapture::OpenWebcam(int device, int image_width, int image_height,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO proper destructors and move constructors
|
// Destructor that releases the capture
|
||||||
|
SequenceCapture::~SequenceCapture()
|
||||||
|
{
|
||||||
|
if (capture.isOpened())
|
||||||
|
capture.release();
|
||||||
|
}
|
||||||
|
|
||||||
bool SequenceCapture::OpenVideoFile(std::string video_file, float fx, float fy, float cx, float cy)
|
bool SequenceCapture::OpenVideoFile(std::string video_file, float fx, float fy, float cx, float cy)
|
||||||
{
|
{
|
||||||
|
@ -327,7 +333,7 @@ bool SequenceCapture::OpenImageSequence(std::string directory, float fx, float f
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assume all images are same size in an image sequence
|
// Assume all images are same size in an image sequence
|
||||||
cv::Mat tmp = cv::imread(image_files[0], -1);
|
cv::Mat tmp = cv::imread(image_files[0], CV_LOAD_IMAGE_COLOR);
|
||||||
this->frame_height = tmp.size().height;
|
this->frame_height = tmp.size().height;
|
||||||
this->frame_width = tmp.size().width;
|
this->frame_width = tmp.size().width;
|
||||||
|
|
||||||
|
@ -346,47 +352,6 @@ bool SequenceCapture::OpenImageSequence(std::string directory, float fx, float f
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void convertToGrayscale(const cv::Mat& in, cv::Mat& out)
|
|
||||||
{
|
|
||||||
if (in.channels() == 3)
|
|
||||||
{
|
|
||||||
// Make sure it's in a correct format
|
|
||||||
if (in.depth() != CV_8U)
|
|
||||||
{
|
|
||||||
if (in.depth() == CV_16U)
|
|
||||||
{
|
|
||||||
cv::Mat tmp = in / 256;
|
|
||||||
tmp.convertTo(tmp, CV_8U);
|
|
||||||
cv::cvtColor(tmp, out, CV_BGR2GRAY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cv::cvtColor(in, out, CV_BGR2GRAY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (in.channels() == 4)
|
|
||||||
{
|
|
||||||
cv::cvtColor(in, out, CV_BGRA2GRAY);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (in.depth() == CV_16U)
|
|
||||||
{
|
|
||||||
cv::Mat tmp = in / 256;
|
|
||||||
out = tmp.clone();
|
|
||||||
}
|
|
||||||
else if (in.depth() != CV_8U)
|
|
||||||
{
|
|
||||||
in.convertTo(out, CV_8U);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
out = in.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SequenceCapture::SetCameraIntrinsics(float fx, float fy, float cx, float cy)
|
void SequenceCapture::SetCameraIntrinsics(float fx, float fy, float cx, float cy)
|
||||||
{
|
{
|
||||||
// If optical centers are not defined just use center of image
|
// If optical centers are not defined just use center of image
|
||||||
|
@ -450,13 +415,13 @@ cv::Mat SequenceCapture::GetNextFrame()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
latest_frame = cv::imread(image_files[frame_num], -1);
|
latest_frame = cv::imread(image_files[frame_num], CV_LOAD_IMAGE_COLOR);
|
||||||
}
|
}
|
||||||
time_stamp = 0;
|
time_stamp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the grayscale frame
|
// Set the grayscale frame
|
||||||
convertToGrayscale(latest_frame, latest_gray_frame);
|
ConvertToGrayscale_8bit(latest_frame, latest_gray_frame);
|
||||||
|
|
||||||
frame_num++;
|
frame_num++;
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "Visualizer.h"
|
#include "Visualizer.h"
|
||||||
#include "VisualizationUtils.h"
|
#include "VisualizationUtils.h"
|
||||||
#include "RotationHelpers.h"
|
#include "RotationHelpers.h"
|
||||||
|
#include "ImageManipulationHelpers.h"
|
||||||
|
|
||||||
// For drawing on images
|
// For drawing on images
|
||||||
#include <opencv2/imgproc.hpp>
|
#include <opencv2/imgproc.hpp>
|
||||||
|
@ -82,10 +83,15 @@ Visualizer::Visualizer(bool vis_track, bool vis_hog, bool vis_align)
|
||||||
this->vis_align = vis_align;
|
this->vis_align = vis_align;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Setting the image on which to draw
|
// Setting the image on which to draw
|
||||||
void Visualizer::SetImage(const cv::Mat& canvas, float fx, float fy, float cx, float cy)
|
void Visualizer::SetImage(const cv::Mat& canvas, float fx, float fy, float cx, float cy)
|
||||||
{
|
{
|
||||||
|
// Convert the image to 8 bit RGB
|
||||||
captured_image = canvas.clone();
|
captured_image = canvas.clone();
|
||||||
|
ConvertToRGB_8bit(captured_image);
|
||||||
|
|
||||||
this->fx = fx;
|
this->fx = fx;
|
||||||
this->fy = fy;
|
this->fy = fy;
|
||||||
this->cx = cx;
|
this->cx = cx;
|
||||||
|
|
BIN
samples/sample3_16bit_gray.png
Normal file
BIN
samples/sample3_16bit_gray.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 187 KiB |
BIN
samples/sample3_16bit_rgb.png
Normal file
BIN
samples/sample3_16bit_rgb.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 456 KiB |
Binary file not shown.
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 28 KiB |
Loading…
Reference in a new issue