198 lines
6.9 KiB
C++
Executable File
198 lines
6.9 KiB
C++
Executable File
// ----------------------------------------------------------------------------
|
|
// - Open3D: www.open3d.org -
|
|
// ----------------------------------------------------------------------------
|
|
// Copyright (c) 2018-2023 www.open3d.org
|
|
// SPDX-License-Identifier: MIT
|
|
// ----------------------------------------------------------------------------
|
|
// @author Ignacio Vizzo [ivizzo@uni-bonn.de]
|
|
//
|
|
// Copyright (c) 2020 Ignacio Vizzo, Cyrill Stachniss, University of Bonn.
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#pragma once
|
|
|
|
namespace open3d {
|
|
namespace pipelines {
|
|
namespace registration {
|
|
|
|
/// \class RobustKernel
|
|
///
|
|
/// Base class that models a robust kernel for outlier rejection. The virtual
|
|
/// function Weight(double residual); must be implemented in derived classes.
|
|
/// This method will be only difference between different types of kernels and
|
|
/// can be easily extended.
|
|
///
|
|
/// The kernels implemented so far and the notation has been inspired by the
|
|
/// publication: "Analysis of Robust Functions for Registration Algorithms",
|
|
/// Philippe Babin et al.
|
|
///
|
|
/// We obtain the correspondendent weights for each residual and turn the
|
|
/// non-linear least-square problem into a IRSL (Iteratively Reweighted
|
|
/// Least-Squares) problem. Changing the weight of each residual is equivalent
|
|
/// to changing the robust kernel used for outlier rejection.
|
|
///
|
|
/// The different loss functions will only impact in the weight for each
|
|
/// residual during the optimization step. For more information please see also:
|
|
/// “Adaptive Robust Kernels for Non-Linear Least Squares Problems”, N.
|
|
/// Chebrolu et al.
|
|
/// The weight w(r) for a given residual `r` and a given loss function `p(r)` is
|
|
/// computed as follow:
|
|
/// w(r) = (1 / r) * (dp(r) / dr) , for all r
|
|
/// Therefore, the only impact of the choice on the kernel is through its first
|
|
/// order derivate.
|
|
class RobustKernel {
|
|
public:
|
|
virtual ~RobustKernel() = default;
|
|
/// Obtain the weight for the given residual according to the robust kernel
|
|
/// model. This method must be implemented in the derived classes that model
|
|
/// the different robust kernels.
|
|
///
|
|
/// \param residual Residual value obtained during the optimization step.
|
|
virtual double Weight(double residual) const = 0;
|
|
};
|
|
|
|
/// \class L2Loss
|
|
///
|
|
/// Classical loss function used for outlier rejection.
|
|
///
|
|
/// The loss p(r) for a given residual 'r' is computed as follow:
|
|
/// p(r) = r^2 / 2
|
|
class L2Loss : public RobustKernel {
|
|
public:
|
|
/// The weight w(r) for a given residual 'r' is computed as follow:
|
|
/// w(r) = 1.0, for all r
|
|
///
|
|
/// \param residual [ignored]
|
|
double Weight(double residual) const override;
|
|
};
|
|
|
|
/// \class L1Loss
|
|
///
|
|
/// L1 loss function used for outlier rejection.
|
|
///
|
|
/// The loss p(r) for a given residual 'r' is computed as follow:
|
|
// p(r) = abs(r)
|
|
class L1Loss : public RobustKernel {
|
|
public:
|
|
/// The weight w(r) for a given residual 'r' is computed as follow:
|
|
/// w(r) = 1.0 / abs(r), for all r
|
|
///
|
|
/// \param residual Residual value obtained during the optimization step.
|
|
double Weight(double residual) const override;
|
|
};
|
|
|
|
/// \class HuberLoss
|
|
///
|
|
/// HuberLoss loss function used for outlier rejection.
|
|
///
|
|
/// The loss p(r) for a given residual 'r' is computed as follow:
|
|
/// p(r) = r^2 for abs(r) <= k,
|
|
/// p(r) = k^2 * (abs(r) - k/2) for abs(r) > k
|
|
///
|
|
/// For more information: http://en.wikipedia.org/wiki/Huber_Loss_Function
|
|
class HuberLoss : public RobustKernel {
|
|
public:
|
|
/// \brief Parametrized Constructor.
|
|
///
|
|
/// \param k Is the scaling parameter of the huber loss function. 'k'
|
|
/// corresponds to 'delta' on this page:
|
|
/// http://en.wikipedia.org/wiki/Huber_Loss_Function
|
|
explicit HuberLoss(double k) : k_(k) {}
|
|
|
|
/// The weight w(r) for a given residual 'r' is computed as follow:
|
|
/// w(r) = 1.0 for abs(r) <= k,
|
|
/// w(r) = k / abs(r) for abs(r) > k
|
|
/// Where k Is the scaling parameter of the loss function.
|
|
///
|
|
/// \param residual Residual value obtained during the optimization step.
|
|
double Weight(double residual) const override;
|
|
|
|
public:
|
|
/// Scaling parameter.
|
|
double k_;
|
|
};
|
|
|
|
/// \class CauchyLoss
|
|
///
|
|
/// CauchyLoss loss function used for outlier rejection.
|
|
///
|
|
/// The loss p(r) for a given residual 'r' is computed as follow:
|
|
/// p(r) = (k^2 / 2) * log(1 + (r / k)^2), for all r
|
|
class CauchyLoss : public RobustKernel {
|
|
public:
|
|
/// \brief Parametrized Constructor.
|
|
///
|
|
/// \param k Is the scaling parameter of the loss function.
|
|
explicit CauchyLoss(double k) : k_(k) {}
|
|
|
|
/// The weight w(r) for a given residual 'r' is computed as follow:
|
|
/// w(r) = 1 / (1 + (r / k)^2)
|
|
/// Where k Is the scaling parameter of the loss function.
|
|
///
|
|
/// \param residual Residual value obtained during the optimization step.
|
|
double Weight(double residual) const override;
|
|
|
|
public:
|
|
/// Scaling parameter.
|
|
double k_;
|
|
};
|
|
|
|
/// \class GMLoss
|
|
///
|
|
/// German-McClure loss function used for outlier rejection.
|
|
///
|
|
/// The loss p(r) for a given residual 'r' is computed as follow:
|
|
/// p(r) = (r^2 / 2) / (1 + (r / k)^2), for all r
|
|
class GMLoss : public RobustKernel {
|
|
public:
|
|
/// \brief Parametrized Constructor.
|
|
///
|
|
/// \param k Is the scaling parameter of the loss function.
|
|
explicit GMLoss(double k) : k_(k) {}
|
|
|
|
/// The weight w(r) for a given residual 'r' is computed as follow:
|
|
/// w(r) = k / (k + r^2)^2, for all r
|
|
/// Where k Is the scaling parameter of the loss function.
|
|
///
|
|
/// \param residual Residual value obtained during the optimization step.
|
|
double Weight(double residual) const override;
|
|
|
|
public:
|
|
/// Scaling parameter.
|
|
double k_;
|
|
};
|
|
|
|
/// \class TukeyLoss
|
|
///
|
|
/// This is the so called Tukey loss function which aggressively attempts to
|
|
/// suppress large errors.
|
|
///
|
|
/// The loss p(r) for a given residual 'r' is computed as follow:
|
|
///
|
|
/// p(r) = k^2 * (1 - (1 - r / k^2)^3 ) / 2 for abs(r) <= k,
|
|
/// p(r) = k^2 / 2 for abs(r) > k.
|
|
///
|
|
class TukeyLoss : public RobustKernel {
|
|
public:
|
|
/// \brief Parametrized Constructor.
|
|
///
|
|
/// \param k Is a running constant for the Tukey Loss function.
|
|
explicit TukeyLoss(double k) : k_(k) {}
|
|
|
|
public:
|
|
/// The weight w(r) for a given residual 'r' is computed as follow:
|
|
/// p(r) = (1 - (r / k)^2 )^2 for abs(r) <= k,
|
|
/// p(r) = 0.0 for abs(r) > k.
|
|
/// Where k Is the scaling parameter of the loss function.
|
|
///
|
|
/// \param residual Residual value obtained during the optimization step.
|
|
double Weight(double residual) const override;
|
|
|
|
public:
|
|
double k_;
|
|
};
|
|
|
|
} // namespace registration
|
|
} // namespace pipelines
|
|
} // namespace open3d
|