X-Git-Url: https://git.creatis.insa-lyon.fr/pubgit/?a=blobdiff_plain;f=lib%2Fcpm%2FPlugins%2FSimpleFillRegion.cxx;fp=lib%2Fcpm%2FPlugins%2FSimpleFillRegion.cxx;h=5dd4911ec2216f930a3210226165afe98eb352c0;hb=bece008148f4a08cff5daaa3c9b2824462b94319;hp=167c9e040e5d2e1dab0b07464a27af7a88df0b87;hpb=93ddd2fe04d05b28dff31448032fd3af93ffe750;p=cpMesh.git diff --git a/lib/cpm/Plugins/SimpleFillRegion.cxx b/lib/cpm/Plugins/SimpleFillRegion.cxx index 167c9e0..5dd4911 100644 --- a/lib/cpm/Plugins/SimpleFillRegion.cxx +++ b/lib/cpm/Plugins/SimpleFillRegion.cxx @@ -1,4 +1,29 @@ #include +#include + +#include +#include + +#define ITK_MANUAL_INSTANTIATION +#include + +// ------------------------------------------------------------------------- +#define cpmPlugins_SimpleFillRegion_Dimension( r, d, i1, i2, f ) \ + if( \ + dynamic_cast< itk::ImageBase< d >* >( i1 ) != NULL && \ + dynamic_cast< itk::ImageBase< d >* >( i2 ) != NULL \ + ) \ + r = this->f< d >( ) + +// ------------------------------------------------------------------------- +#define cpmPlugins_SimpleFillRegion_Pixel1( r, p, d, i, f ) \ + if( dynamic_cast< itk::Image< p, d >* >( i ) != NULL ) \ + r = this->f< p, d >( ) + +// ------------------------------------------------------------------------- +#define cpmPlugins_SimpleFillRegion_Pixel2( r, p1, p2, d, i, f ) \ + if( dynamic_cast< itk::Image< p2, d >* >( i ) != NULL ) \ + r = this->f< p1, p2, d >( ) // ------------------------------------------------------------------------- cpm::Plugins::SimpleFillRegion:: @@ -6,6 +31,8 @@ SimpleFillRegion( ) : Superclass( ) { this->SetNumberOfInputs( 2 ); + this->SetNumberOfOutputs( 1 ); + this->_MakeOutput< cpPlugins::Interface::Image >( 0 ); this->m_DefaultParameters[ "MinDelta" ] = TParameter( "double", "0" ); this->m_DefaultParameters[ "MaxDelta" ] = TParameter( "double", "0" ); @@ -29,7 +56,211 @@ GetClassName( ) const std::string cpm::Plugins::SimpleFillRegion:: _GenerateData( ) { - std::cout << "Simple fill region" << std::endl; + itk::DataObject* i1 = this->_GetInput( 0 ); + itk::DataObject* i2 = this->_GetInput( 1 ); + + std::string r = + "cpm::Plugins::SimpleFillRegion: itk::Image(s) dimensions not supported"; + cpmPlugins_SimpleFillRegion_Dimension( r, 2, i1, i2, _GD0 ); + else cpmPlugins_SimpleFillRegion_Dimension( r, 3, i1, i2, _GD0 ); + return( r ); +} + +// ------------------------------------------------------------------------- +template< unsigned int D > +std::string cpm::Plugins::SimpleFillRegion:: +_GD0( ) +{ + typedef itk::ImageBase< D > _TImage; + + _TImage* i1 = dynamic_cast< _TImage* >( this->_GetInput( 0 ) ); + + std::string r = + "cpm::Plugins::SimpleFillRegion: first image's pixel type not supported"; + cpmPlugins_SimpleFillRegion_Pixel1( r, char, D, i1, _GD1 ); + else cpmPlugins_SimpleFillRegion_Pixel1( r, short, D, i1, _GD1 ); + else cpmPlugins_SimpleFillRegion_Pixel1( r, int, D, i1, _GD1 ); + else cpmPlugins_SimpleFillRegion_Pixel1( r, long, D, i1, _GD1 ); + else cpmPlugins_SimpleFillRegion_Pixel1( r, unsigned char, D, i1, _GD1 ); + else cpmPlugins_SimpleFillRegion_Pixel1( r, unsigned short, D, i1, _GD1 ); + else cpmPlugins_SimpleFillRegion_Pixel1( r, unsigned int, D, i1, _GD1 ); + else cpmPlugins_SimpleFillRegion_Pixel1( r, unsigned long, D, i1, _GD1 ); + else cpmPlugins_SimpleFillRegion_Pixel1( r, float, D, i1, _GD1 ); + else cpmPlugins_SimpleFillRegion_Pixel1( r, double, D, i1, _GD1 ); + return( r ); +} + +// ------------------------------------------------------------------------- +template< class P1, unsigned int D > +std::string cpm::Plugins::SimpleFillRegion:: +_GD1( ) +{ + typedef itk::ImageBase< D > _TImage; + + _TImage* i2 = dynamic_cast< _TImage* >( this->_GetInput( 1 ) ); + + std::string r = + "cpm::Plugins::SimpleFillRegion: second image's pixel type not supported"; + cpmPlugins_SimpleFillRegion_Pixel2( r, P1, char, D, i2, _GD2 ); + else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, short, D, i2, _GD2 ); + else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, int, D, i2, _GD2 ); + else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, long, D, i2, _GD2 ); + else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, unsigned char, D, i2, _GD2 ); + else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, unsigned short, D, i2, _GD2 ); + else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, unsigned int, D, i2, _GD2 ); + else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, unsigned long, D, i2, _GD2 ); + else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, float, D, i2, _GD2 ); + else cpmPlugins_SimpleFillRegion_Pixel2( r, P1, double, D, i2, _GD2 ); + return( r ); +} + +// ------------------------------------------------------------------------- +template< typename I1, class I2, typename TCoordRep > +class SimpleFillRegionFunction + : public itk::BinaryThresholdImageFunction< I1, TCoordRep > +{ +public: + typedef SimpleFillRegionFunction Self; + typedef itk::BinaryThresholdImageFunction< I1, TCoordRep > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + itkTypeMacro( SimpleFillRegionFunction, itkBinaryThresholdImageFunction ); + itkNewMacro( Self ); + + itkSetConstObjectMacro( InputSegmentation, I2 ); + + typedef typename Superclass::InputImageType InputImageType; + typedef typename I1::PixelType PixelType; + itkStaticConstMacro(ImageDimension, unsigned int, Superclass::ImageDimension); + typedef typename Superclass::PointType PointType; + typedef typename Superclass::IndexType IndexType; + typedef typename Superclass::ContinuousIndexType ContinuousIndexType; + + virtual bool EvaluateAtIndex( const IndexType& index ) const + { + bool cont = true; + if( this->m_InputSegmentation.IsNotNull( ) ) + cont = ( + this->m_InputSegmentation->GetPixel( index ) == + ( typename I2::PixelType )( 0 ) + ); + if( cont ) + return( this->Superclass::EvaluateAtIndex( index ) ); + else + return( false ); + } + +protected: + SimpleFillRegionFunction( ) + : Superclass( ) + { + } + virtual ~SimpleFillRegionFunction( ) + { + } + +private: + // Purposely not implemented + SimpleFillRegionFunction( const Self& ); + Self& operator=( const Self& ); + +protected: + typename I2::ConstPointer m_InputSegmentation; +}; + +// ------------------------------------------------------------------------- +template< class P1, class P2, unsigned int D > +std::string cpm::Plugins::SimpleFillRegion:: +_GD2( ) +{ + typedef itk::Image< P1, D > _TImage1; + typedef itk::Image< P2, D > _TImage2; + + _TImage1* i1 = dynamic_cast< _TImage1* >( this->_GetInput( 0 ) ); + _TImage2* i2 = dynamic_cast< _TImage2* >( this->_GetInput( 1 ) ); + + // Transform input seed + typename _TImage1::PointType pnt; + TParameters::const_iterator sIt; + sIt = this->m_Parameters.find( "Seed" ); + if( sIt == this->m_Parameters.end( ) ) + return( "cpm::Plugins::SimpleFillRegion: no seed given." ); + char* buff = new char[ sIt->second.second.size( ) + 1 ]; + std::memcpy( buff, sIt->second.second.c_str( ), sIt->second.second.size( ) ); + buff[ sIt->second.second.size( ) ] = '\0'; + char* tok = std::strtok( buff, ":" ); + for( unsigned int d = 0; d < D; ++d ) + { + pnt[ d ] = std::atof( tok ); + tok = std::strtok( NULL, ":" ); + + } // rof + delete [] buff; + typename _TImage1::IndexType idx; + if( !( i1->TransformPhysicalPointToIndex( pnt, idx ) ) ) + return( "cpm::Plugins::SimpleFillRegion: seed is outside image regions." ); + + // Check spatial compatilibity + if( i1->GetLargestPossibleRegion( ) != i2->GetLargestPossibleRegion( ) ) + return( "cpm::Plugins::SimpleFillRegion: incompatible regions." ); + if( i1->GetSpacing( ) != i2->GetSpacing( ) ) + return( "cpm::Plugins::SimpleFillRegion: incompatible spacings." ); + if( i1->GetOrigin( ) != i2->GetOrigin( ) ) + return( "cpm::Plugins::SimpleFillRegion: incompatible origins." ); + if( i1->GetDirection( ) != i2->GetDirection( ) ) + return( "cpm::Plugins::SimpleFillRegion: incompatible directions." ); + + // Create output + cpPlugins::Interface::Image* out_obj = + dynamic_cast< cpPlugins::Interface::Image* >( this->GetOutput( 0 ) ); + typename _TImage2::Pointer out = + dynamic_cast< _TImage2* >( out_obj->GetDataObject( ) ); + if( out.IsNull( ) ) + { + out = _TImage2::New( ); + this->_SetOutput( 0, out ); + + } // fi + + // Create memory, if needed + if( + i1->GetLargestPossibleRegion( ) != out->GetLargestPossibleRegion( ) || + i1->GetSpacing( ) != out->GetSpacing( ) || + i1->GetOrigin( ) != out->GetOrigin( ) || + i1->GetDirection( ) != out->GetDirection( ) + ) + { + out->SetLargestPossibleRegion( i1->GetLargestPossibleRegion( ) ); + out->SetRequestedRegion( i1->GetRequestedRegion( ) ); + out->SetBufferedRegion( i1->GetBufferedRegion( ) ); + out->SetDirection( i1->GetDirection( ) ); + out->SetOrigin( i1->GetOrigin( ) ); + out->SetSpacing( i1->GetSpacing( ) ); + out->Allocate( ); + + } // fi + out->FillBuffer( P2( 0 ) ); + + P1 min_delta = P1( std::atof( this->m_Parameters[ "MinDelta" ].second.c_str( ) ) ); + P1 max_delta = P1( std::atof( this->m_Parameters[ "MaxDelta" ].second.c_str( ) ) ); + P1 lower = i1->GetPixel( idx ) - min_delta; + P1 upper = i1->GetPixel( idx ) + min_delta; + + typedef SimpleFillRegionFunction< _TImage1, _TImage2, double > _TFunction; + typename _TFunction::Pointer f = _TFunction::New( ); + f->SetInputImage( i1 ); + f->SetInputSegmentation( i2 ); + f->ThresholdBetween( lower, upper ); + + typedef + itk::FloodFilledImageFunctionConditionalConstIterator< _TImage1, _TFunction > + _TIterator; + _TIterator fIt( i1, f, idx ); + for( fIt.GoToBegin( ); !fIt.IsAtEnd( ); ++fIt ) + out->SetPixel( fIt.GetIndex( ), 1 ); + + return( "" ); } // eof - $RCSfile$