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 */
|