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::
65 itk::DataObject* i1 = this->_GetInput( 0 );
66 itk::DataObject* i2 = this->_GetInput( 1 );
69 "cpm::Plugins::SimpleFillRegion: itk::Image(s) dimensions not supported";
70 cpmPlugins_SimpleFillRegion_Dimension( r, 2, i1, i2, _GD0 );
71 else cpmPlugins_SimpleFillRegion_Dimension( r, 3, i1, i2, _GD0 );
75 // -------------------------------------------------------------------------
76 template< unsigned int D >
77 std::string cpm::Plugins::SimpleFillRegion::
80 typedef itk::ImageBase< D > _TImage;
82 _TImage* i1 = dynamic_cast< _TImage* >( this->_GetInput( 0 ) );
85 "cpm::Plugins::SimpleFillRegion: first image's pixel type not supported";
86 cpmPlugins_SimpleFillRegion_Pixel1( r, char, D, i1, _GD1 );
87 else cpmPlugins_SimpleFillRegion_Pixel1( r, short, D, i1, _GD1 );
88 else cpmPlugins_SimpleFillRegion_Pixel1( r, int, D, i1, _GD1 );
89 else cpmPlugins_SimpleFillRegion_Pixel1( r, long, D, i1, _GD1 );
90 else cpmPlugins_SimpleFillRegion_Pixel1( r, unsigned char, D, i1, _GD1 );
91 else cpmPlugins_SimpleFillRegion_Pixel1( r, unsigned short, D, i1, _GD1 );
92 else cpmPlugins_SimpleFillRegion_Pixel1( r, unsigned int, D, i1, _GD1 );
93 else cpmPlugins_SimpleFillRegion_Pixel1( r, unsigned long, D, i1, _GD1 );
94 else cpmPlugins_SimpleFillRegion_Pixel1( r, float, D, i1, _GD1 );
95 else cpmPlugins_SimpleFillRegion_Pixel1( r, double, D, i1, _GD1 );
99 // -------------------------------------------------------------------------
100 template< class P1, unsigned int D >
101 std::string cpm::Plugins::SimpleFillRegion::
104 typedef itk::ImageBase< D > _TImage;
106 _TImage* i2 = dynamic_cast< _TImage* >( this->_GetInput( 1 ) );
109 "cpm::Plugins::SimpleFillRegion: second image's pixel type not supported";
110 cpmPlugins_SimpleFillRegion_Pixel2( r, P1, char, D, i2, _GD2 );
111 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, short, D, i2, _GD2 );
112 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, int, D, i2, _GD2 );
113 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, long, D, i2, _GD2 );
114 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, unsigned char, D, i2, _GD2 );
115 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, unsigned short, D, i2, _GD2 );
116 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, unsigned int, D, i2, _GD2 );
117 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, unsigned long, D, i2, _GD2 );
118 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, float, D, i2, _GD2 );
119 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, double, D, i2, _GD2 );
123 // -------------------------------------------------------------------------
124 template< typename I1, class I2, typename TCoordRep >
125 class SimpleFillRegionFunction
126 : public itk::BinaryThresholdImageFunction< I1, TCoordRep >
129 typedef SimpleFillRegionFunction Self;
130 typedef itk::BinaryThresholdImageFunction< I1, TCoordRep > Superclass;
131 typedef itk::SmartPointer< Self > Pointer;
132 typedef itk::SmartPointer< const Self > ConstPointer;
134 itkTypeMacro( SimpleFillRegionFunction, itkBinaryThresholdImageFunction );
137 itkSetConstObjectMacro( InputSegmentation, I2 );
139 typedef typename Superclass::InputImageType InputImageType;
140 typedef typename I1::PixelType PixelType;
141 itkStaticConstMacro(ImageDimension, unsigned int, Superclass::ImageDimension);
142 typedef typename Superclass::PointType PointType;
143 typedef typename Superclass::IndexType IndexType;
144 typedef typename Superclass::ContinuousIndexType ContinuousIndexType;
146 virtual bool EvaluateAtIndex( const IndexType& index ) const
149 if( this->m_InputSegmentation.IsNotNull( ) )
151 this->m_InputSegmentation->GetPixel( index ) ==
152 ( typename I2::PixelType )( 0 )
155 return( this->Superclass::EvaluateAtIndex( index ) );
161 SimpleFillRegionFunction( )
165 virtual ~SimpleFillRegionFunction( )
170 // Purposely not implemented
171 SimpleFillRegionFunction( const Self& );
172 Self& operator=( const Self& );
175 typename I2::ConstPointer m_InputSegmentation;
178 // -------------------------------------------------------------------------
179 template< class P1, class P2, unsigned int D >
180 std::string cpm::Plugins::SimpleFillRegion::
183 typedef itk::Image< P1, D > _TImage1;
184 typedef itk::Image< P2, D > _TImage2;
186 _TImage1* i1 = dynamic_cast< _TImage1* >( this->_GetInput( 0 ) );
187 _TImage2* i2 = dynamic_cast< _TImage2* >( this->_GetInput( 1 ) );
189 // Transform input seed
190 typename _TImage1::PointType pnt =
191 this->m_Parameters.GetValueAsPoint< typename _TImage1::PointType >( "Seed" );
192 typename _TImage1::IndexType idx;
193 i1->TransformPhysicalPointToIndex( pnt, idx );
195 // Check spatial compatilibity
196 if( i1->GetLargestPossibleRegion( ) != i2->GetLargestPossibleRegion( ) )
197 return( "cpm::Plugins::SimpleFillRegion: incompatible regions." );
198 if( i1->GetSpacing( ) != i2->GetSpacing( ) )
199 return( "cpm::Plugins::SimpleFillRegion: incompatible spacings." );
200 if( i1->GetOrigin( ) != i2->GetOrigin( ) )
201 return( "cpm::Plugins::SimpleFillRegion: incompatible origins." );
202 if( i1->GetDirection( ) != i2->GetDirection( ) )
203 return( "cpm::Plugins::SimpleFillRegion: incompatible directions." );
206 typename _TImage2::Pointer out = _TImage2::New( );
207 this->_SetOutput( 0, out );
209 // Create memory, if needed
211 i1->GetLargestPossibleRegion( ) != out->GetLargestPossibleRegion( ) ||
212 i1->GetSpacing( ) != out->GetSpacing( ) ||
213 i1->GetOrigin( ) != out->GetOrigin( ) ||
214 i1->GetDirection( ) != out->GetDirection( )
217 out->SetLargestPossibleRegion( i1->GetLargestPossibleRegion( ) );
218 out->SetRequestedRegion( i1->GetRequestedRegion( ) );
219 out->SetBufferedRegion( i1->GetBufferedRegion( ) );
220 out->SetDirection( i1->GetDirection( ) );
221 out->SetOrigin( i1->GetOrigin( ) );
222 out->SetSpacing( i1->GetSpacing( ) );
226 out->FillBuffer( P2( 0 ) );
228 P1 min_delta = P1( this->m_Parameters.GetValueAsReal( "MinDelta" ) );
229 P1 max_delta = P1( this->m_Parameters.GetValueAsReal( "MaxDelta" ) );
230 P1 lower = i1->GetPixel( idx ) - min_delta;
231 P1 upper = i1->GetPixel( idx ) + min_delta;
233 typedef SimpleFillRegionFunction< _TImage1, _TImage2, double > _TFunction;
234 typename _TFunction::Pointer f = _TFunction::New( );
235 f->SetInputImage( i1 );
236 f->SetInputSegmentation( i2 );
237 f->ThresholdBetween( lower, upper );
240 itk::FloodFilledImageFunctionConditionalConstIterator< _TImage1, _TFunction >
242 _TIterator fIt( i1, f, idx );
243 for( fIt.GoToBegin( ); !fIt.IsAtEnd( ); ++fIt )
244 out->SetPixel( fIt.GetIndex( ), 1 );