30 #ifndef __itkLabelGeometryImageFilter_txx
31 #define __itkLabelGeometryImageFilter_txx
38 #include "itkNumericTraits.h"
50 #if defined(__GNUC__) && (__GNUC__ <= 2) //NOTE: This class needs a mutex for gnu 2.95
52 #define LOCK_HASHMAP this->m_Mutex.Lock()
53 #define UNLOCK_HASHMAP this->m_Mutex.Unlock()
56 #define UNLOCK_HASHMAP
62 template<
class TLabelImage,
class TIntensityImage>
67 rotationMatrix(TLabelImage::ImageDimension,TLabelImage::ImageDimension,0);
68 for(
unsigned int i = 0; i < TLabelImage::ImageDimension; i++ )
70 rotationMatrix.set_column(i,eig.get_eigenvector(i) );
74 rotationMatrix.fliplr();
81 if( TLabelImage::ImageDimension == 2 )
83 matrixDet = vnl_det(rotationMatrix[0], rotationMatrix[1]);
85 else if( TLabelImage::ImageDimension == 3 )
87 matrixDet = vnl_det(rotationMatrix[0], rotationMatrix[1], rotationMatrix[2]);
92 std::cerr <<
"ERROR: Determinant cannot be calculated for this dimension!" << std::endl;
97 rotationMatrix.set_column(TLabelImage::ImageDimension-1,-rotationMatrix.get_column(TLabelImage::ImageDimension-1));
101 rotationMatrix.inplace_transpose();
103 return rotationMatrix;
106 template<
class TLabelImage,
class TIntensityImage,
class TGenericImage>
110 vnl_symmetric_eigensystem<double> eig,
122 vnl_RotationMatrix.inplace_transpose();
128 typename TransformType::Pointer transform = TransformType::New();
130 typename TransformType::CenterType center;
132 typename TransformType::OutputVectorType translation;
133 translation.Fill( 0 );
134 transform->SetCenter( center );
135 transform->SetTranslation( translation );
136 transform->SetMatrix( rotationMatrix );
139 typename ResampleFilterType::Pointer resampler = ResampleFilterType::New();
145 typename ResampleFilterType::SizeType boundingBoxSize;
146 for(
unsigned int i = 0; i < TLabelImage::ImageDimension; i++ )
148 boundingBoxSize[i] = (
typename ResampleFilterType::SizeType::SizeValueType)vcl_ceil(labelGeometry.
m_OrientedBoundingBoxSize[i]);
151 resampler->SetTransform( transform );
152 resampler->SetSize( boundingBoxSize );
153 resampler->SetOutputSpacing( filter->
GetInput()->GetSpacing() );
161 typename InterpolatorType::Pointer interpolator = InterpolatorType::New();
162 resampler->SetInterpolator( interpolator );
166 typename CastType::Pointer caster = CastType::New();
167 caster->SetInput( filter->
GetInput() );
168 resampler->SetInput( caster->GetOutput() );
183 typename InterpolatorType::Pointer interpolator = InterpolatorType::New();
184 resampler->SetInterpolator( interpolator );
188 typename CastType::Pointer caster = CastType::New();
190 resampler->SetInput( caster->GetOutput() );
198 template<
class TLabelImage,
class TIntensityImage>
202 this->SetNumberOfRequiredInputs(1);
203 m_CalculatePixelIndices =
false;
204 m_CalculateOrientedBoundingBox =
false;
205 m_CalculateOrientedLabelRegions =
false;
206 m_CalculateOrientedIntensityRegions =
false;
209 template<
class TLabelImage,
class TIntensityImage>
218 this->GetInput()->GetBufferedRegion());
228 label = labelIt.
Get();
230 mapIt = m_LabelGeometryMapper.find( label );
234 if (mapIt == m_LabelGeometryMapper.end())
240 mapIt = m_LabelGeometryMapper.insert( MapValueType(label,
LabelGeometry()) ).first;
248 (*mapIt).second.m_Label = label;
252 typename ImageIteratorWithIndexType::IndexType index = labelIt.
GetIndex();
253 for (
unsigned int i = 0; i < ( 2 * ImageDimension); i += 2 )
256 if ((*mapIt).second.m_BoundingBox[i] > index[i/2])
258 (*mapIt).second.m_BoundingBox[i] = index[i/2];
261 if ((*mapIt).second.m_BoundingBox[i + 1] < index[i/2])
263 (*mapIt).second.m_BoundingBox[i + 1] = index[i/2];
268 (*mapIt).second.m_ZeroOrderMoment++;
270 for (
unsigned int i = 0; i < ImageDimension; i++ )
273 (*mapIt).second.m_FirstOrderRawMoments[i] += index[i];
280 for(
unsigned int i = 0; i < ImageDimension; i++ )
283 for(
unsigned int j = 0; j < ImageDimension; j++ )
285 (*mapIt).second.m_SecondOrderRawMoments(i,j) += index[i]*index[j];
289 if( m_CalculatePixelIndices ==
true )
292 (*mapIt).second.m_PixelIndices.push_back( index );
298 const TIntensityImage * intensityImage = this->GetIntensityInput();
309 IntensityImageIteratorType it( intensityImage, intensityImage->GetBufferedRegion() );
311 typename IntensityImageIteratorType::IndexType index;
315 while( !it.IsAtEnd() )
317 label = labelIt.
Get();
318 mapIt = m_LabelGeometryMapper.find( label );
320 value =
static_cast<RealType>(it.Get());
321 index = it.GetIndex();
324 (*mapIt).second.m_Sum += value;
326 for (
unsigned int i = 0; i < ImageDimension; i++ )
329 (*mapIt).second.m_FirstOrderWeightedRawMoments[i] += index[i] * (
typename LabelIndexType::IndexValueType)value;
340 if( !intensityImage )
342 if( m_CalculateOrientedIntensityRegions )
344 std::cerr <<
"ERROR: An input intensity image must be used in order to calculate the oriented intensity image." << std::endl;
346 m_CalculateOrientedIntensityRegions =
false;
355 float pixelSecondOrderCentralMoment = 1.0f / 12.0f;
360 for( mapIt = m_LabelGeometryMapper.begin(); mapIt != m_LabelGeometryMapper.end(); mapIt++ )
364 (*mapIt).second.m_BoundingBoxVolume = 1;
365 for(
unsigned int i = 0; i < ImageDimension; i++ )
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];
371 for(
unsigned int i = 0; i < ImageDimension; i++ )
374 (*mapIt).second.m_Centroid[i] =
static_cast<typename LabelPointType::ValueType
>((*mapIt).second.m_FirstOrderRawMoments[i]) / (*mapIt).second.m_ZeroOrderMoment;
380 (*mapIt).second.m_WeightedCentroid[i] = 0.0;
384 (*mapIt).second.m_WeightedCentroid[i] =
static_cast<typename LabelPointType::ValueType
>((*mapIt).second.m_FirstOrderWeightedRawMoments[i]) / (*mapIt).second.m_Sum;
389 MatrixType normalizedSecondOrderCentralMoments(ImageDimension,ImageDimension,0);
390 for(
unsigned int i = 0; i < ImageDimension; i++ )
392 for(
unsigned int j = 0; j < ImageDimension; j++ )
394 normalizedSecondOrderCentralMoments(i,j) = ((*mapIt).second.m_SecondOrderRawMoments(i,j))/((*mapIt).second.m_ZeroOrderMoment) - (*mapIt).second.m_Centroid[i] * (*mapIt).second.m_Centroid[j];
399 normalizedSecondOrderCentralMoments(i,j) += pixelSecondOrderCentralMoment;
407 vnl_symmetric_eigensystem<double> eig(normalizedSecondOrderCentralMoments);
411 MatrixType eigenvectors(ImageDimension,ImageDimension,0);
412 for(
unsigned int i = 0; i < ImageDimension; i++ )
414 eigenvectors.set_column(i,eig.get_eigenvector(i));
415 eigenvalues[i] = eig.get_eigenvalue(i);
417 (*mapIt).second.m_Eigenvalues = eigenvalues;
418 (*mapIt).second.m_Eigenvectors = eigenvectors;
422 for(
unsigned int i = 0; i < ImageDimension; i++ )
424 axesLength[i] = 4 * vcl_sqrt( eigenvalues[i] );
426 (*mapIt).second.m_AxesLength = axesLength;
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]);
433 if( m_CalculateOrientedBoundingBox ==
true )
436 CalculateOrientedBoundingBoxVertices(eig, (*mapIt).second );
438 if( m_CalculateOrientedLabelRegions ==
true )
440 CalculateOrientedImage<TLabelImage, TIntensityImage, LabelImageType>(
441 this, eig, (*mapIt).second, true );
443 if( m_CalculateOrientedIntensityRegions ==
true )
447 if( this->GetIntensityInput() )
449 CalculateOrientedImage<TLabelImage, TIntensityImage, IntensityImageType>(
450 this, eig, (*mapIt).second, false );
454 m_AllLabels.push_back( (*mapIt).first );
459 template<
class TLabelImage,
class TIntensityImage>
474 MatrixType rotationMatrix = CalculateRotationMatrix<TLabelImage,TIntensityImage>(eig);
475 MatrixType inverseRotationMatrix = rotationMatrix.transpose();
483 for(
unsigned int i = 0; i < labelGeometry.
m_PixelIndices.size(); i++ )
485 for(
unsigned int j = 0; j < ImageDimension; j++ )
492 MatrixType transformedPixelLocations = rotationMatrix * pixelLocations;
500 for (
unsigned int i = 0; i < ImageDimension * 2; i += 2)
506 for(
unsigned int column = 0; column < transformedPixelLocations.columns(); column++ )
508 for (
unsigned int i = 0; i < ( 2 * ImageDimension); i += 2 )
511 if (transformedBoundingBox[i] > transformedPixelLocations(i/2,column) )
513 transformedBoundingBox[i] = transformedPixelLocations(i/2,column);
516 if (transformedBoundingBox[i + 1] < transformedPixelLocations(i/2,column) )
518 transformedBoundingBox[i + 1] = transformedPixelLocations(i/2,column);
525 for(
unsigned int i = 0; i < (2 * ImageDimension); i += 2 )
528 transformedBoundingBox[i] -= 0.5;
530 transformedBoundingBox[i+1] += 0.5;
538 for(
unsigned int i = 0; i < (2 * ImageDimension); i += 2 )
555 unsigned int numberOfVertices =
556 (
unsigned int)vcl_pow( 2.0, (
int)ImageDimension );
557 MatrixType transformedBoundingBoxVertices(ImageDimension,numberOfVertices ,0);
561 for(
unsigned int i = 0; i < numberOfVertices; i++ )
564 for(
unsigned int j = 0; j < ImageDimension; j++ )
567 binaryIndex[j] = val%2;
571 arrayIndex = binaryIndex[j] + 2*j;
572 transformedBoundingBoxVertices(j,i) = transformedBoundingBox[arrayIndex];
579 MatrixType orientedBoundingBoxVertices = inverseRotationMatrix * transformedBoundingBoxVertices;
583 for(
unsigned int i = 0; i < orientedBoundingBoxVertices.columns(); i++ )
585 for(
unsigned int j = 0; j < ImageDimension; j++ )
587 orientedBoundingBoxVertices(j,i) += labelGeometry.
m_Centroid[j];
595 for(
unsigned int i = 0; i < ImageDimension; i++ )
603 template<
class TLabelImage,
class TIntensityImage>
609 mapIt = m_LabelGeometryMapper.find( label );
610 if ( mapIt == m_LabelGeometryMapper.end() )
619 return (*mapIt).second.m_PixelIndices;
624 template<
class TLabelImage,
class TIntensityImage>
630 mapIt = m_LabelGeometryMapper.find( label );
631 if ( mapIt == m_LabelGeometryMapper.end() )
638 return (*mapIt).second.m_ZeroOrderMoment;
641 template<
class TLabelImage,
class TIntensityImage>
647 mapIt = m_LabelGeometryMapper.find( label );
648 if ( mapIt == m_LabelGeometryMapper.end() )
655 return (*mapIt).second.m_Sum;
659 template<
class TLabelImage,
class TIntensityImage>
665 mapIt = m_LabelGeometryMapper.find( label );
666 if ( mapIt == m_LabelGeometryMapper.end() )
671 return emptyCentroid;
675 return (*mapIt).second.m_Centroid;
679 template<
class TLabelImage,
class TIntensityImage>
685 mapIt = m_LabelGeometryMapper.find( label );
686 if ( mapIt == m_LabelGeometryMapper.end() )
691 return emptyCentroid;
695 return (*mapIt).second.m_WeightedCentroid;
699 template<
class TLabelImage,
class TIntensityImage>
705 mapIt = m_LabelGeometryMapper.find( label );
706 if ( mapIt == m_LabelGeometryMapper.end() )
714 return (*mapIt).second.m_Eigenvalues;
718 template<
class TLabelImage,
class TIntensityImage>
724 mapIt = m_LabelGeometryMapper.find( label );
725 if ( mapIt == m_LabelGeometryMapper.end() )
728 MatrixType emptyMatrix(ImageDimension,ImageDimension,0);
733 return (*mapIt).second.m_Eigenvectors;
738 template<
class TLabelImage,
class TIntensityImage>
744 mapIt = m_LabelGeometryMapper.find( label );
745 if ( mapIt == m_LabelGeometryMapper.end() )
750 return emptyAxesLength;
754 return (*mapIt).second.m_AxesLength;
758 template<
class TLabelImage,
class TIntensityImage>
764 return axisLength[0];
767 template<
class TLabelImage,
class TIntensityImage>
773 return axisLength[ImageDimension-1];
776 template<
class TLabelImage,
class TIntensityImage>
782 mapIt = m_LabelGeometryMapper.find( label );
783 if ( mapIt == m_LabelGeometryMapper.end() )
790 return (*mapIt).second.m_Eccentricity;
793 template<
class TLabelImage,
class TIntensityImage>
799 mapIt = m_LabelGeometryMapper.find( label );
800 if ( mapIt == m_LabelGeometryMapper.end() )
807 return (*mapIt).second.m_Elongation;
811 template<
class TLabelImage,
class TIntensityImage>
817 mapIt = m_LabelGeometryMapper.find( label );
818 if ( mapIt == m_LabelGeometryMapper.end() )
825 return (*mapIt).second.m_Orientation;
829 template<
class TLabelImage,
class TIntensityImage>
835 mapIt = m_LabelGeometryMapper.find( label );
836 if ( mapIt == m_LabelGeometryMapper.end() )
845 return (*mapIt).second.m_BoundingBox;
849 template<
class TLabelImage,
class TIntensityImage>
855 mapIt = m_LabelGeometryMapper.find( label );
856 if ( mapIt == m_LabelGeometryMapper.end() )
863 return (*mapIt).second.m_BoundingBoxVolume;
867 template<
class TLabelImage,
class TIntensityImage>
873 mapIt = m_LabelGeometryMapper.find( label );
874 if ( mapIt == m_LabelGeometryMapper.end() )
883 return (*mapIt).second.m_BoundingBoxSize;
888 template<
class TLabelImage,
class TIntensityImage>
893 unsigned int numberOfVertices =
894 (
unsigned int)vcl_pow( 2.0, (
int)ImageDimension );
896 mapIt = m_LabelGeometryMapper.find( label );
897 if ( mapIt == m_LabelGeometryMapper.end() )
901 emptyPoint.Fill( 0 );
903 emptyVertices.resize(numberOfVertices,emptyPoint);
904 return emptyVertices;
908 return (*mapIt).second.m_OrientedBoundingBoxVertices;
913 template<
class TLabelImage,
class TIntensityImage>
919 mapIt = m_LabelGeometryMapper.find( label );
920 if ( mapIt == m_LabelGeometryMapper.end() )
927 return (*mapIt).second.m_OrientedBoundingBoxVolume;
931 template<
class TLabelImage,
class TIntensityImage>
937 mapIt = m_LabelGeometryMapper.find( label );
938 if ( mapIt == m_LabelGeometryMapper.end() )
950 return (*mapIt).second.m_OrientedBoundingBoxSize;
954 template<
class TLabelImage,
class TIntensityImage>
960 mapIt = m_LabelGeometryMapper.find( label );
961 if ( mapIt == m_LabelGeometryMapper.end() )
970 return (*mapIt).second.m_OrientedBoundingBoxOrigin;
974 template<
class TLabelImage,
class TIntensityImage>
980 mapIt = m_LabelGeometryMapper.find( label );
981 if ( mapIt == m_LabelGeometryMapper.end() )
984 MatrixType emptyMatrix(ImageDimension,ImageDimension,0);
989 return (*mapIt).second.m_RotationMatrix;
993 template<
class TLabelImage,
class TIntensityImage>
999 mapIt = m_LabelGeometryMapper.find( label );
1001 if ( mapIt == m_LabelGeometryMapper.end() )
1013 unsigned int dimension = bbox.
Size() / 2;
1015 for (
unsigned int i = 0; i < dimension; i++)
1017 index[i] = bbox[2*i];
1018 size[i] = bbox[2*i+1] - bbox[2*i] + 1;
1021 region.SetSize(size);
1022 region.SetIndex(index);
1029 template<
class TLabelImage,
class TIntensityImage>
1035 mapIt = m_LabelGeometryMapper.find( label );
1036 if ( mapIt == m_LabelGeometryMapper.end() )
1043 return (*mapIt).second.m_OrientedLabelImage;
1047 template<
class TLabelImage,
class TIntensityImage>
1053 mapIt = m_LabelGeometryMapper.find( label );
1054 if ( mapIt == m_LabelGeometryMapper.end() )
1061 return (*mapIt).second.m_OrientedIntensityImage;
1066 template <
class TImage,
class TLabelImage>
1071 Superclass::PrintSelf(os,indent);
1073 os << indent <<
"Number of labels: " << m_LabelGeometryMapper.size()
1077 for( mapIt = m_LabelGeometryMapper.begin(); mapIt != m_LabelGeometryMapper.end(); mapIt++ )
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;
1092 os <<
"\t Oriented bounding box volume: " << (*mapIt).second.m_OrientedBoundingBoxVolume;
1093 os <<
"\t Oriented bounding box size: " << (*mapIt).second.m_OrientedBoundingBoxSize;
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;