File: itkAdvancedImageMomentsCalculator.h

package info (click to toggle)
elastix 5.2.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 42,480 kB
  • sloc: cpp: 68,403; lisp: 4,118; python: 1,013; xml: 182; sh: 177; makefile: 33
file content (342 lines) | stat: -rw-r--r-- 12,981 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/
#ifndef itkAdvancedImageMomentsCalculator_h
#define itkAdvancedImageMomentsCalculator_h

#include "itkInPlaceImageFilter.h"
#include "itkBinaryThresholdImageFilter.h"
#include "itkAffineTransform.h"
#include "itkImage.h"
#include "itkImageMaskSpatialObject.h"
#include "itkImageGridSampler.h"
#include "itkImageFullSampler.h"

#include <vnl/vnl_vector_fixed.h>
#include <vnl/vnl_matrix_fixed.h>
#include <vnl/vnl_diag_matrix.h>

#include "itkMultiThreaderBase.h"

#include <vector>

namespace itk
{
/** \class AdvancedImageMomentsCalculator
 * \brief Compute moments of an n-dimensional image.
 *
 * This class provides methods for computing the moments and related
 * properties of a single-echo image.  Computing the (non-central)
 * moments of a large image can easily take a million times longer
 * than computing the various other values derived from them, so we
 * compute the moments only on explicit request, and save their values
 * (in an AdvancedImageMomentsCalculator object) for later retrieval by the user.
 *
 * The non-central moments computed by this class are not really
 * intended for general use and are therefore in index coordinates;
 * that is, we pretend that the index that selects a particular
 * pixel also equals its physical coordinates.  The center of gravity,
 * central moments, principal moments and principal axes are all
 * more generally useful and are computed in the physical coordinates
 * defined by the Origin and Spacing parameters of the image.
 *
 * The methods that return values return the values themselves rather
 * than references because the cost is small compared to the cost of
 * computing the moments and doing so simplifies memory management for
 * the caller.
 *
 * \ingroup Operators
 *
 * \todo It's not yet clear how multi-echo images should be handled here.
 * \ingroup ITKImageStatistics
 */
template <typename TImage>
class ITK_TEMPLATE_EXPORT AdvancedImageMomentsCalculator : public Object
{
public:
  /** Standard class typedefs. */
  using Self = AdvancedImageMomentsCalculator<TImage>;
  using Superclass = Object;
  using Pointer = SmartPointer<Self>;
  using ConstPointer = SmartPointer<const Self>;

  /** Method for creation through the object factory. */
  itkNewMacro(Self);

  /** Run-time type information (and related methods). */
  itkTypeMacro(AdvancedImageMomentsCalculator, Object);

  /** Extract the dimension of the image. */
  itkStaticConstMacro(ImageDimension, unsigned int, TImage::ImageDimension);

  /** Standard scalar type within this class. */
  using ScalarType = double;

  /** Standard vector type within this class. */
  using VectorType = Vector<ScalarType, Self::ImageDimension>;

  /** Spatial Object type within this class. */
  using SpatialObjectType = ImageMaskSpatialObject<Self::ImageDimension>;

  /** Spatial Object member types used within this class. */
  using SpatialObjectPointer = typename SpatialObjectType::Pointer;
  using SpatialObjectConstPointer = typename SpatialObjectType::ConstPointer;

  /** Standard matrix type within this class. */
  using MatrixType = Matrix<ScalarType, Self::ImageDimension, Self::ImageDimension>;

  /** Standard image type within this class. */
  using ImageType = TImage;

  /** Standard image type pointer within this class. */
  using ImagePointer = typename ImageType::Pointer;
  using ImageConstPointer = typename ImageType::ConstPointer;

  /** Affine transform for mapping to and from principal axis */
  using AffineTransformType = AffineTransform<double, Self::ImageDimension>;
  using AffineTransformPointer = typename AffineTransformType::Pointer;

  /** Set the input image. */
  virtual void
  SetImage(const ImageType * image)
  {
    if (m_Image != image)
    {
      m_Image = image;
      this->Modified();
      m_Valid = false;
    }
  }

