PointCorrespondenceDistance.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2013-2015 Imperial College London
5  * Copyright 2013-2015 Andreas Schuh
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifndef MIRTK_PointCorrespondenceDistance_H
21 #define MIRTK_PointCorrespondenceDistance_H
22 
23 #include "mirtk/PointSetDistance.h"
24 
25 #include "mirtk/Array.h"
26 #include "mirtk/EventDelegate.h"
27 #include "mirtk/PointCorrespondence.h"
28 #include "mirtk/RadialErrorFunction.h"
29 
30 #include "mirtk/TestProd.h"
31 
32 
33 namespace mirtk {
34 
35 
36 class EventDelegate;
37 
38 
39 /**
40  * Distance error of established/known point correspondences
41  *
42  * This distance term evaluates the residual registration error of each
43  * transformed target point relative to its corresponding source point.
44  * It is a generic point set distance measure which can be used for many
45  * types of point sets, including in particular point clouds, curves, and
46  * surface meshes.
47  *
48  * A corresponding point locator is utilized to find the corresponding point
49  * in the source data set. This can be, for example, the closest point in the
50  * source data set, the closest point on the source surface, or the matched
51  * source data set point which is closest in terms of some other feature than
52  * just Euclidean distance of the points. A special case of point correspondence
53  * is one which remains fixed and maps the i-th point in the target data set to
54  * the j-th point in the source data set. This is the case for manually labeled
55  * fiducial markers (cf. FiducialRegistrationError) or pre-computed
56  * correspondence maps using an external point/surface matching algorithm.
57  *
58  * The Euclidean distance of corresponding points is further weighted by an
59  * error function which may non-linearly penalize established correspondences
60  * and reduce influence of outliers or incorrect matches in order to improve
61  * the robustness of the point set registration.
62  */
64 {
66 
67  FRIEND_TEST(PointCorrespondenceDistance, FuzzyMatch);
68 
69  // ---------------------------------------------------------------------------
70  // Attributes
71 protected:
72 
73  /// Forwards correspondence map event messages to observers of energy term
75 
76  /// Approximate distance between sampled target points
77  mirtkPublicAttributeMacro(double, TargetSampleDistance);
78 
79  /// Approximate distance between sampled source points
80  mirtkPublicAttributeMacro(double, SourceSampleDistance);
81 
82  /// Maximum number of target samples used
83  mirtkPublicAttributeMacro(int, NumberOfTargetSamples);
84 
85  /// Maximum number of target samples used
86  mirtkPublicAttributeMacro(int, NumberOfSourceSamples);
87 
88  /// Indices of sampled target points
89  mirtkAttributeMacro(Array<int>, TargetSample);
90 
91  /// Indices of sampled source points
92  mirtkAttributeMacro(Array<int>, SourceSample);
93 
94  /// Number of Update calls between reevaluation of correspondences
95  mirtkPublicAttributeMacro(int, UpdatePeriod);
96 
97  /// Number of invocations of Update modulo _UpdatePeriod
98  mirtkAttributeMacro(int, NumberOfUpdates);
99 
100  /// Point correspondence map
101  mirtkComponentMacro(PointCorrespondence, Correspondence);
102 
103  /// Polydata registration error weight function
105 
106  /// Whether to evaluate error of target points and corresponding source points
107  mirtkPublicAttributeMacro(bool, EvaluateTargetError);
108 
109  /// Whether to evaluate error of source points and corresponding target points
110  mirtkPublicAttributeMacro(bool, EvaluateSourceError);
111 
112  // ---------------------------------------------------------------------------
113  // Construction/Destruction
114 
115 protected:
116 
117  /// Construct distance with given default point correspondence type and error function
118  PointCorrespondenceDistance(const char *, double,
120  RadialErrorFunction * = NULL);
121 
122 public:
123 
124  /// Constructor
125  PointCorrespondenceDistance(const char * = "", double = 1.0);
126 
127  /// Copy constructor
129 
130  /// Assignment operator
132 
133  /// Destructor
135 
136  // ---------------------------------------------------------------------------
137  // Parameters
138 
139 protected:
140 
141  /// Set parameter value from string
142  virtual bool SetWithoutPrefix(const char *, const char *);
143 
144 public:
145 
146  // Do not hide other overload
148 
149  /// Get parameter key/value as string map
150  virtual ParameterList Parameter() const;
151 
152  // ---------------------------------------------------------------------------
153  // Initialization/update
154 
155 protected:
156 
157  /// Sample point sets
158  void SamplePoints();
159 
160 public:
161 
162  /// Initialize error measure once input and parameters have been set
163  virtual void Initialize();
164 
165  /// Reinitialize error measure after change of input topology
166  virtual void Reinitialize();
167 
168  /// Update moving input points and internal state of distance measure
169  virtual void Update(bool = true);
170 
171  /// Update energy term after convergence
172  virtual bool Upgrade();
173 
174  // ---------------------------------------------------------------------------
175  // Evaluation
176 
177  /// Whether to evaluate target to source error
178  bool DoEvaluateTargetError() const;
179 
180  /// Whether to evaluate source to target error
181  bool DoEvaluateSourceError() const;
182 
183 protected:
184 
185  /// Evaluate unweighted energy term
186  virtual double Evaluate();
187 
188  /// Compute non-parametric gradient w.r.t the given point set
189  ///
190  /// \param[in] source Set of transformed fiducial points.
191  /// \param[out] gradient Non-parametric fiducial registration error gradient.
192  virtual void NonParametricGradient(const RegisteredPointSet *source,
193  GradientType *gradient);
194 
195  /// Convert non-parametric gradient of point set distance measure into
196  /// gradient w.r.t transformation parameters
197  ///
198  /// This function calls Transformation::ParametricGradient of the
199  /// transformation to apply the chain rule in order to obtain the gradient
200  /// of the distance measure w.r.t the transformation parameters.
201  /// It adds the weighted gradient to the final registration energy gradient.
202  ///
203  /// \param[in] source Transformed point set.
204  /// \param[in] np_gradient Point-wise non-parametric gradient.
205  /// \param[inout] gradient Gradient to which the computed parametric gradient
206  /// is added, after multiplication by the given \p weight.
207  /// \param[in] weight Weight of point set distance measure.
208  virtual void ParametricGradient(const RegisteredPointSet *source,
209  const GradientType *np_gradient,
210  double *gradient,
211  double weight);
212 
213  /// Evaluate gradient of point distance measure
214  ///
215  /// This function calls the virtual NonParametricGradient function to be
216  /// implemented by subclasses for each transformed input data set to obtain
217  /// the gradient of the point set distance measure. It then converts this gradient
218  /// into a gradient w.r.t the transformation parameters using the ParametricGradient.
219  ///
220  /// If both target and source data sets are transformed by different transformations,
221  /// the resulting gradient vector contains first the derivative values w.r.t
222  /// the parameters of the target transformation followed by those computed
223  /// w.r.t the parameters of the source transformation. If both data sets are
224  /// transformed by the same transformation, the sum of the derivative values
225  /// is added to the resulting gradient vector. This is in particular the case
226  /// for a velocity based transformation model which is applied to deform both
227  /// data sets "mid-way". Otherwise, only one input data set is transformed
228  /// (usually the target) and the derivative values of only the respective
229  /// transformation parameters added to the gradient vector.
230  ///
231  /// \sa NonParametricGradient, ParametricGradient
232  ///
233  /// \param[in,out] gradient Gradient to which the computed gradient of the
234  /// point set distance measure is added after
235  /// multiplying by the given similarity \p weight.
236  /// \param[in] step Step length for finite differences (unused).
237  /// \param[in] weight Weight of point set distance measure.
238  void EvaluateGradient(double *gradient, double step, double weight);
239 
240  /// Forward point correspondence map event
241  void ForwardEvent(Observable *, Event, const void *);
242 
243  // ---------------------------------------------------------------------------
244  // Debugging
245 public:
246 
247  /// Write input of data fidelity term
248  virtual void WriteDataSets(const char *, const char *, bool = true) const;
249 
250  /// Write gradient of data fidelity term w.r.t each transformed input
251  virtual void WriteGradient(const char *, const char *) const;
252 
253 protected:
254 
255  /// Write given input data set to specified file
256  virtual void WriteDataSet(const char *,
257  const RegisteredPointSet *,
258  const Array<int> &,
259  const PointCorrespondence *) const;
260 
261 };
262 
263 
264 } // namespace mirtk
265 
266 #endif // MIRTK_PointCorrespondenceDistance_H
mirtkComponentMacro(PointCorrespondence, Correspondence)
Point correspondence map.
virtual void WriteGradient(const char *, const char *) const
Write gradient of data fidelity term w.r.t each transformed input.
virtual bool Upgrade()
Update energy term after convergence.
virtual void Initialize()
Initialize error measure once input and parameters have been set.
virtual ~PointCorrespondenceDistance()
Destructor.
virtual ParameterList Parameter() const
Get parameter key/value as string map.
virtual void NonParametricGradient(const RegisteredPointSet *source, GradientType *gradient)
virtual void Update(bool=true)
Update moving input points and internal state of distance measure.
Array< Pair< string, string > > ParameterList
Ordered list of parameter name/value pairs.
Definition: Object.h:38
void EvaluateGradient(double *gradient, double step, double weight)
PointCorrespondenceDistance(const char *, double, PointCorrespondence *, RadialErrorFunction *=NULL)
Construct distance with given default point correspondence type and error function.
mirtkPublicAttributeMacro(double, TargetSampleDistance)
Approximate distance between sampled target points.
virtual void ParametricGradient(const RegisteredPointSet *source, const GradientType *np_gradient, double *gradient, double weight)
virtual ParameterList Parameter() const
Get parameter key/value as string map.
Definition: IOConfig.h:41
Point correspondence distance measure.
Definition: EnergyMeasure.h:61
virtual void WriteDataSets(const char *, const char *, bool=true) const
Write input of data fidelity term.
virtual void Reinitialize()
Reinitialize error measure after change of input topology.
virtual double Evaluate()
Evaluate unweighted energy term.
void SamplePoints()
Sample point sets.
bool DoEvaluateTargetError() const
Whether to evaluate target to source error.
Event
Events that can be observed.
Definition: Event.h:32
bool DoEvaluateSourceError() const
Whether to evaluate source to target error.
PointCorrespondenceDistance & operator=(const PointCorrespondenceDistance &)
Assignment operator.
virtual bool SetWithoutPrefix(const char *, const char *)
Set parameter value from string.
EventDelegate _EventDelegate
Forwards correspondence map event messages to observers of energy term.
virtual void WriteDataSet(const char *, const RegisteredPointSet *, const Array< int > &, const PointCorrespondence *) const
Write given input data set to specified file.
void ForwardEvent(Observable *, Event, const void *)
Forward point correspondence map event.
mirtkAttributeMacro(Array< int >, TargetSample)
Indices of sampled target points.