Orfeo Toolbox  3.16
itkLabelGeometryImageFilter.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkLabelGeometryImageFilter.txx,v $
5  Language: C++
6  Date: $Date: 2010-04-04 14:46:21 $
7  Version: $Revision: 1.10 $
8 
9  Copyright (c) Insight Software Consortium. All rights reserved.
10  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11 
12  This software is distributed WITHOUT ANY WARRANTY; without even
13  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14  PURPOSE. See the above copyright notices for more information.
15 
16 =========================================================================*/
17 
18 /*=========================================================================
19 *
20 * Authors: Dirk Padfield and James Miller.
21 *
22 * This work is part of the National Alliance for Medical Image
23 * Computing (NAMIC), funded by the National Institutes of Health
24 * through the NIH Roadmap for Medical Research, Grant U54 EB005149.
25 * Information on the National Centers for Biomedical Computing
26 * can be obtained from http://nihroadmap.nih.gov/bioinformatics.
27 *
28 *=========================================================================*/
29 
30 #ifndef __itkLabelGeometryImageFilter_txx
31 #define __itkLabelGeometryImageFilter_txx
32 
34 
35 #include "itkImageRegionIterator.h"
38 #include "itkNumericTraits.h"
39 #include "itkProgressReporter.h"
40 #include "itkCastImageFilter.h"
41 
42 #include "itkAffineTransform.h"
43 #include "itkResampleImageFilter.h"
47 
48 namespace itk {
49 
50 #if defined(__GNUC__) && (__GNUC__ <= 2) //NOTE: This class needs a mutex for gnu 2.95
51 
52 #define LOCK_HASHMAP this->m_Mutex.Lock()
53 #define UNLOCK_HASHMAP this->m_Mutex.Unlock()
54 #else
55 #define LOCK_HASHMAP
56 #define UNLOCK_HASHMAP
57 #endif
58 
59 //
60 // Helper functions
61 //
62 template<class TLabelImage, class TIntensityImage>
64 CalculateRotationMatrix(vnl_symmetric_eigensystem<double> eig)
65 {
67  rotationMatrix(TLabelImage::ImageDimension,TLabelImage::ImageDimension,0);
68  for( unsigned int i = 0; i < TLabelImage::ImageDimension; i++ )
69  {
70  rotationMatrix.set_column(i,eig.get_eigenvector(i) );
71  }
72  // After vnl_symmetric_eigensystem, the columns of V are the eigenvectors, sorted by increasing eigenvalue, from most negative to most positive.
73  // First reorder the eigenvectors by decreasing eigenvalue.
74  rotationMatrix.fliplr();
75 
76  // Next, check whether the determinant of the matrix is negative.
77  // If it is, then the vectors do not follow the right-hand rule. We
78  // can fix this by making one of them negative. Make the last
79  // eigenvector (with smallest eigenvalue) negative.
80  float matrixDet;
81  if( TLabelImage::ImageDimension == 2 )
82  {
83  matrixDet = vnl_det(rotationMatrix[0], rotationMatrix[1]);
84  }
85  else if( TLabelImage::ImageDimension == 3 )
86  {
87  matrixDet = vnl_det(rotationMatrix[0], rotationMatrix[1], rotationMatrix[2]);
88  }
89  else
90  {
91  matrixDet = 0.0f;
92  std::cerr << "ERROR: Determinant cannot be calculated for this dimension!" << std::endl;
93  }
94 
95  if( matrixDet < 0 )
96  {
97  rotationMatrix.set_column(TLabelImage::ImageDimension-1,-rotationMatrix.get_column(TLabelImage::ImageDimension-1));
98  }
99 
100  // Transpose the matrix to yield the rotation matrix.
101  rotationMatrix.inplace_transpose();
102 
103  return rotationMatrix;
104 }
105 
106 template<class TLabelImage, class TIntensityImage, class TGenericImage>
107 bool
110  vnl_symmetric_eigensystem<double> eig,
112  bool useLabelImage)
113 {
114  // CalculateOrientedBoundingBoxVertices needs to have already been
115  // called. This is taken care of by the flags.
116 
117  // Rotate the original object to align with the coordinate
118  // system defined by the eigenvectors.
119  // Since the resampler moves from the output image to the input
120  // image, we take the transpose of the rotation matrix.
121  typename LabelGeometryImageFilter<TLabelImage,TIntensityImage>::MatrixType vnl_RotationMatrix = CalculateRotationMatrix<TLabelImage,TIntensityImage>(eig);
122  vnl_RotationMatrix.inplace_transpose();
123 
124  // Set up the transform. Here the center of rotation is the
125  // centroid of the object, the rotation matrix is specified by the
126  // eigenvectors, and there is no translation.
128  typename TransformType::Pointer transform = TransformType::New();
129  typename TransformType::MatrixType rotationMatrix( vnl_RotationMatrix );
130  typename TransformType::CenterType center;
131  center = labelGeometry.m_Centroid;
132  typename TransformType::OutputVectorType translation;
133  translation.Fill( 0 );
134  transform->SetCenter( center );
135  transform->SetTranslation( translation );
136  transform->SetMatrix( rotationMatrix );
137 
139  typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
140 
141  // The m_OrientedBoundingBoxSize is specified to float precision.
142  // Here we need an integer size large enough to contain all of the points, so we take the ceil of it.
143  // We also need to ensure that that bounding box is not outside of
144  // the image bounds.
145  typename ResampleFilterType::SizeType boundingBoxSize;
146  for( unsigned int i = 0; i < TLabelImage::ImageDimension; i++ )
147  {
148  boundingBoxSize[i] = (typename ResampleFilterType::SizeType::SizeValueType)vcl_ceil(labelGeometry.m_OrientedBoundingBoxSize[i]);
149  }
150 
151  resampler->SetTransform( transform );
152  resampler->SetSize( boundingBoxSize );
153  resampler->SetOutputSpacing( filter->GetInput()->GetSpacing() );
154  resampler->SetOutputOrigin( labelGeometry.m_OrientedBoundingBoxOrigin );
155 
156  if( useLabelImage )
157  {
158  // Set up the interpolator.
159  // Use a nearest neighbor interpolator since these are labeled images.
161  typename InterpolatorType::Pointer interpolator = InterpolatorType::New();
162  resampler->SetInterpolator( interpolator );
163 
164  // Cast the type to enable compilation.
166  typename CastType::Pointer caster = CastType::New();
167  caster->SetInput( filter->GetInput() );
168  resampler->SetInput( caster->GetOutput() );
169  resampler->Update();
170  labelGeometry.m_OrientedLabelImage->Graft( resampler->GetOutput() );
171  }
172  else
173  {
174  // If there is no intensity input defined, return;
175  if( !filter->GetIntensityInput() )
176  {
177  return true;
178  }
179 
180  // Set up the interpolator.
181  // Use a linear interpolator since these are intensity images.
183  typename InterpolatorType::Pointer interpolator = InterpolatorType::New();
184  resampler->SetInterpolator( interpolator );
185 
186  // Cast the type to enable compilation.
188  typename CastType::Pointer caster = CastType::New();
189  caster->SetInput( filter->GetIntensityInput() );
190  resampler->SetInput( caster->GetOutput() );
191  resampler->Update();
192  labelGeometry.m_OrientedIntensityImage->Graft( resampler->GetOutput() );
193  }
194 
195  return true;
196 }
197 
198 template<class TLabelImage, class TIntensityImage>
201 {
202  this->SetNumberOfRequiredInputs(1);
203  m_CalculatePixelIndices = false;
204  m_CalculateOrientedBoundingBox = false;
205  m_CalculateOrientedLabelRegions = false;
206  m_CalculateOrientedIntensityRegions = false;
207 }
208 
209 template<class TLabelImage, class TIntensityImage>
210 void
213 {
214  LabelPixelType label;
215 
216  // Iterator over the label image.
217  ImageRegionConstIterator<TLabelImage> labelIt (this->GetInput(),
218  this->GetInput()->GetBufferedRegion());
219 
220  typedef ImageRegionConstIteratorWithIndex<TLabelImage> ImageIteratorWithIndexType;
221 
222  // Iterator over the mapping from labels to geometry values.
223  MapIterator mapIt;
224 
225  // Do the work
226  while (!labelIt.IsAtEnd())
227  {
228  label = labelIt.Get();
229 
230  mapIt = m_LabelGeometryMapper.find( label );
231 
232  // Is the label already in the mapper?
233  // If not, create a new geometry object.
234  if (mapIt == m_LabelGeometryMapper.end())
235  {
236  typedef typename MapType::value_type MapValueType;
237 
238  LOCK_HASHMAP;
239  // map insert is defined as: pair<iterator, bool> insert(const value_type& x)
240  mapIt = m_LabelGeometryMapper.insert( MapValueType(label,LabelGeometry()) ).first;
241 
243  }
244 
245  // Update the geometry values.
246 
247  // LABEL
248  (*mapIt).second.m_Label = label;
249 
250  // BOUNDING BOX
251  // The bounding box is defined in (min, max) pairs, such as (xmin,xmax,ymin,ymax,zmin,zmax).
252  typename ImageIteratorWithIndexType::IndexType index = labelIt.GetIndex();
253  for ( unsigned int i = 0; i < ( 2 * ImageDimension); i += 2 )
254  {
255  // Update min
256  if ((*mapIt).second.m_BoundingBox[i] > index[i/2])
257  {
258  (*mapIt).second.m_BoundingBox[i] = index[i/2];
259  }
260  // Update max
261  if ((*mapIt).second.m_BoundingBox[i + 1] < index[i/2])
262  {
263  (*mapIt).second.m_BoundingBox[i + 1] = index[i/2];
264  }
265  }
266 
267  // VOLUME
268  (*mapIt).second.m_ZeroOrderMoment++;
269 
270  for (unsigned int i = 0; i < ImageDimension; i++ )
271  {
272  // FIRST ORDER RAW MOMENTS
273  (*mapIt).second.m_FirstOrderRawMoments[i] += index[i];
274  }
275 
276  // SECOND ORDER RAW MOMENTS
277  // Even for ND, the second order moments can be found from just
278  // two nested loops since second order moments consider only
279  // interactions between pairs of indices.
280  for( unsigned int i = 0; i < ImageDimension; i++ )
281  {
282  // It is only necessary to fill in half of the matrix since it is symmetric.
283  for( unsigned int j = 0; j < ImageDimension; j++ )
284  {
285  (*mapIt).second.m_SecondOrderRawMoments(i,j) += index[i]*index[j];
286  }
287  }
288 
289  if( m_CalculatePixelIndices == true )
290  {
291  // Pixel location list
292  (*mapIt).second.m_PixelIndices.push_back( index );
293  }
294 
295  ++labelIt;
296  }
297 
298  const TIntensityImage * intensityImage = this->GetIntensityInput();
299 
300  // If an intensity image is defined, we can also calculate further
301  // features.
302  if( intensityImage )
303  {
304  RealType value;
305 
306  // Iterator over the intensity image.
307  typedef ImageRegionConstIteratorWithIndex<TIntensityImage> IntensityImageIteratorType;
308 
309  IntensityImageIteratorType it( intensityImage, intensityImage->GetBufferedRegion() );
310 
311  typename IntensityImageIteratorType::IndexType index;
312 
313  labelIt.GoToBegin();
314 
315  while( !it.IsAtEnd() )
316  {
317  label = labelIt.Get();
318  mapIt = m_LabelGeometryMapper.find( label );
319 
320  value = static_cast<RealType>(it.Get());
321  index = it.GetIndex();
322 
323  // INTEGRATED PIXEL VALUE
324  (*mapIt).second.m_Sum += value;
325 
326  for (unsigned int i = 0; i < ImageDimension; i++ )
327  {
328  // FIRST ORDER WEIGHTED RAW MOMENTS
329  (*mapIt).second.m_FirstOrderWeightedRawMoments[i] += index[i] * (typename LabelIndexType::IndexValueType)value;
330  }
331 
332  ++it;
333  ++labelIt;
334  }
335  }
336 
337 
338  // If there is no intensity input defined, the oriented
339  // intensity regions cannot be calculated.
340  if( !intensityImage )
341  {
342  if( m_CalculateOrientedIntensityRegions )
343  {
344  std::cerr << "ERROR: An input intensity image must be used in order to calculate the oriented intensity image." << std::endl;
345  }
346  m_CalculateOrientedIntensityRegions = false;
347  }
348 
349 
350  // We need to add to the second order moment the second order
351  // moment of a pixel. This can be derived analytically. The first
352  // order moment of a pixel can be shown to be 0, and the first order
353  // cross moment can also be shown to be 0. The second order moment
354  // can be shown to be 1/12.
355  float pixelSecondOrderCentralMoment = 1.0f / 12.0f;
356 
357  // Now that the m_LabelGeometryMapper has been updated for all
358  // pixels in the image, we can calculate other geometrical values.
359  // Loop through all labels of the image.
360  for( mapIt = m_LabelGeometryMapper.begin(); mapIt != m_LabelGeometryMapper.end(); mapIt++ )
361  {
362 
363  // Update the bounding box measurements.
364  (*mapIt).second.m_BoundingBoxVolume = 1;
365  for( unsigned int i = 0; i < ImageDimension; i++ )
366  {
367  (*mapIt).second.m_BoundingBoxSize[i] = (*mapIt).second.m_BoundingBox[2*i+1] - (*mapIt).second.m_BoundingBox[2*i] + 1;
368  (*mapIt).second.m_BoundingBoxVolume = (*mapIt).second.m_BoundingBoxVolume * (*mapIt).second.m_BoundingBoxSize[i];
369  }
370 
371  for( unsigned int i = 0; i < ImageDimension; i++ )
372  {
373  // Normalize the centroid sum by the count to get the centroid.
374  (*mapIt).second.m_Centroid[i] = static_cast<typename LabelPointType::ValueType>((*mapIt).second.m_FirstOrderRawMoments[i]) / (*mapIt).second.m_ZeroOrderMoment;
375 
376  // This is the weighted sum. It only calculates correctly if
377  // the intensity image is defined.
378  if (!intensityImage)
379  {
380  (*mapIt).second.m_WeightedCentroid[i] = 0.0;
381  }
382  else
383  {
384  (*mapIt).second.m_WeightedCentroid[i] = static_cast<typename LabelPointType::ValueType>((*mapIt).second.m_FirstOrderWeightedRawMoments[i]) / (*mapIt).second.m_Sum;
385  }
386  }
387 
388  // Using the raw moments, we can calculate the central moments.
389  MatrixType normalizedSecondOrderCentralMoments(ImageDimension,ImageDimension,0);
390  for( unsigned int i = 0; i < ImageDimension; i++ )
391  {
392  for( unsigned int j = 0; j < ImageDimension; j++ )
393  {
394  normalizedSecondOrderCentralMoments(i,j) = ((*mapIt).second.m_SecondOrderRawMoments(i,j))/((*mapIt).second.m_ZeroOrderMoment) - (*mapIt).second.m_Centroid[i] * (*mapIt).second.m_Centroid[j];
395  // We need to add to the second order moment the second order
396  // moment of a pixel. This can be derived analytically.
397  if( i == j )
398  {
399  normalizedSecondOrderCentralMoments(i,j) += pixelSecondOrderCentralMoment;
400  }
401  }
402  }
403 
404  // Compute the eigenvalues/eigenvectors of the covariance matrix.
405  // The result is stored in increasing eigenvalues with
406  // corresponding eigenvectors.
407  vnl_symmetric_eigensystem<double> eig(normalizedSecondOrderCentralMoments);
408 
409  // Calculate the eigenvalues/eigenvectors
410  VectorType eigenvalues(ImageDimension,0);
411  MatrixType eigenvectors(ImageDimension,ImageDimension,0);
412  for( unsigned int i = 0; i < ImageDimension; i++ )
413  {
414  eigenvectors.set_column(i,eig.get_eigenvector(i));
415  eigenvalues[i] = eig.get_eigenvalue(i);
416  }
417  (*mapIt).second.m_Eigenvalues = eigenvalues;
418  (*mapIt).second.m_Eigenvectors = eigenvectors;
419 
420 
422  for( unsigned int i = 0; i < ImageDimension; i++ )
423  {
424  axesLength[i] = 4 * vcl_sqrt( eigenvalues[i] );
425  }
426  (*mapIt).second.m_AxesLength = axesLength;
427 
428  // The following three features are currently only defined in 2D.
429  (*mapIt).second.m_Eccentricity = vcl_sqrt((eigenvalues[1] - eigenvalues[0])/eigenvalues[1]);
430  (*mapIt).second.m_Elongation = axesLength[1]/axesLength[0];
431  (*mapIt).second.m_Orientation = vcl_atan2( eig.get_eigenvector(1)[1], eig.get_eigenvector(1)[0]);
432 
433  if( m_CalculateOrientedBoundingBox == true )
434  {
435  // Calculate the oriented bounding box using the eigenvectors.
436  CalculateOrientedBoundingBoxVertices(eig, (*mapIt).second );
437  }
438  if( m_CalculateOrientedLabelRegions == true )
439  {
440  CalculateOrientedImage<TLabelImage, TIntensityImage, LabelImageType>(
441  this, eig, (*mapIt).second, true );
442  }
443  if( m_CalculateOrientedIntensityRegions == true )
444  {
445  // If there is no intensity input defined, the oriented
446  // intensity regions cannot be calculated.
447  if( this->GetIntensityInput() )
448  {
449  CalculateOrientedImage<TLabelImage, TIntensityImage, IntensityImageType>(
450  this, eig, (*mapIt).second, false );
451  }
452  }
453 
454  m_AllLabels.push_back( (*mapIt).first );
455  }
456 }
457 
458 
459 template<class TLabelImage, class TIntensityImage>
460 bool
462 ::CalculateOrientedBoundingBoxVertices(vnl_symmetric_eigensystem<double> eig, LabelGeometry & labelGeometry)
463 {
464  // Calculate the oriented bounding box using the eigenvectors.
465  // For each label, the pixels are rotated to the new coordinate
466  // system defined by the eigenvectors. The bounding boxes are
467  // calculated in this space, and then they are rotated back to the
468  // original coordinate system to define the oriented bounding boxes.
469  // The reverse rotation is the transpose of the rotation matrix.
470 
471  // m_PixelIndices needs to have already been calculated. This is
472  // handled by the flags.
473 
474  MatrixType rotationMatrix = CalculateRotationMatrix<TLabelImage,TIntensityImage>(eig);
475  MatrixType inverseRotationMatrix = rotationMatrix.transpose();
476 
477  labelGeometry.m_RotationMatrix = rotationMatrix;
478 
479  // Convert the pixel locations to a vnl_matrix.
480  // Subtract the centroid of the region so that the rotation will
481  // be about the center of the region.
482  MatrixType pixelLocations(ImageDimension, labelGeometry.m_PixelIndices.size(), 0);
483  for( unsigned int i = 0; i < labelGeometry.m_PixelIndices.size(); i++ )
484  {
485  for( unsigned int j = 0; j < ImageDimension; j++ )
486  {
487  pixelLocations(j,i) = labelGeometry.m_PixelIndices[i][j] - labelGeometry.m_Centroid[j];
488  }
489  }
490 
491  // Rotate the points by the rotation matrix from the eigenvectors.
492  MatrixType transformedPixelLocations = rotationMatrix * pixelLocations;
493 
494  // Find the min and max of the point locations in this new
495  // coordinate system. These values will be float, so we use a
496  // BoundingBoxFloatType rather than BoundingBoxType.
497  // The bounding box order is [minX,maxX,minY,maxY,...]
498  BoundingBoxFloatType transformedBoundingBox;
499  // Initialize the bounding box values.
500  for (unsigned int i = 0; i < ImageDimension * 2; i += 2)
501  {
502  transformedBoundingBox[i] = NumericTraits<float>::max();
503  transformedBoundingBox[i+1] = NumericTraits<float>::NonpositiveMin();
504  }
505 
506  for( unsigned int column = 0; column < transformedPixelLocations.columns(); column++ )
507  {
508  for (unsigned int i = 0; i < ( 2 * ImageDimension); i += 2 )
509  {
510  // Update min
511  if (transformedBoundingBox[i] > transformedPixelLocations(i/2,column) )
512  {
513  transformedBoundingBox[i] = transformedPixelLocations(i/2,column);
514  }
515  // Update max
516  if (transformedBoundingBox[i + 1] < transformedPixelLocations(i/2,column) )
517  {
518  transformedBoundingBox[i + 1] = transformedPixelLocations(i/2,column);
519  }
520  }
521  }
522 
523  // Add 0.5 pixel buffers on each side of the bounding box to be sure to
524  // encompass the pixels and not cut through them.
525  for( unsigned int i = 0; i < (2 * ImageDimension); i += 2 )
526  {
527  // If the index corresponds with a min, subtract 0.5.
528  transformedBoundingBox[i] -= 0.5;
529  // Otherwise, add 0.5.
530  transformedBoundingBox[i+1] += 0.5;
531  }
532 
533  // The bounding box volume can be calculated directly from the
534  // transformed bounding box.
535  // Since 0.5 was already added to the border of the bounding box,
536  // it is not necessary to add 1 to the range to get the correct range.
537  labelGeometry.m_OrientedBoundingBoxVolume = 1;
538  for( unsigned int i = 0; i < (2 * ImageDimension); i += 2 )
539  {
540  labelGeometry.m_OrientedBoundingBoxSize[i/2] = transformedBoundingBox[i+1] - transformedBoundingBox[i];
541  labelGeometry.m_OrientedBoundingBoxVolume *= transformedBoundingBox[i+1] - transformedBoundingBox[i];
542  }
543 
544  // The bounding box cannot be transformed directly because an
545  // oriented bounding box cannot be specified simply by the min and
546  // max in each dimension. Instead, the oriented bounding box is
547  // specified by the points corresponding to the vertices of the
548  // oriented bounding box. We find these from the oriented
549  // bounding box and transform them back to the original coordinate frame.
550  // The order of the vertices corresponds with binary counting,
551  // where min is zero and max is one. For example, in 2D, binary
552  // counting will give [0,0],[0,1],[1,0],[1,1], which corresponds
553  // to [minX,minY],[minX,maxY],[maxX,minY],[maxX,maxY].
554  // Loop through each dimension of the bounding box and find all of the vertices.
555  unsigned int numberOfVertices =
556  (unsigned int)vcl_pow( 2.0, (int)ImageDimension );
557  MatrixType transformedBoundingBoxVertices(ImageDimension,numberOfVertices ,0);
558  int val;
559  LabelIndexType binaryIndex;
560  int arrayIndex;
561  for( unsigned int i = 0; i < numberOfVertices; i++ )
562  {
563  val = i;
564  for( unsigned int j = 0; j < ImageDimension; j++ )
565  {
566  // This is the binary index as described above.
567  binaryIndex[j] = val%2;
568  val = val/2;
569  // This is the index into the transformedBoundingBox array
570  // corresponding to the binaryIndex.
571  arrayIndex = binaryIndex[j] + 2*j;
572  transformedBoundingBoxVertices(j,i) = transformedBoundingBox[arrayIndex];
573  }
574  }
575 
576 
577  // Transform the transformed bounding box vertices back to the
578  // original coordinate system.
579  MatrixType orientedBoundingBoxVertices = inverseRotationMatrix * transformedBoundingBoxVertices;
580 
581  // Add the centroid back to each of the vertices since it was
582  // subtracted when the points were rotated.
583  for( unsigned int i = 0; i < orientedBoundingBoxVertices.columns(); i++ )
584  {
585  for( unsigned int j = 0; j < ImageDimension; j++ )
586  {
587  orientedBoundingBoxVertices(j,i) += labelGeometry.m_Centroid[j];
588  // Copy the oriented bounding box vertices back to a vector of
589  // points for the mapper.
590  labelGeometry.m_OrientedBoundingBoxVertices[i][j] = orientedBoundingBoxVertices(j,i);
591  }
592  }
593 
594  // Find the origin of the oriented bounding box.
595  for( unsigned int i = 0; i < ImageDimension; i++ )
596  {
597  labelGeometry.m_OrientedBoundingBoxOrigin[i] = transformedBoundingBox[2*i] + labelGeometry.m_Centroid[i];
598  }
599 
600  return true;
601 }
602 
603 template<class TLabelImage, class TIntensityImage>
607 {
608  MapConstIterator mapIt;
609  mapIt = m_LabelGeometryMapper.find( label );
610  if ( mapIt == m_LabelGeometryMapper.end() )
611  {
612  // label does not exist, return a default value
613  LabelIndicesType emptyVector;
614  emptyVector.clear();
615  return emptyVector;
616  }
617  else
618  {
619  return (*mapIt).second.m_PixelIndices;
620  }
621 }
622 
623 
624 template<class TLabelImage, class TIntensityImage>
625 unsigned long
628 {
629  MapConstIterator mapIt;
630  mapIt = m_LabelGeometryMapper.find( label );
631  if ( mapIt == m_LabelGeometryMapper.end() )
632  {
633  // label does not exist, return a default value
634  return 0;
635  }
636  else
637  {
638  return (*mapIt).second.m_ZeroOrderMoment;
639  }
640 }
641 template<class TLabelImage, class TIntensityImage>
645 {
646  MapConstIterator mapIt;
647  mapIt = m_LabelGeometryMapper.find( label );
648  if ( mapIt == m_LabelGeometryMapper.end() )
649  {
650  // label does not exist, return a default value
652  }
653  else
654  {
655  return (*mapIt).second.m_Sum;
656  }
657 }
658 
659 template<class TLabelImage, class TIntensityImage>
663 {
664  MapConstIterator mapIt;
665  mapIt = m_LabelGeometryMapper.find( label );
666  if ( mapIt == m_LabelGeometryMapper.end() )
667  {
668  // label does not exist, return a default value
669  LabelPointType emptyCentroid;
671  return emptyCentroid;
672  }
673  else
674  {
675  return (*mapIt).second.m_Centroid;
676  }
677 }
678 
679 template<class TLabelImage, class TIntensityImage>
683 {
684  MapConstIterator mapIt;
685  mapIt = m_LabelGeometryMapper.find( label );
686  if ( mapIt == m_LabelGeometryMapper.end() )
687  {
688  // label does not exist, return a default value
689  LabelPointType emptyCentroid;
691  return emptyCentroid;
692  }
693  else
694  {
695  return (*mapIt).second.m_WeightedCentroid;
696  }
697 }
698 
699 template<class TLabelImage, class TIntensityImage>
703 {
704  MapConstIterator mapIt;
705  mapIt = m_LabelGeometryMapper.find( label );
706  if ( mapIt == m_LabelGeometryMapper.end() )
707  {
708  // label does not exist, return a default value
709  VectorType emptyVector(ImageDimension,0);
710  return emptyVector;
711  }
712  else
713  {
714  return (*mapIt).second.m_Eigenvalues;
715  }
716 }
717 
718 template<class TLabelImage, class TIntensityImage>
722 {
723  MapConstIterator mapIt;
724  mapIt = m_LabelGeometryMapper.find( label );
725  if ( mapIt == m_LabelGeometryMapper.end() )
726  {
727  // label does not exist, return a default value
728  MatrixType emptyMatrix(ImageDimension,ImageDimension,0);
729  return emptyMatrix;
730  }
731  else
732  {
733  return (*mapIt).second.m_Eigenvectors;
734  }
735 }
736 
737 
738 template<class TLabelImage, class TIntensityImage>
742 {
743  MapConstIterator mapIt;
744  mapIt = m_LabelGeometryMapper.find( label );
745  if ( mapIt == m_LabelGeometryMapper.end() )
746  {
747  // label does not exist, return a default value
748  LabelPointType emptyAxesLength;
750  return emptyAxesLength;
751  }
752  else
753  {
754  return (*mapIt).second.m_AxesLength;
755  }
756 }
757 
758 template<class TLabelImage, class TIntensityImage>
762 {
763  AxesLengthType axisLength = GetAxesLength(label);
764  return axisLength[0];
765 }
766 
767 template<class TLabelImage, class TIntensityImage>
771 {
772  AxesLengthType axisLength = GetAxesLength(label);
773  return axisLength[ImageDimension-1];
774 }
775 
776 template<class TLabelImage, class TIntensityImage>
780 {
781  MapConstIterator mapIt;
782  mapIt = m_LabelGeometryMapper.find( label );
783  if ( mapIt == m_LabelGeometryMapper.end() )
784  {
785  // label does not exist, return a default value
787  }
788  else
789  {
790  return (*mapIt).second.m_Eccentricity;
791  }
792 }
793 template<class TLabelImage, class TIntensityImage>
797 {
798  MapConstIterator mapIt;
799  mapIt = m_LabelGeometryMapper.find( label );
800  if ( mapIt == m_LabelGeometryMapper.end() )
801  {
802  // label does not exist, return a default value
804  }
805  else
806  {
807  return (*mapIt).second.m_Elongation;
808  }
809 }
810 
811 template<class TLabelImage, class TIntensityImage>
815 {
816  MapConstIterator mapIt;
817  mapIt = m_LabelGeometryMapper.find( label );
818  if ( mapIt == m_LabelGeometryMapper.end() )
819  {
820  // label does not exist, return a default value
822  }
823  else
824  {
825  return (*mapIt).second.m_Orientation;
826  }
827 }
828 
829 template<class TLabelImage, class TIntensityImage>
833 {
834  MapConstIterator mapIt;
835  mapIt = m_LabelGeometryMapper.find( label );
836  if ( mapIt == m_LabelGeometryMapper.end() )
837  {
838  BoundingBoxType emptyBox;
840  // label does not exist, return a default value
841  return emptyBox;
842  }
843  else
844  {
845  return (*mapIt).second.m_BoundingBox;
846  }
847 }
848 
849 template<class TLabelImage, class TIntensityImage>
853 {
854  MapConstIterator mapIt;
855  mapIt = m_LabelGeometryMapper.find( label );
856  if ( mapIt == m_LabelGeometryMapper.end() )
857  {
858  // label does not exist, return a default value
860  }
861  else
862  {
863  return (*mapIt).second.m_BoundingBoxVolume;
864  }
865 }
866 
867 template<class TLabelImage, class TIntensityImage>
871 {
872  MapConstIterator mapIt;
873  mapIt = m_LabelGeometryMapper.find( label );
874  if ( mapIt == m_LabelGeometryMapper.end() )
875  {
876  // label does not exist, return a default value
877  LabelSizeType emptySize;
879  return emptySize;
880  }
881  else
882  {
883  return (*mapIt).second.m_BoundingBoxSize;
884  }
885 }
886 
887 
888 template<class TLabelImage, class TIntensityImage>
892 {
893  unsigned int numberOfVertices =
894  (unsigned int)vcl_pow( 2.0, (int)ImageDimension );
895  MapConstIterator mapIt;
896  mapIt = m_LabelGeometryMapper.find( label );
897  if ( mapIt == m_LabelGeometryMapper.end() )
898  {
899  // label does not exist, return a default value
900  LabelPointType emptyPoint;
901  emptyPoint.Fill( 0 );
902  BoundingBoxVerticesType emptyVertices;
903  emptyVertices.resize(numberOfVertices,emptyPoint);
904  return emptyVertices;
905  }
906  else
907  {
908  return (*mapIt).second.m_OrientedBoundingBoxVertices;
909  }
910 }
911 
912 
913 template<class TLabelImage, class TIntensityImage>
917 {
918  MapConstIterator mapIt;
919  mapIt = m_LabelGeometryMapper.find( label );
920  if ( mapIt == m_LabelGeometryMapper.end() )
921  {
922  // label does not exist, return a default value
924  }
925  else
926  {
927  return (*mapIt).second.m_OrientedBoundingBoxVolume;
928  }
929 }
930 
931 template<class TLabelImage, class TIntensityImage>
935 {
936  MapConstIterator mapIt;
937  mapIt = m_LabelGeometryMapper.find( label );
938  if ( mapIt == m_LabelGeometryMapper.end() )
939  {
940  // label does not exist, return a default value
941 // LabelSizeType emptySize;
942 // emptySize.Fill( NumericTraits<LabelSizeType::SizeValueType>::Zero);
943 // return emptySize;
944  LabelPointType emptySize;
946  return emptySize;
947  }
948  else
949  {
950  return (*mapIt).second.m_OrientedBoundingBoxSize;
951  }
952 }
953 
954 template<class TLabelImage, class TIntensityImage>
958 {
959  MapConstIterator mapIt;
960  mapIt = m_LabelGeometryMapper.find( label );
961  if ( mapIt == m_LabelGeometryMapper.end() )
962  {
963  // label does not exist, return a default value
964  LabelPointType emptySize;
966  return emptySize;
967  }
968  else
969  {
970  return (*mapIt).second.m_OrientedBoundingBoxOrigin;
971  }
972 }
973 
974 template<class TLabelImage, class TIntensityImage>
978 {
979  MapConstIterator mapIt;
980  mapIt = m_LabelGeometryMapper.find( label );
981  if ( mapIt == m_LabelGeometryMapper.end() )
982  {
983  // label does not exist, return a default value
984  MatrixType emptyMatrix(ImageDimension,ImageDimension,0);
985  return emptyMatrix;
986  }
987  else
988  {
989  return (*mapIt).second.m_RotationMatrix;
990  }
991 }
992 
993 template<class TLabelImage, class TIntensityImage>
997 {
998  MapConstIterator mapIt;
999  mapIt = m_LabelGeometryMapper.find( label );
1000 
1001  if ( mapIt == m_LabelGeometryMapper.end() )
1002  {
1003  RegionType emptyRegion;
1004  // label does not exist, return a default value
1005  return emptyRegion;
1006  }
1007  else
1008  {
1009  BoundingBoxType bbox = this->GetBoundingBox( label );
1010  IndexType index;
1011  SizeType size;
1012 
1013  unsigned int dimension = bbox.Size() / 2;
1014 
1015  for (unsigned int i = 0; i < dimension; i++)
1016  {
1017  index[i] = bbox[2*i];
1018  size[i] = bbox[2*i+1] - bbox[2*i] + 1;
1019  }
1020  RegionType region;
1021  region.SetSize(size);
1022  region.SetIndex(index);
1023 
1024  return region;
1025  }
1026 }
1027 
1028 
1029 template<class TLabelImage, class TIntensityImage>
1030 TLabelImage *
1033 {
1034  MapConstIterator mapIt;
1035  mapIt = m_LabelGeometryMapper.find( label );
1036  if ( mapIt == m_LabelGeometryMapper.end() )
1037  {
1038  // label does not exist, return a default value
1039  return NULL;
1040  }
1041  else
1042  {
1043  return (*mapIt).second.m_OrientedLabelImage;
1044  }
1045 }
1046 
1047 template<class TLabelImage, class TIntensityImage>
1048 TIntensityImage *
1051 {
1052  MapConstIterator mapIt;
1053  mapIt = m_LabelGeometryMapper.find( label );
1054  if ( mapIt == m_LabelGeometryMapper.end() )
1055  {
1056  // label does not exist, return a default value
1057  return NULL;
1058  }
1059  else
1060  {
1061  return (*mapIt).second.m_OrientedIntensityImage;
1062  }
1063 }
1064 
1065 
1066 template <class TImage, class TLabelImage>
1067 void
1069 ::PrintSelf(std::ostream& os, Indent indent) const
1070 {
1071  Superclass::PrintSelf(os,indent);
1072 
1073  os << indent << "Number of labels: " << m_LabelGeometryMapper.size()
1074  << std::endl;
1075 
1076  MapConstIterator mapIt;
1077  for( mapIt = m_LabelGeometryMapper.begin(); mapIt != m_LabelGeometryMapper.end(); mapIt++ )
1078  {
1079  os << indent << "Label[" << (unsigned long)((*mapIt).second.m_Label) << "]: ";
1080  os << "\t Volume: " << (*mapIt).second.m_ZeroOrderMoment;
1081  os << "\t Integrated Intensity: " << (*mapIt).second.m_Sum;
1082  os << "\t Centroid: " << (*mapIt).second.m_Centroid;
1083  os << "\t Weighted Centroid: " << (*mapIt).second.m_WeightedCentroid;
1084  os << "\t Axes Length: " << (*mapIt).second.m_AxesLength;
1085  os << "\t Eccentricity: " << (*mapIt).second.m_Eccentricity;
1086  os << "\t Elongation: " << (*mapIt).second.m_Elongation;
1087  os << "\t Orientation: " << (*mapIt).second.m_Orientation;
1088  os << "\t Bounding box: " << (*mapIt).second.m_BoundingBox;
1089  os << "\t Bounding box volume: " << (*mapIt).second.m_BoundingBoxVolume;
1090  os << "\t Bounding box size: " << (*mapIt).second.m_BoundingBoxSize;
1091  // Oriented bounding box verticies
1092  os << "\t Oriented bounding box volume: " << (*mapIt).second.m_OrientedBoundingBoxVolume;
1093  os << "\t Oriented bounding box size: " << (*mapIt).second.m_OrientedBoundingBoxSize;
1094  // Rotation matrix
1095  os << std::endl;
1096  os << "\t Calculate oriented intensity regions: " << m_CalculateOrientedIntensityRegions;
1097  os << "\t Calculate pixel indices: " << m_CalculatePixelIndices;
1098  os << "\t Calculate oriented bounding box: " << m_CalculateOrientedBoundingBox;
1099  os << "\t Calculate oriented label regions: " << m_CalculateOrientedLabelRegions;
1100  os << "\n\n";
1101  }
1102 
1103 }
1104 
1105 
1106 }// end namespace itk
1107 #endif

Generated at Sat May 18 2013 23:48:50 for Orfeo Toolbox with doxygen 1.8.3.1