  /** Set the spatial object mask. */
  virtual void
  SetSpatialObjectMask(const ImageMaskSpatialObject<Self::ImageDimension> * so)
  {
    if (m_SpatialObjectMask != so)
    {
      m_SpatialObjectMask = so;
      this->Modified();
      m_Valid = false;
    }
  }

  /** Compute moments of a new or modified image.
   * This method computes the moments of the image given as a
   * parameter and stores them in the object.  The values of these
   * moments and related parameters can then be retrieved by using
   * other methods of this object. */
  /** The multi-threading implementation. */
  void
  Compute();

  /** The main functions that performs the single thread computation. */
  void
  ComputeSingleThreaded();
  /** Return the total mass (or zeroth moment) of an image.
   * This method returns the sum of pixel intensities (also known as
   * the zeroth moment or the total mass) of the image whose moments
   * were last computed by this object. */
  ScalarType
  GetTotalMass() const;

  /** Return first moments about origin, in index coordinates.
   * This method returns the first moments around the origin of the
   * image whose moments were last computed by this object.  For
   * simplicity, these moments are computed in index coordinates
   * rather than physical coordinates. */
  VectorType
  GetFirstMoments() const;

  /** Return second moments about origin, in index coordinates.
   * This method returns the second moments around the origin
   * of the image whose moments were last computed by this object.
   * For simplicity, these moments are computed in index coordinates
   * rather than physical coordinates. */
  MatrixType
  GetSecondMoments() const;

  /** Return center of gravity, in physical coordinates.
   * This method returns the center of gravity of the image whose
   * moments were last computed by this object.  The center of
   * gravity is computed in physical coordinates. */
  VectorType
  GetCenterOfGravity() const;

  /** Return second central moments, in physical coordinates.
   * This method returns the central second moments of the image
   * whose moments were last computed by this object.  The central
   * moments are computed in physical coordinates. */
  MatrixType
  GetCentralMoments() const;

  /** Return principal moments, in physical coordinates.
   * This method returns the principal moments of the image whose
   * moments were last computed by this object.  The moments are
   * returned as a vector, with the principal moments ordered from
   * smallest to largest.  The moments are computed in physical
   * coordinates.   */
  VectorType
  GetPrincipalMoments() const;

  /** Return principal axes, in physical coordinates.
   * This method returns the principal axes of the image whose
   * moments were last computed by this object.  The moments are
   * returned as an orthogonal matrix, each row of which corresponds
   * to one principal moment; for example, the principal axis
   * corresponding to the smallest principal moment is the vector
   * m[0], where m is the value returned by this method.  The matrix
   * of principal axes is guaranteed to be a proper rotation; that
   * is, to have determinant +1 and to preserve parity.  (Unless you
   * have foolishly made one or more of the spacing values negative;
   * in that case, _you_ get to figure out the consequences.)  The
   * moments are computed in physical coordinates. */
  MatrixType
  GetPrincipalAxes() const;

  /** Get the affine transform from principal axes to physical axes
   * This method returns an affine transform which transforms from
   * the principal axes coordinate system to physical coordinates. */
  AffineTransformPointer
  GetPrincipalAxesToPhysicalAxesTransform() const;

  /** Get the affine transform from physical axes to principal axes
   * This method returns an affine transform which transforms from
   * the physical coordinate system to the principal axes coordinate
   * system. */
  AffineTransformPointer
  GetPhysicalAxesToPrincipalAxesTransform() const;

  /** Set the number of threads. */
  void
  SetNumberOfWorkUnits(ThreadIdType numberOfThreads)
  {
    this->m_Threader->SetNumberOfWorkUnits(numberOfThreads);
  }

  virtual void
  BeforeThreadedCompute();

  virtual void
  AfterThreadedCompute();

  using ImageGridSamplerType = itk::ImageGridSampler<ImageType>;
  //  using ImageGridSamplerType = itk::ImageFullSampler< ImageType >    ;
  using ImageGridSamplerPointer = typename ImageGridSamplerType::Pointer;
  using ImageSampleContainerType = typename ImageGridSamplerType ::ImageSampleContainerType;
  using ImageSampleContainerPointer = typename ImageSampleContainerType::Pointer;

