Skip to content

Commit

Permalink
Reworked PriorCost and renamed it to NormCost
Browse files Browse the repository at this point in the history
* Removed the 'weight' parameter. ScaledLoss should be used by the caller instead.
* Added a static Create function, to make it easier to construct the cost object (like it's done in the Ceres tutorial).
* Updated calling code in fit-model-ceres
  • Loading branch information
patrikhuber committed Feb 11, 2023
1 parent c6fe2c7 commit e79da91
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 30 deletions.
29 changes: 15 additions & 14 deletions examples/fit-model-ceres.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,21 +351,22 @@ int main(int argc, char* argv[])
&camera_translation_and_intrinsics[0], &shape_coefficients[0],
&blendshape_coefficients[0]);
}
// Shape prior:
CostFunction* shape_prior_cost =
new AutoDiffCostFunction<fitting::PriorCost, 10 /* num residuals */, 10 /* shape-coeffs */>(
new fitting::PriorCost(10, 35.0));
fitting_costfunction.AddResidualBlock(shape_prior_cost, NULL, &shape_coefficients[0]);
// Shape prior and bounds, for 10 shape coefficients:
CostFunction* shape_prior_cost = fitting::NormCost::Create<10>();
ScaledLoss* shape_prior_scaled_loss =
new ScaledLoss(nullptr, 35.0, Ownership::TAKE_OWNERSHIP);
fitting_costfunction.AddResidualBlock(shape_prior_cost, shape_prior_scaled_loss, &shape_coefficients[0]);
for (int i = 0; i < 10; ++i)
{
fitting_costfunction.SetParameterLowerBound(&shape_coefficients[0], i, -3.0);
fitting_costfunction.SetParameterUpperBound(&shape_coefficients[0], i, 3.0);
}
// Prior and constraints on blendshapes:
CostFunction* blendshapes_prior_cost =
new AutoDiffCostFunction<fitting::PriorCost, 6 /* num residuals */, 6 /* bs-coeffs */>(
new fitting::PriorCost(6, 10.0));
fitting_costfunction.AddResidualBlock(blendshapes_prior_cost, NULL, &blendshape_coefficients[0]);
CostFunction* blendshapes_prior_cost = fitting::NormCost::Create<6>();
LossFunction* blendshapes_prior_scaled_loss =
new ScaledLoss(new SoftLOneLoss(1.0), 10.0, Ownership::TAKE_OWNERSHIP);
fitting_costfunction.AddResidualBlock(blendshapes_prior_cost, blendshapes_prior_scaled_loss,
&blendshape_coefficients[0]);
fitting_costfunction.SetParameterLowerBound(&blendshape_coefficients[0], 0, 0.0);
fitting_costfunction.SetParameterLowerBound(&blendshape_coefficients[0], 1, 0.0);
fitting_costfunction.SetParameterLowerBound(&blendshape_coefficients[0], 2, 0.0);
Expand Down Expand Up @@ -412,11 +413,11 @@ int main(int argc, char* argv[])
&camera_translation_and_intrinsics[0], &shape_coefficients[0],
&blendshape_coefficients[0], &colour_coefficients[0]);
}
// Prior for the colour coefficients:
CostFunction* colour_prior_cost =
new AutoDiffCostFunction<fitting::PriorCost, 10 /* num residuals */, 10 /* colour-coeffs */>(
new fitting::PriorCost(10, 35.0));
fitting_costfunction.AddResidualBlock(colour_prior_cost, NULL, &colour_coefficients[0]);
// Prior and bounds, for 10 colour coefficients:
CostFunction* color_prior_cost = fitting::NormCost::Create<10>();
ScaledLoss* color_prior_scaled_loss =
new ScaledLoss(nullptr, 35.0, Ownership::TAKE_OWNERSHIP);
fitting_costfunction.AddResidualBlock(color_prior_cost, color_prior_scaled_loss, &colour_coefficients[0]);
for (int i = 0; i < 10; ++i)
{
fitting_costfunction.SetParameterLowerBound(&colour_coefficients[0], i, -3.0);
Expand Down
43 changes: 27 additions & 16 deletions include/eos/fitting/ceres_nonlinear.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* File: include/eos/fitting/ceres_nonlinear.hpp
*
* Copyright 2016 Patrik Huber
* Copyright 2016-2023 Patrik Huber
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -30,6 +30,7 @@
#include "glm/gtc/quaternion.hpp"
#include "glm/gtx/transform.hpp"

#include "ceres/ceres.h"
#include "ceres/cubic_interpolation.h"

#include "opencv2/core/core.hpp"
Expand All @@ -51,44 +52,54 @@ std::array<T, 3> get_vertex_colour(const morphablemodel::PcaModel& colour_model,
const T* const colour_coeffs);

/**
* Cost function for a prior on the parameters.
* Cost function that consists of the parameter values themselves as residual.
*
* Prior towards zero (0, 0...) for the parameters.
* Note: The weight is inside the norm, so may not correspond to the "usual"
* formulas. However I think it's equivalent up to a scaling factor, but it
* should be checked.
* If used with a squared loss, this corresponds to an L2 norm constraint on the parameters.
* This class is implemented exactly like Ceres' NormalPrior.
*/
struct PriorCost
struct NormCost
{

/**
* Creates a new prior object with set number of variables and a weight.
* Creates a new NormCost object with set number of parameters.
*
* @param[in] num_variables Number of variables that the parameter vector contains.
* @param[in] weight A weight that the parameters are multiplied with.
* @param[in] num_parameters Number of parameters that the parameter vector contains.
*/
PriorCost(int num_variables, double weight = 1.0) : num_variables(num_variables), weight(weight){};
NormCost(int num_parameters) : num_parameters(num_parameters){};

/**
* Cost function implementation.
*
* @param[in] x An array of parameters.
* @param[in] residual An array of the resulting residuals.
* @return Returns true. The ceres documentation is not clear about that I think.
* @return whether the computation of the residuals was successful. Always returns true.
*/
template <typename T>
bool operator()(const T* const x, T* residual) const
{
for (int i = 0; i < num_variables; ++i)
for (int i = 0; i < num_parameters; ++i)
{
residual[i] = weight * x[i];
residual[i] = x[i];
}
return true;
};

/**
* Factory to hide the construction of the CostFunction object from the client code.
*
* The number of parameters is given as a template argument, so that we can use Ceres' fixed-size
* constructor.
*/
template <int num_parameters>
static ceres::CostFunction* Create()
{
return (new ceres::AutoDiffCostFunction<NormCost, num_parameters /* num residuals */,
num_parameters /* num parameters */>(
new NormCost(num_parameters)));
}

private:
int num_variables;
double weight;
int num_parameters;
};

/**
Expand Down

0 comments on commit e79da91

Please sign in to comment.