1 #include <cpm/Plugins/SimpleFillRegion.h>
2 #include <cpPlugins/Interface/Image.h>
4 #include <itkBinaryThresholdImageFunction.h>
5 #include <itkFloodFilledImageFunctionConditionalConstIterator.h>
7 #define ITK_MANUAL_INSTANTIATION
10 // -------------------------------------------------------------------------
11 #define cpmPlugins_SimpleFillRegion_Dimension( r, d, i1, i2, f ) \
13 dynamic_cast< itk::ImageBase< d >* >( i1 ) != NULL && \
14 dynamic_cast< itk::ImageBase< d >* >( i2 ) != NULL \
18 // -------------------------------------------------------------------------
19 #define cpmPlugins_SimpleFillRegion_Pixel1( r, p, d, i, f ) \
20 if( dynamic_cast< itk::Image< p, d >* >( i ) != NULL ) \
21 r = this->f< p, d >( )
23 // -------------------------------------------------------------------------
24 #define cpmPlugins_SimpleFillRegion_Pixel2( r, p1, p2, d, i, f ) \
25 if( dynamic_cast< itk::Image< p2, d >* >( i ) != NULL ) \
26 r = this->f< p1, p2, d >( )
28 // -------------------------------------------------------------------------
29 std::string cpm::Plugins::SimpleFillRegion::
32 return( "cpm::Plugins::SimpleFillRegion" );
35 // -------------------------------------------------------------------------
36 cpm::Plugins::SimpleFillRegion::
40 this->SetNumberOfInputs( 2 );
41 this->SetNumberOfOutputs( 1 );
42 this->_MakeOutput< cpPlugins::Interface::Image >( 0 );
44 using namespace cpPlugins::Interface;
45 this->m_DefaultParameters.Configure( Parameters::Real, "MinDelta" );
46 this->m_DefaultParameters.Configure( Parameters::Real, "MaxDelta" );
47 this->m_DefaultParameters.Configure( Parameters::Point, "Seed" );
49 this->m_DefaultParameters.SetValueAsReal( "MinDelta", 0 );
50 this->m_DefaultParameters.SetValueAsReal( "MaxDelta", 0 );
51 this->m_DefaultParameters.SetValueAsPoint( "Seed", 3, 0.0, 0.0, 0.0 );
52 this->m_Parameters = this->m_DefaultParameters;
55 // -------------------------------------------------------------------------
56 cpm::Plugins::SimpleFillRegion::
61 // -------------------------------------------------------------------------
62 std::string cpm::Plugins::SimpleFillRegion::
66 itk::DataObject* i1 = this->_GetInput( 0 );
67 itk::DataObject* i2 = this->_GetInput( 1 );
70 "cpm::Plugins::SimpleFillRegion: itk::Image(s) dimensions not supported";
71 cpmPlugins_SimpleFillRegion_Dimension( r, 2, i1, i2, _GD0 );
72 else cpmPlugins_SimpleFillRegion_Dimension( r, 3, i1, i2, _GD0 );
78 // -------------------------------------------------------------------------
80 template< unsigned int D >
81 std::string cpm::Plugins::SimpleFillRegion::
84 typedef itk::ImageBase< D > _TImage;
86 _TImage* i1 = dynamic_cast< _TImage* >( this->_GetInput( 0 ) );
89 "cpm::Plugins::SimpleFillRegion: first image's pixel type not supported";
90 cpmPlugins_SimpleFillRegion_Pixel1( r, char, D, i1, _GD1 );
91 else cpmPlugins_SimpleFillRegion_Pixel1( r, short, D, i1, _GD1 );
92 else cpmPlugins_SimpleFillRegion_Pixel1( r, int, D, i1, _GD1 );
93 else cpmPlugins_SimpleFillRegion_Pixel1( r, long, D, i1, _GD1 );
94 else cpmPlugins_SimpleFillRegion_Pixel1( r, unsigned char, D, i1, _GD1 );
95 else cpmPlugins_SimpleFillRegion_Pixel1( r, unsigned short, D, i1, _GD1 );
96 else cpmPlugins_SimpleFillRegion_Pixel1( r, unsigned int, D, i1, _GD1 );
97 else cpmPlugins_SimpleFillRegion_Pixel1( r, unsigned long, D, i1, _GD1 );
98 else cpmPlugins_SimpleFillRegion_Pixel1( r, float, D, i1, _GD1 );
99 else cpmPlugins_SimpleFillRegion_Pixel1( r, double, D, i1, _GD1 );
103 // -------------------------------------------------------------------------
104 template< class P1, unsigned int D >
105 std::string cpm::Plugins::SimpleFillRegion::
108 typedef itk::ImageBase< D > _TImage;
110 _TImage* i2 = dynamic_cast< _TImage* >( this->_GetInput( 1 ) );
113 "cpm::Plugins::SimpleFillRegion: second image's pixel type not supported";
114 cpmPlugins_SimpleFillRegion_Pixel2( r, P1, char, D, i2, _GD2 );
115 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, short, D, i2, _GD2 );
116 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, int, D, i2, _GD2 );
117 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, long, D, i2, _GD2 );
118 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, unsigned char, D, i2, _GD2 );
119 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, unsigned short, D, i2, _GD2 );
120 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, unsigned int, D, i2, _GD2 );
121 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, unsigned long, D, i2, _GD2 );
122 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, float, D, i2, _GD2 );
123 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, double, D, i2, _GD2 );
127 // -------------------------------------------------------------------------
128 template< typename I1, class I2, typename TCoordRep >
129 class SimpleFillRegionFunction
130 : public itk::BinaryThresholdImageFunction< I1, TCoordRep >
133 typedef SimpleFillRegionFunction Self;
134 typedef itk::BinaryThresholdImageFunction< I1, TCoordRep > Superclass;
135 typedef itk::SmartPointer< Self > Pointer;
136 typedef itk::SmartPointer< const Self > ConstPointer;
138 itkTypeMacro( SimpleFillRegionFunction, itkBinaryThresholdImageFunction );
141 itkSetConstObjectMacro( InputSegmentation, I2 );
143 typedef typename Superclass::InputImageType InputImageType;
144 typedef typename I1::PixelType PixelType;
145 itkStaticConstMacro(ImageDimension, unsigned int, Superclass::ImageDimension);
146 typedef typename Superclass::PointType PointType;
147 typedef typename Superclass::IndexType IndexType;
148 typedef typename Superclass::ContinuousIndexType ContinuousIndexType;
150 virtual bool EvaluateAtIndex( const IndexType& index ) const
153 if( this->m_InputSegmentation.IsNotNull( ) )
155 this->m_InputSegmentation->GetPixel( index ) ==
156 ( typename I2::PixelType )( 0 )
159 return( this->Superclass::EvaluateAtIndex( index ) );
165 SimpleFillRegionFunction( )
169 virtual ~SimpleFillRegionFunction( )
174 // Purposely not implemented
175 SimpleFillRegionFunction( const Self& );
176 Self& operator=( const Self& );
179 typename I2::ConstPointer m_InputSegmentation;
182 // -------------------------------------------------------------------------
183 template< class P1, class P2, unsigned int D >
184 std::string cpm::Plugins::SimpleFillRegion::
187 typedef itk::Image< P1, D > _TImage1;
188 typedef itk::Image< P2, D > _TImage2;
190 _TImage1* i1 = dynamic_cast< _TImage1* >( this->_GetInput( 0 ) );
191 _TImage2* i2 = dynamic_cast< _TImage2* >( this->_GetInput( 1 ) );
193 // Transform input seed
194 typename _TImage1::PointType pnt =
195 this->m_Parameters.GetValueAsPoint< typename _TImage1::PointType >( "Seed" );
196 typename _TImage1::IndexType idx;
197 i1->TransformPhysicalPointToIndex( pnt, idx );
199 // Check spatial compatilibity
200 if( i1->GetLargestPossibleRegion( ) != i2->GetLargestPossibleRegion( ) )
201 return( "cpm::Plugins::SimpleFillRegion: incompatible regions." );
202 if( i1->GetSpacing( ) != i2->GetSpacing( ) )
203 return( "cpm::Plugins::SimpleFillRegion: incompatible spacings." );
204 if( i1->GetOrigin( ) != i2->GetOrigin( ) )
205 return( "cpm::Plugins::SimpleFillRegion: incompatible origins." );
206 if( i1->GetDirection( ) != i2->GetDirection( ) )
207 return( "cpm::Plugins::SimpleFillRegion: incompatible directions." );
210 typename _TImage2::Pointer out = _TImage2::New( );
211 this->_SetOutput( 0, out );
213 // Create memory, if needed
215 i1->GetLargestPossibleRegion( ) != out->GetLargestPossibleRegion( ) ||
216 i1->GetSpacing( ) != out->GetSpacing( ) ||
217 i1->GetOrigin( ) != out->GetOrigin( ) ||
218 i1->GetDirection( ) != out->GetDirection( )
221 out->SetLargestPossibleRegion( i1->GetLargestPossibleRegion( ) );
222 out->SetRequestedRegion( i1->GetRequestedRegion( ) );
223 out->SetBufferedRegion( i1->GetBufferedRegion( ) );
224 out->SetDirection( i1->GetDirection( ) );
225 out->SetOrigin( i1->GetOrigin( ) );
226 out->SetSpacing( i1->GetSpacing( ) );
230 out->FillBuffer( P2( 0 ) );
232 P1 min_delta = P1( this->m_Parameters.GetValueAsReal( "MinDelta" ) );
233 P1 max_delta = P1( this->m_Parameters.GetValueAsReal( "MaxDelta" ) );
234 P1 lower = i1->GetPixel( idx ) - min_delta;
235 P1 upper = i1->GetPixel( idx ) + min_delta;
237 typedef SimpleFillRegionFunction< _TImage1, _TImage2, double > _TFunction;
238 typename _TFunction::Pointer f = _TFunction::New( );
239 f->SetInputImage( i1 );
240 f->SetInputSegmentation( i2 );
241 f->ThresholdBetween( lower, upper );
244 itk::FloodFilledImageFunctionConditionalConstIterator< _TImage1, _TFunction >
246 _TIterator fIt( i1, f, idx );
247 for( fIt.GoToBegin( ); !fIt.IsAtEnd( ); ++fIt )
248 out->SetPixel( fIt.GetIndex( ), 1 );