  virtual void
  SampleImage(ImageSampleContainerPointer & sampleContainer);

  using BinaryThresholdImageFilterType = itk::BinaryThresholdImageFilter<TImage, TImage>;
  using InputPixelType = typename TImage::PixelType;

  /** Set some parameters. */
  itkSetMacro(NumberOfSamplesForCenteredTransformInitialization, SizeValueType);
  itkSetMacro(LowerThresholdForCenterGravity, InputPixelType);
  itkSetMacro(CenterOfGravityUsesLowerThreshold, bool);

protected:
  AdvancedImageMomentsCalculator();
  ~AdvancedImageMomentsCalculator() override = default;
  void
  PrintSelf(std::ostream & os, Indent indent) const override;

  /** Typedef for multi-threading. */
  using ThreadInfoType = MultiThreaderBase::WorkUnitInfo;

  /** Launch MultiThread Compute. */
  void
  LaunchComputeThreaderCallback() const;

  /** Compute threader callback function. */
  static ITK_THREAD_RETURN_FUNCTION_CALL_CONVENTION
  ComputeThreaderCallback(void * arg);

  /** The threaded implementation of Compute(). */
  virtual void
  ThreadedCompute(ThreadIdType threadID);

  /** Initialize some multi-threading related parameters. */
  virtual void
  InitializeThreadingParameters();

  /** To give the threads access to all member variables and functions. */
  struct MultiThreaderParameterType
  {
    Self * st_Self;
  };

  struct ComputePerThreadStruct
  {
    /**  Used for accumulating variables. */
    ScalarType    st_M0; // Zeroth moment for threading
    VectorType    st_M1; // First moments about origin for threading
    MatrixType    st_M2; // Second moments about origin for threading
    VectorType    st_Cg; // Center of gravity (physical units) for threading
    MatrixType    st_Cm; // Second central moments (physical) for threading
    SizeValueType st_NumberOfPixelsCounted;
  };
  itkPadStruct(ITK_CACHE_LINE_ALIGNMENT, ComputePerThreadStruct, PaddedComputePerThreadStruct);
  itkAlignedTypedef(ITK_CACHE_LINE_ALIGNMENT, PaddedComputePerThreadStruct, AlignedComputePerThreadStruct);

  /** The type of region used for multithreading */
  using ThreadRegionType = typename ImageType::RegionType;

private:
  /** Internal helper function. Does post processing at the end of
   * ComputeSingleThreaded() and AfterThreadedCompute() */
  void
  DoPostProcessing();

  AdvancedImageMomentsCalculator(const Self &);
  void
  operator=(const Self &);

  MultiThreaderBase::Pointer m_Threader{};

  mutable MultiThreaderParameterType m_ThreaderParameters{};

  mutable std::vector<AlignedComputePerThreadStruct> m_ComputePerThreadVariables{};
  bool                                               m_UseMultiThread{};
  SizeValueType                                      m_NumberOfPixelsCounted{};

  SizeValueType               m_NumberOfSamplesForCenteredTransformInitialization{};
  InputPixelType              m_LowerThresholdForCenterGravity{};
  bool                        m_CenterOfGravityUsesLowerThreshold{};
  ImageSampleContainerPointer m_SampleContainer{};

  bool       m_Valid{}; // Have moments been computed yet?
  ScalarType m_M0{};    // Zeroth moment
  VectorType m_M1{};    // First moments about origin
  MatrixType m_M2{};    // Second moments about origin
  VectorType m_Cg{};    // Center of gravity (physical units)
  MatrixType m_Cm{};    // Second central moments (physical)
  VectorType m_Pm{};    // Principal moments (physical)
  MatrixType m_Pa{};    // Principal axes (physical)

  ImageConstPointer         m_Image{};
  SpatialObjectConstPointer m_SpatialObjectMask{};

}; // class AdvancedImageMomentsCalculator
} // end namespace itk

#ifndef ITK_MANUAL_INSTANTIATION
#  include "itkAdvancedImageMomentsCalculator.hxx"
#endif

#endif /* itkAdvancedImageMomentsCalculator_h */