Removing code duplication and getting rid of some C++ warnings due to float/double and signed/unsigned mixing.

This commit is contained in:
Tadas Baltrusaitis
2018-09-18 08:24:16 +01:00
parent 6aed4e5e19
commit 630aba9006
16 changed files with 109 additions and 285 deletions

View File

@@ -7,7 +7,7 @@ branches:
only:
- master
- develop
- feature/no-ui-fix
- feature/code_cleanup
compiler:
- gcc

View File

@@ -3,10 +3,11 @@ branches:
only:
- develop
- master
- /^feature/-.*$/
- feature/code_cleanup
max_jobs: 4
configuration:
- Release
- Debug
platform:
- x64
- Win32

View File

@@ -147,7 +147,7 @@ namespace GazeAnalyser_Interop {
// Perform manual projection of points
vector<cv::Point2f> imagePoints_left;
for (int i = 0; i < points_left.size(); ++i)
for (size_t i = 0; i < points_left.size(); ++i)
{
float x = points_left[i].x * fx / points_left[i].z + cx;
float y = points_left[i].y * fy / points_left[i].z + cy;
@@ -156,7 +156,7 @@ namespace GazeAnalyser_Interop {
}
vector<cv::Point2f> imagePoints_right;
for (int i = 0; i < points_right.size(); ++i)
for (size_t i = 0; i < points_right.size(); ++i)
{
float x = points_right[i].x * fx / points_right[i].z + cx;
float y = points_right[i].y * fy / points_right[i].z + cy;

View File

@@ -96,7 +96,7 @@ namespace UtilitiesOF {
std::vector<std::string> image_files_std;
for (size_t i = 0; i < image_files->Count; ++i)
for (int i = 0; i < image_files->Count; ++i)
{
std::string image_file = msclr::interop::marshal_as<std::string>(image_files[i]);
image_files_std.push_back(image_file);

View File

@@ -55,17 +55,6 @@ namespace FaceAnalysis
// The following two methods go hand in hand
void ExtractSummaryStatistics(const cv::Mat_<double>& descriptors, cv::Mat_<double>& sum_stats, bool mean, bool stdev, bool max_min);
void AddDescriptor(cv::Mat_<double>& descriptors, cv::Mat_<double> new_descriptor, int curr_frame, int num_frames_to_keep = 120);
//===========================================================================
// Point set and landmark manipulation functions
//===========================================================================
// Using Kabsch's algorithm for aligning shapes
//This assumes that align_from and align_to are already mean normalised
cv::Matx22f AlignShapesKabsch2D(const cv::Mat_<float>& align_from, const cv::Mat_<float>& align_to);
//=============================================================================
// Basically Kabsch's algorithm but also allows the collection of points to be different in scale from each other
cv::Matx22f AlignShapesWithScale(cv::Mat_<float>& src, cv::Mat_<float> dst);
//============================================================================
// Matrix reading functionality

View File

@@ -703,7 +703,7 @@ void FaceAnalyser::ExtractAllPredictionsOfflineClass(vector<std::pair<std::strin
// Perform a moving average of 7 frames on classifications
int window_size = 7;
vector<double> au_vals_tmp = au_vals;
if(au_vals.size() > (window_size - 1) / 2)
if((int)au_vals.size() > (window_size - 1) / 2)
{
for (size_t i = (window_size - 1)/2; i < au_vals.size() - (window_size - 1) / 2; ++i)
{

View File

@@ -34,6 +34,8 @@
#include <Face_utils.h>
#include <RotationHelpers.h>
// OpenCV includes
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc.hpp>
@@ -131,7 +133,7 @@ namespace FaceAnalysis
extract_rigid_points(source_landmarks, destination_landmarks);
}
cv::Matx22f scale_rot_matrix = AlignShapesWithScale(source_landmarks, destination_landmarks);
cv::Matx22f scale_rot_matrix = Utilities::AlignShapesWithScale(source_landmarks, destination_landmarks);
cv::Matx23f warp_matrix;
warp_matrix(0,0) = scale_rot_matrix(0,0);
@@ -170,7 +172,7 @@ namespace FaceAnalysis
extract_rigid_points(source_landmarks, destination_landmarks);
}
cv::Matx22f scale_rot_matrix = AlignShapesWithScale(source_landmarks, destination_landmarks);
cv::Matx22f scale_rot_matrix = Utilities::AlignShapesWithScale(source_landmarks, destination_landmarks);
cv::Matx23f warp_matrix;
warp_matrix(0,0) = scale_rot_matrix(0,0);
@@ -333,88 +335,6 @@ namespace FaceAnalysis
new_descriptor.copyTo(descriptors.row(row_to_change));
}
//===========================================================================
// Point set and landmark manipulation functions
//===========================================================================
// Using Kabsch's algorithm for aligning shapes
//This assumes that align_from and align_to are already mean normalised
cv::Matx22f AlignShapesKabsch2D(const cv::Mat_<float>& align_from, const cv::Mat_<float>& align_to)
{
cv::SVD svd(align_from.t() * align_to);
// make sure no reflection is there
// corr ensures that we do only rotaitons and not reflections
float d = cv::determinant(svd.vt.t() * svd.u.t());
cv::Matx22f corr = cv::Matx22f::eye();
if (d > 0)
{
corr(1, 1) = 1;
}
else
{
corr(1, 1) = -1;
}
cv::Matx22f R;
cv::Mat(svd.vt.t()*cv::Mat(corr)*svd.u.t()).copyTo(R);
return R;
}
//=============================================================================
// Basically Kabsch's algorithm but also allows the collection of points to be different in scale from each other
cv::Matx22f AlignShapesWithScale(cv::Mat_<float>& src, cv::Mat_<float> dst)
{
int n = src.rows;
// First we mean normalise both src and dst
float mean_src_x = cv::mean(src.col(0))[0];
float mean_src_y = cv::mean(src.col(1))[0];
float mean_dst_x = cv::mean(dst.col(0))[0];
float mean_dst_y = cv::mean(dst.col(1))[0];
cv::Mat_<float> src_mean_normed = src.clone();
src_mean_normed.col(0) = src_mean_normed.col(0) - mean_src_x;
src_mean_normed.col(1) = src_mean_normed.col(1) - mean_src_y;
cv::Mat_<float> dst_mean_normed = dst.clone();
dst_mean_normed.col(0) = dst_mean_normed.col(0) - mean_dst_x;
dst_mean_normed.col(1) = dst_mean_normed.col(1) - mean_dst_y;
// Find the scaling factor of each
cv::Mat src_sq;
cv::pow(src_mean_normed, 2, src_sq);
cv::Mat dst_sq;
cv::pow(dst_mean_normed, 2, dst_sq);
float s_src = sqrt(cv::sum(src_sq)[0] / n);
float s_dst = sqrt(cv::sum(dst_sq)[0] / n);
src_mean_normed = src_mean_normed / s_src;
dst_mean_normed = dst_mean_normed / s_dst;
float s = s_dst / s_src;
// Get the rotation
cv::Matx22f R = AlignShapesKabsch2D(src_mean_normed, dst_mean_normed);
cv::Matx22f A;
cv::Mat(s * R).copyTo(A);
cv::Mat_<float> aligned = (cv::Mat(cv::Mat(A) * src.t())).t();
cv::Mat_<float> offset = dst - aligned;
float t_x = cv::mean(offset.col(0))[0];
float t_y = cv::mean(offset.col(1))[0];
return A;
}
//============================================================================
// Matrix reading functionality
//============================================================================

View File

@@ -58,19 +58,6 @@ namespace LandmarkDetector
// templ is the template we are convolving with, templ_dfts it's dfts at varying windows sizes (optional), _result - the output, method the type of convolution
void matchTemplate_m(const cv::Mat_<float>& input_img, cv::Mat_<double>& img_dft, cv::Mat& _integral_img, cv::Mat& _integral_img_sq, const cv::Mat_<float>& templ, map<int, cv::Mat_<double> >& templ_dfts, cv::Mat_<float>& result, int method);
//===========================================================================
// Point set and landmark manipulation functions
//===========================================================================
// Using Kabsch's algorithm for aligning shapes
//This assumes that align_from and align_to are already mean normalised
cv::Matx22d AlignShapesKabsch2D(const cv::Mat_<double>& align_from, const cv::Mat_<double>& align_to);
cv::Matx22f AlignShapesKabsch2D_f(const cv::Mat_<float>& align_from, const cv::Mat_<float>& align_to);
//=============================================================================
// Basically Kabsch's algorithm but also allows the collection of points to be different in scale from each other
cv::Matx22d AlignShapesWithScale(cv::Mat_<double>& src, cv::Mat_<double> dst);
cv::Matx22f AlignShapesWithScale_f(cv::Mat_<float>& src, cv::Mat_<float> dst);
// Useful utility for grabing a bounding box around a set of 2D landmarks (as a 1D 2n x 1 vector of xs followed by doubles or as an n x 2 vector)
void ExtractBoundingBox(const cv::Mat_<float>& landmarks, float &min_x, float &max_x, float &min_y, float &max_y);

View File

@@ -77,7 +77,7 @@ namespace LandmarkDetector
auto iter = input_output_maps[0].row(k).begin();
float neg_mult = prelu_weights.at<float>(k);
for (size_t i = 0; i < w; ++i)
for (int i = 0; i < w; ++i)
{
float in_val = *iter;
// Apply the PReLU
@@ -105,7 +105,7 @@ namespace LandmarkDetector
cv::Size orig_size = input_maps[0].size();
cv::Mat_<float> input_concat((int)input_maps.size(), input_maps[0].cols * input_maps[0].rows);
for (int in = 0; in < input_maps.size(); ++in)
for (int in = 0; in < (int)input_maps.size(); ++in)
{
cv::Mat_<float> add = input_maps[in];

View File

@@ -354,9 +354,9 @@ void CNN::Read(const string& location)
// Rearrange the flattened kernels into weight matrices for direct convolution computation
cv::Mat_<float> weight_matrix(num_in_maps * kernels_rearr[0][0].rows * kernels_rearr[0][0].cols, num_kernels);
for (size_t k = 0; k < num_kernels; ++k)
for (int k = 0; k < num_kernels; ++k)
{
for (size_t i = 0; i < num_in_maps; ++i)
for (int i = 0; i < num_in_maps; ++i)
{
// Flatten the kernel
cv::Mat_<float> k_flat = kernels_rearr[k][i].t();
@@ -370,7 +370,7 @@ void CNN::Read(const string& location)
// Add a bias term to the weight matrix for efficiency
cv::Mat_<float> W(weight_matrix.rows, weight_matrix.cols + 1, 1.0);
for (size_t k = 0; k < weight_matrix.rows; ++k)
for (int k = 0; k < weight_matrix.rows; ++k)
{
W.at<float>(k, weight_matrix.cols) = biases[k];
}

View File

@@ -263,9 +263,9 @@ void DetectionValidator::Read(string location)
// Rearrange the flattened kernels into weight matrices for direct convolution computation
cv::Mat_<float> weight_matrix(num_in_maps * kernels_rearr[0][0].rows * kernels_rearr[0][0].cols, num_kernels);
for (size_t k = 0; k < num_kernels; ++k)
for (int k = 0; k < num_kernels; ++k)
{
for (size_t i = 0; i < num_in_maps; ++i)
for (int i = 0; i < num_in_maps; ++i)
{
// Flatten the kernel
cv::Mat_<float> k_flat = kernels_rearr[k][i].t();
@@ -279,7 +279,7 @@ void DetectionValidator::Read(string location)
// Add a bias term to the weight matrix for efficiency
cv::Mat_<float> W(weight_matrix.rows, weight_matrix.cols + 1, 1.0);
for (size_t k = 0; k < weight_matrix.rows; ++k)
for (int k = 0; k < weight_matrix.rows; ++k)
{
W.at<float>(k, weight_matrix.cols) = biases[k];
}

View File

@@ -520,7 +520,7 @@ bool DetectLandmarksInImageMultiHypEarlyTerm(const cv::Mat_<uchar> &grayscale_im
// Setup the parameters accordingly
// Only do the first iteration
for (int i = 1; i < params.window_sizes_current.size(); ++i)
for (size_t i = 1; i < params.window_sizes_current.size(); ++i)
{
params.window_sizes_current[i] = 0;
}

View File

@@ -284,163 +284,6 @@ namespace LandmarkDetector
}
}
//===========================================================================
// Point set and landmark manipulation functions
//===========================================================================
// Using Kabsch's algorithm for aligning shapes
//This assumes that align_from and align_to are already mean normalised
cv::Matx22d AlignShapesKabsch2D(const cv::Mat_<double>& align_from, const cv::Mat_<double>& align_to)
{
cv::SVD svd(align_from.t() * align_to);
// make sure no reflection is there
// corr ensures that we do only rotaitons and not reflections
double d = cv::determinant(svd.vt.t() * svd.u.t());
cv::Matx22d corr = cv::Matx22d::eye();
if (d > 0)
{
corr(1, 1) = 1;
}
else
{
corr(1, 1) = -1;
}
cv::Matx22d R;
cv::Mat(svd.vt.t()*cv::Mat(corr)*svd.u.t()).copyTo(R);
return R;
}
cv::Matx22f AlignShapesKabsch2D_f(const cv::Mat_<float>& align_from, const cv::Mat_<float>& align_to)
{
cv::SVD svd(align_from.t() * align_to);
// make sure no reflection is there
// corr ensures that we do only rotaitons and not reflections
float d = cv::determinant(svd.vt.t() * svd.u.t());
cv::Matx22f corr = cv::Matx22f::eye();
if (d > 0)
{
corr(1, 1) = 1;
}
else
{
corr(1, 1) = -1;
}
cv::Matx22f R;
cv::Mat(svd.vt.t()*cv::Mat(corr)*svd.u.t()).copyTo(R);
return R;
}
//=============================================================================
// Basically Kabsch's algorithm but also allows the collection of points to be different in scale from each other
cv::Matx22d AlignShapesWithScale(cv::Mat_<double>& src, cv::Mat_<double> dst)
{
int n = src.rows;
// First we mean normalise both src and dst
double mean_src_x = cv::mean(src.col(0))[0];
double mean_src_y = cv::mean(src.col(1))[0];
double mean_dst_x = cv::mean(dst.col(0))[0];
double mean_dst_y = cv::mean(dst.col(1))[0];
cv::Mat_<double> src_mean_normed = src.clone();
src_mean_normed.col(0) = src_mean_normed.col(0) - mean_src_x;
src_mean_normed.col(1) = src_mean_normed.col(1) - mean_src_y;
cv::Mat_<double> dst_mean_normed = dst.clone();
dst_mean_normed.col(0) = dst_mean_normed.col(0) - mean_dst_x;
dst_mean_normed.col(1) = dst_mean_normed.col(1) - mean_dst_y;
// Find the scaling factor of each
cv::Mat src_sq;
cv::pow(src_mean_normed, 2, src_sq);
cv::Mat dst_sq;
cv::pow(dst_mean_normed, 2, dst_sq);
double s_src = sqrt(cv::sum(src_sq)[0] / n);
double s_dst = sqrt(cv::sum(dst_sq)[0] / n);
src_mean_normed = src_mean_normed / s_src;
dst_mean_normed = dst_mean_normed / s_dst;
double s = s_dst / s_src;
// Get the rotation
cv::Matx22d R = AlignShapesKabsch2D(src_mean_normed, dst_mean_normed);
cv::Matx22d A;
cv::Mat(s * R).copyTo(A);
cv::Mat_<double> aligned = (cv::Mat(cv::Mat(A) * src.t())).t();
cv::Mat_<double> offset = dst - aligned;
double t_x = cv::mean(offset.col(0))[0];
double t_y = cv::mean(offset.col(1))[0];
return A;
}
cv::Matx22f AlignShapesWithScale_f(cv::Mat_<float>& src, cv::Mat_<float> dst)
{
int n = src.rows;
// First we mean normalise both src and dst
float mean_src_x = cv::mean(src.col(0))[0];
float mean_src_y = cv::mean(src.col(1))[0];
float mean_dst_x = cv::mean(dst.col(0))[0];
float mean_dst_y = cv::mean(dst.col(1))[0];
cv::Mat_<float> src_mean_normed = src.clone();
src_mean_normed.col(0) = src_mean_normed.col(0) - mean_src_x;
src_mean_normed.col(1) = src_mean_normed.col(1) - mean_src_y;
cv::Mat_<float> dst_mean_normed = dst.clone();
dst_mean_normed.col(0) = dst_mean_normed.col(0) - mean_dst_x;
dst_mean_normed.col(1) = dst_mean_normed.col(1) - mean_dst_y;
// Find the scaling factor of each
cv::Mat src_sq;
cv::pow(src_mean_normed, 2, src_sq);
cv::Mat dst_sq;
cv::pow(dst_mean_normed, 2, dst_sq);
float s_src = sqrt(cv::sum(src_sq)[0] / n);
float s_dst = sqrt(cv::sum(dst_sq)[0] / n);
src_mean_normed = src_mean_normed / s_src;
dst_mean_normed = dst_mean_normed / s_dst;
float s = s_dst / s_src;
// Get the rotation
cv::Matx22f R = AlignShapesKabsch2D_f(src_mean_normed, dst_mean_normed);
cv::Matx22f A = s * R;
cv::Mat_<float> aligned = (cv::Mat(cv::Mat(A) * src.t())).t();
cv::Mat_<float> offset = dst - aligned;
float t_x = cv::mean(offset.col(0))[0];
float t_y = cv::mean(offset.col(1))[0];
return A;
}
// Useful utility for grabing a bounding box around a set of 2D landmarks (as a 1D 2n x 1 vector of xs followed by doubles or as an n x 2 vector)
void ExtractBoundingBox(const cv::Mat_<float>& landmarks, float &min_x, float &max_x, float &min_y, float &max_y)
{

View File

@@ -36,6 +36,8 @@
#include "Patch_experts.h"
#include "RotationHelpers.h"
// TBB includes
#include <tbb/tbb.h>
@@ -156,7 +158,7 @@ void Patch_experts::Response(vector<cv::Mat_<float> >& patch_expert_responses, c
cv::Mat_<float> reference_shape_2D = (reference_shape.reshape(1, 2).t());
cv::Mat_<float> image_shape_2D = landmark_locations.reshape(1, 2).t();
sim_img_to_ref = AlignShapesWithScale_f(image_shape_2D, reference_shape_2D);
sim_img_to_ref = Utilities::AlignShapesWithScale(image_shape_2D, reference_shape_2D);
sim_ref_to_img = sim_img_to_ref.inv(cv::DECOMP_LU);
float a1 = sim_ref_to_img(0, 0);
@@ -461,21 +463,21 @@ bool Patch_experts::Read(vector<string> intensity_svr_expert_locations, vector<s
}
// Reading in weights/biases/cutoffs
for (int i = 0; i < centers[0].size(); ++i)
for (size_t i = 0; i < centers[0].size(); ++i)
{
double weight;
earlyTermFile >> weight;
early_term_weights.push_back(weight);
}
for (int i = 0; i < centers[0].size(); ++i)
for (size_t i = 0; i < centers[0].size(); ++i)
{
double bias;
earlyTermFile >> bias;
early_term_biases.push_back(bias);
}
for (int i = 0; i < centers[0].size(); ++i)
for (size_t i = 0; i < centers[0].size(); ++i)
{
double cutoff;
earlyTermFile >> cutoff;

View File

@@ -160,5 +160,87 @@ namespace Utilities
}
//===========================================================================
// Point set and landmark manipulation functions
//===========================================================================
// Using Kabsch's algorithm for aligning shapes
//This assumes that align_from and align_to are already mean normalised
static cv::Matx22f AlignShapesKabsch2D(const cv::Mat_<float>& align_from, const cv::Mat_<float>& align_to)
{
cv::SVD svd(align_from.t() * align_to);
// make sure no reflection is there
// corr ensures that we do only rotaitons and not reflections
double d = cv::determinant(svd.vt.t() * svd.u.t());
cv::Matx22f corr = cv::Matx22f::eye();
if (d > 0)
{
corr(1, 1) = 1;
}
else
{
corr(1, 1) = -1;
}
cv::Matx22f R;
cv::Mat(svd.vt.t()*cv::Mat(corr)*svd.u.t()).copyTo(R);
return R;
}
//=============================================================================
// Basically Kabsch's algorithm but also allows the collection of points to be different in scale from each other
static cv::Matx22f AlignShapesWithScale(cv::Mat_<float>& src, cv::Mat_<float> dst)
{
int n = src.rows;
// First we mean normalise both src and dst
float mean_src_x = (float)cv::mean(src.col(0))[0];
float mean_src_y = (float)cv::mean(src.col(1))[0];
float mean_dst_x = (float)cv::mean(dst.col(0))[0];
float mean_dst_y = (float)cv::mean(dst.col(1))[0];
cv::Mat_<float> src_mean_normed = src.clone();
src_mean_normed.col(0) = src_mean_normed.col(0) - mean_src_x;
src_mean_normed.col(1) = src_mean_normed.col(1) - mean_src_y;
cv::Mat_<float> dst_mean_normed = dst.clone();
dst_mean_normed.col(0) = dst_mean_normed.col(0) - mean_dst_x;
dst_mean_normed.col(1) = dst_mean_normed.col(1) - mean_dst_y;
// Find the scaling factor of each
cv::Mat src_sq;
cv::pow(src_mean_normed, 2, src_sq);
cv::Mat dst_sq;
cv::pow(dst_mean_normed, 2, dst_sq);
float s_src = (float)sqrt(cv::sum(src_sq)[0] / n);
float s_dst = (float)sqrt(cv::sum(dst_sq)[0] / n);
src_mean_normed = src_mean_normed / s_src;
dst_mean_normed = dst_mean_normed / s_dst;
float s = s_dst / s_src;
// Get the rotation
cv::Matx22f R = AlignShapesKabsch2D(src_mean_normed, dst_mean_normed);
cv::Matx22f A;
cv::Mat(s * R).copyTo(A);
//cv::Mat_<float> aligned = (cv::Mat(cv::Mat(A) * src.t())).t();
//cv::Mat_<float> offset = dst - aligned;
//float t_x = cv::mean(offset.col(0))[0];
//float t_y = cv::mean(offset.col(1))[0];
return A;
}
}
#endif

View File

@@ -468,7 +468,7 @@ void SequenceCapture::CaptureThread()
}
else if (is_image_seq)
{
if (image_files.empty() || frame_num_int >= image_files.size())
if (image_files.empty() || frame_num_int >= (int)image_files.size())
{
// Indicate lack of success by returning an empty image
tmp_frame = cv::Mat();