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 cpm::Plugins::SimpleFillRegion::
33 this->SetNumberOfInputs( 2 );
34 this->SetNumberOfOutputs( 1 );
35 this->_MakeOutput< cpPlugins::Interface::Image >( 0 );
37 this->m_DefaultParameters[ "MinDelta" ] = TParameter( "double", "0" );
38 this->m_DefaultParameters[ "MaxDelta" ] = TParameter( "double", "0" );
39 this->m_DefaultParameters[ "Seed" ] = TParameter( "point", "0:0:0" );
42 // -------------------------------------------------------------------------
43 cpm::Plugins::SimpleFillRegion::
48 // -------------------------------------------------------------------------
49 std::string cpm::Plugins::SimpleFillRegion::
52 return( "cpm::Plugins::SimpleFillRegion" );
55 // -------------------------------------------------------------------------
56 std::string cpm::Plugins::SimpleFillRegion::
59 itk::DataObject* i1 = this->_GetInput( 0 );
60 itk::DataObject* i2 = this->_GetInput( 1 );
63 "cpm::Plugins::SimpleFillRegion: itk::Image(s) dimensions not supported";
64 cpmPlugins_SimpleFillRegion_Dimension( r, 2, i1, i2, _GD0 );
65 else cpmPlugins_SimpleFillRegion_Dimension( r, 3, i1, i2, _GD0 );
69 // -------------------------------------------------------------------------
70 template< unsigned int D >
71 std::string cpm::Plugins::SimpleFillRegion::
74 typedef itk::ImageBase< D > _TImage;
76 _TImage* i1 = dynamic_cast< _TImage* >( this->_GetInput( 0 ) );
79 "cpm::Plugins::SimpleFillRegion: first image's pixel type not supported";
80 cpmPlugins_SimpleFillRegion_Pixel1( r, char, D, i1, _GD1 );
81 else cpmPlugins_SimpleFillRegion_Pixel1( r, short, D, i1, _GD1 );
82 else cpmPlugins_SimpleFillRegion_Pixel1( r, int, D, i1, _GD1 );
83 else cpmPlugins_SimpleFillRegion_Pixel1( r, long, D, i1, _GD1 );
84 else cpmPlugins_SimpleFillRegion_Pixel1( r, unsigned char, D, i1, _GD1 );
85 else cpmPlugins_SimpleFillRegion_Pixel1( r, unsigned short, D, i1, _GD1 );
86 else cpmPlugins_SimpleFillRegion_Pixel1( r, unsigned int, D, i1, _GD1 );
87 else cpmPlugins_SimpleFillRegion_Pixel1( r, unsigned long, D, i1, _GD1 );
88 else cpmPlugins_SimpleFillRegion_Pixel1( r, float, D, i1, _GD1 );
89 else cpmPlugins_SimpleFillRegion_Pixel1( r, double, D, i1, _GD1 );
93 // -------------------------------------------------------------------------
94 template< class P1, unsigned int D >
95 std::string cpm::Plugins::SimpleFillRegion::
98 typedef itk::ImageBase< D > _TImage;
100 _TImage* i2 = dynamic_cast< _TImage* >( this->_GetInput( 1 ) );
103 "cpm::Plugins::SimpleFillRegion: second image's pixel type not supported";
104 cpmPlugins_SimpleFillRegion_Pixel2( r, P1, char, D, i2, _GD2 );
105 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, short, D, i2, _GD2 );
106 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, int, D, i2, _GD2 );
107 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, long, D, i2, _GD2 );
108 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, unsigned char, D, i2, _GD2 );
109 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, unsigned short, D, i2, _GD2 );
110 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, unsigned int, D, i2, _GD2 );
111 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, unsigned long, D, i2, _GD2 );
112 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, float, D, i2, _GD2 );
113 else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, double, D, i2, _GD2 );
117 // -------------------------------------------------------------------------
118 template< typename I1, class I2, typename TCoordRep >
119 class SimpleFillRegionFunction
120 : public itk::BinaryThresholdImageFunction< I1, TCoordRep >
123 typedef SimpleFillRegionFunction Self;
124 typedef itk::BinaryThresholdImageFunction< I1, TCoordRep > Superclass;
125 typedef itk::SmartPointer< Self > Pointer;
126 typedef itk::SmartPointer< const Self > ConstPointer;
128 itkTypeMacro( SimpleFillRegionFunction, itkBinaryThresholdImageFunction );
131 itkSetConstObjectMacro( InputSegmentation, I2 );
133 typedef typename Superclass::InputImageType InputImageType;
134 typedef typename I1::PixelType PixelType;
135 itkStaticConstMacro(ImageDimension, unsigned int, Superclass::ImageDimension);
136 typedef typename Superclass::PointType PointType;
137 typedef typename Superclass::IndexType IndexType;
138 typedef typename Superclass::ContinuousIndexType ContinuousIndexType;
140 virtual bool EvaluateAtIndex( const IndexType& index ) const
143 if( this->m_InputSegmentation.IsNotNull( ) )
145 this->m_InputSegmentation->GetPixel( index ) ==
146 ( typename I2::PixelType )( 0 )
149 return( this->Superclass::EvaluateAtIndex( index ) );
155 SimpleFillRegionFunction( )
159 virtual ~SimpleFillRegionFunction( )
164 // Purposely not implemented
165 SimpleFillRegionFunction( const Self& );
166 Self& operator=( const Self& );
169 typename I2::ConstPointer m_InputSegmentation;
172 // -------------------------------------------------------------------------
173 template< class P1, class P2, unsigned int D >
174 std::string cpm::Plugins::SimpleFillRegion::
177 typedef itk::Image< P1, D > _TImage1;
178 typedef itk::Image< P2, D > _TImage2;
180 _TImage1* i1 = dynamic_cast< _TImage1* >( this->_GetInput( 0 ) );
181 _TImage2* i2 = dynamic_cast< _TImage2* >( this->_GetInput( 1 ) );
183 // Transform input seed
184 typename _TImage1::PointType pnt;
185 TParameters::const_iterator sIt;
186 sIt = this->m_Parameters.find( "Seed" );
187 if( sIt == this->m_Parameters.end( ) )
188 return( "cpm::Plugins::SimpleFillRegion: no seed given." );
189 char* buff = new char[ sIt->second.second.size( ) + 1 ];
190 std::memcpy( buff, sIt->second.second.c_str( ), sIt->second.second.size( ) );
191 buff[ sIt->second.second.size( ) ] = '\0';
192 char* tok = std::strtok( buff, ":" );
193 for( unsigned int d = 0; d < D; ++d )
195 pnt[ d ] = std::atof( tok );
196 tok = std::strtok( NULL, ":" );
200 typename _TImage1::IndexType idx;
201 if( !( i1->TransformPhysicalPointToIndex( pnt, idx ) ) )
202 return( "cpm::Plugins::SimpleFillRegion: seed is outside image regions." );
204 // Check spatial compatilibity
205 if( i1->GetLargestPossibleRegion( ) != i2->GetLargestPossibleRegion( ) )
206 return( "cpm::Plugins::SimpleFillRegion: incompatible regions." );
207 if( i1->GetSpacing( ) != i2->GetSpacing( ) )
208 return( "cpm::Plugins::SimpleFillRegion: incompatible spacings." );
209 if( i1->GetOrigin( ) != i2->GetOrigin( ) )
210 return( "cpm::Plugins::SimpleFillRegion: incompatible origins." );
211 if( i1->GetDirection( ) != i2->GetDirection( ) )
212 return( "cpm::Plugins::SimpleFillRegion: incompatible directions." );
215 cpPlugins::Interface::Image* out_obj =
216 dynamic_cast< cpPlugins::Interface::Image* >( this->GetOutput( 0 ) );
217 typename _TImage2::Pointer out =
218 dynamic_cast< _TImage2* >( out_obj->GetDataObject( ) );
221 out = _TImage2::New( );
222 this->_SetOutput( 0, out );
226 // Create memory, if needed
228 i1->GetLargestPossibleRegion( ) != out->GetLargestPossibleRegion( ) ||
229 i1->GetSpacing( ) != out->GetSpacing( ) ||
230 i1->GetOrigin( ) != out->GetOrigin( ) ||
231 i1->GetDirection( ) != out->GetDirection( )
234 out->SetLargestPossibleRegion( i1->GetLargestPossibleRegion( ) );
235 out->SetRequestedRegion( i1->GetRequestedRegion( ) );
236 out->SetBufferedRegion( i1->GetBufferedRegion( ) );
237 out->SetDirection( i1->GetDirection( ) );
238 out->SetOrigin( i1->GetOrigin( ) );
239 out->SetSpacing( i1->GetSpacing( ) );
243 out->FillBuffer( P2( 0 ) );
245 P1 min_delta = P1( std::atof( this->m_Parameters[ "MinDelta" ].second.c_str( ) ) );
246 P1 max_delta = P1( std::atof( this->m_Parameters[ "MaxDelta" ].second.c_str( ) ) );
247 P1 lower = i1->GetPixel( idx ) - min_delta;
248 P1 upper = i1->GetPixel( idx ) + min_delta;
250 typedef SimpleFillRegionFunction< _TImage1, _TImage2, double > _TFunction;
251 typename _TFunction::Pointer f = _TFunction::New( );
252 f->SetInputImage( i1 );
253 f->SetInputSegmentation( i2 );
254 f->ThresholdBetween( lower, upper );
257 itk::FloodFilledImageFunctionConditionalConstIterator< _TImage1, _TFunction >
259 _TIterator fIt( i1, f, idx );
260 for( fIt.GoToBegin( ); !fIt.IsAtEnd( ); ++fIt )
261 out->SetPixel( fIt.GetIndex( ), 1 );