cpd  0.5.1
Coherent Point Drift: C++ library for point set registration
transform.hpp
Go to the documentation of this file.
1 // cpd - Coherent Point Drift
2 // Copyright (C) 2017 Pete Gadomski <pete.gadomski@gmail.com>
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License along
15 // with this program; if not, write to the Free Software Foundation, Inc.,
16 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 
24 
25 #pragma once
26 
27 #include <chrono>
28 #include <cpd/gauss_transform.hpp>
29 #include <cpd/matrix.hpp>
30 #include <cpd/normalization.hpp>
31 #include <cpd/utils.hpp>
32 #include <memory>
33 
34 namespace cpd {
35 
37 const size_t DEFAULT_MAX_ITERATIONS = 150;
39 const bool DEFAULT_NORMALIZE = true;
41 const double DEFAULT_OUTLIERS = 0.1;
43 const double DEFAULT_TOLERANCE = 1e-5;
45 const double DEFAULT_SIGMA2 = 0.0;
47 const bool DEFAULT_CORRESPONDENCE = false;
49 const bool DEFAULT_LINKED = true;
50 
52 struct Result {
56  double sigma2;
60  std::chrono::microseconds runtime;
62  size_t iterations;
63 
68  virtual void denormalize(const Normalization& normalization);
69 };
70 
74 template <typename Result>
75 class Transform {
76 public:
77  Transform()
78  : m_correspondence(DEFAULT_CORRESPONDENCE)
79  , m_gauss_transform(GaussTransform::make_default())
80  , m_max_iterations(DEFAULT_MAX_ITERATIONS)
81  , m_normalize(DEFAULT_NORMALIZE)
82  , m_outliers(DEFAULT_OUTLIERS)
83  , m_sigma2(DEFAULT_SIGMA2)
84  , m_tolerance(DEFAULT_TOLERANCE) {}
85 
88  m_correspondence = correspondence;
89  return *this;
90  }
91 
94  std::unique_ptr<GaussTransform> gauss_transform) {
95  m_gauss_transform = std::move(gauss_transform);
96  return *this;
97  }
98 
100  Transform& max_iterations(double max_iterations) {
101  m_max_iterations = max_iterations;
102  return *this;
103  }
104 
106  Transform& normalize(bool normalize) {
107  m_normalize = normalize;
108  return *this;
109  }
110 
112  Transform& outliers(double outliers) {
113  m_outliers = outliers;
114  return *this;
115  }
116 
119  m_sigma2 = sigma2;
120  return *this;
121  }
122 
124  Transform& tolerance(double tolerance) {
125  m_tolerance = tolerance;
126  return *this;
127  }
128 
130  Result run(Matrix fixed, Matrix moving) {
131  auto tic = std::chrono::high_resolution_clock::now();
132  Normalization normalization(fixed, moving, linked());
133  if (m_normalize) {
134  fixed = normalization.fixed;
135  moving = normalization.moving;
136  }
137 
138  this->init(fixed, moving);
139 
140  Result result;
141  result.points = moving;
142  if (m_sigma2 == 0.0) {
143  result.sigma2 = cpd::default_sigma2(fixed, moving);
144  } else if (m_normalize) {
145  result.sigma2 = m_sigma2 / normalization.fixed_scale;
146  } else {
147  result.sigma2 = m_sigma2;
148  }
149 
150  size_t iter = 0;
151  double ntol = m_tolerance + 10.0;
152  double l = 0.;
153  while (iter < m_max_iterations && ntol > m_tolerance &&
154  result.sigma2 > 10 * std::numeric_limits<double>::epsilon()) {
155  Probabilities probabilities = m_gauss_transform->compute(
156  fixed, result.points, result.sigma2, m_outliers);
157  this->modify_probabilities(probabilities);
158 
159  ntol = std::abs((probabilities.l - l) / probabilities.l);
160  l = probabilities.l;
161 
162  result =
163  this->compute_one(fixed, moving, probabilities, result.sigma2);
164  ++iter;
165  }
166 
167  if (m_normalize) {
168  result.denormalize(normalization);
169  }
170  if (m_correspondence) {
171  Probabilities probabilities = m_gauss_transform->compute(
172  fixed, result.points, m_sigma2, m_outliers);
173  result.correspondence = probabilities.correspondence;
174  assert(result.correspondence.rows() > 0);
175  }
176  auto toc = std::chrono::high_resolution_clock::now();
177  result.runtime =
178  std::chrono::duration_cast<std::chrono::microseconds>(toc - tic);
179  result.iterations = iter;
180  return result;
181  }
182 
188  virtual void init(const Matrix& fixed, const Matrix& moving) {}
189 
194  virtual void modify_probabilities(Probabilities& probabilities) const {}
195 
197  virtual Result compute_one(const Matrix& fixed, const Matrix& moving,
198  const Probabilities& probabilities,
199  double sigma2) const = 0;
200 
204  virtual bool linked() const = 0;
205 
206 private:
207  bool m_correspondence;
208  std::unique_ptr<GaussTransform> m_gauss_transform;
209  size_t m_max_iterations;
210  bool m_normalize;
211  double m_outliers;
212  double m_sigma2;
213  double m_tolerance;
214 };
215 } // namespace cpd
const bool DEFAULT_NORMALIZE
Whether points should be normalized by default.
Definition: transform.hpp:39
IndexVector correspondence
The correspondence vector.
Definition: transform.hpp:58
static std::unique_ptr< GaussTransform > make_default()
Returns the default Gauss transform as a unique ptr.
Matrix moving
The moving points.
Definition: normalization.hpp:40
Transform & tolerance(double tolerance)
Sets the final tolerance.
Definition: transform.hpp:124
Utility to scale/offset points to (roughly) conform to unit shape centered at zero.
Transform & correspondence(bool correspondence)
Sets whether the correspondence vector will be computed.
Definition: transform.hpp:87
Basic typedefs for our flavors of Eigen matrices.
const double DEFAULT_TOLERANCE
The default tolerance.
Definition: transform.hpp:43
virtual void modify_probabilities(Probabilities &probabilities) const
Modifies Probabilities in some way.
Definition: transform.hpp:194
double sigma2
The final sigma2 value.
Definition: transform.hpp:56
size_t iterations
The number of iterations.
Definition: transform.hpp:62
Eigen::MatrixXd Matrix
Our base matrix class.
Definition: matrix.hpp:29
const double DEFAULT_OUTLIERS
The default outlier weight.
Definition: transform.hpp:41
The always-present, always-ambiguous utils file.
Eigen::Matrix< Matrix::Index, Eigen::Dynamic, 1 > IndexVector
Typedef for an index vector, used to index other matrices.
Definition: matrix.hpp:35
double default_sigma2(const Matrix &fixed, const Matrix &moving)
Computes the default sigma2 for the given matrices.
Basic correspondence/error calculation between two datasets, using the direct method of the Gauss tra...
Transform & outliers(double outliers)
Sets the outlier tolerance.
Definition: transform.hpp:112
Transform & max_iterations(double max_iterations)
Sets the max iterations for this transform.
Definition: transform.hpp:100
const size_t DEFAULT_MAX_ITERATIONS
The default number of iterations allowed.
Definition: transform.hpp:37
Result run(Matrix fixed, Matrix moving)
Runs this transform for the provided matrices.
Definition: transform.hpp:130
std::chrono::microseconds runtime
The runtime.
Definition: transform.hpp:60
virtual void init(const Matrix &fixed, const Matrix &moving)
Initialize this transform for the provided matrices.
Definition: transform.hpp:188
Transform & sigma2(double sigma2)
Sets the sigma2 value for this transform.
Definition: transform.hpp:118
const double DEFAULT_SIGMA2
The default sigma2.
Definition: transform.hpp:45
Generic coherent point drift transform.
Definition: transform.hpp:75
The result of a generic transform run.
Definition: transform.hpp:52
const bool DEFAULT_LINKED
Are the scalings of the two datasets linked by default?
Definition: transform.hpp:49
Transform & normalize(bool normalize)
Sets whether to normalize the points before running cpd.
Definition: transform.hpp:106
The results of normalizing data to a unit cube (or whatever dimensionality).
Definition: normalization.hpp:30
IndexVector correspondence
The correspondence vector between the two datasets.
Definition: gauss_transform.hpp:42
Matrix fixed
The fixed points.
Definition: normalization.hpp:34
Matrix points
The final moved points.
Definition: transform.hpp:54
Top-level cpd namespace.
Definition: affine.hpp:26
Transform & gauss_transform(std::unique_ptr< GaussTransform > gauss_transform)
Sets the gauss transform.
Definition: transform.hpp:93
const bool DEFAULT_CORRESPONDENCE
Whether correspondence vector should be computed by default.
Definition: transform.hpp:47
double fixed_scale
The scaling factor for the fixed points.
Definition: normalization.hpp:36
Probability matrices produced by comparing two data sets with a GaussTransform.
Definition: gauss_transform.hpp:32
double l
The total error.
Definition: gauss_transform.hpp:40
virtual void denormalize(const Normalization &normalization)
De-normalize this result.