From 9947c770b79585f718013305a956cf9473a4e0b2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Leonardo=20Fl=C3=B3rez-Valencia?= Date: Fri, 3 Mar 2017 18:05:19 -0500 Subject: [PATCH] ... --- .../Algorithms/ImageFunctorFilter.h | 82 +++----- .../Algorithms/ImageFunctorFilter.hxx | 65 ++++++ .../Algorithms/RGBToSingleChannelFunctor.h | 86 ++++++++ .../Algorithms/RGBToSingleChannelFunctor.hxx | 188 ++++++++++++++++++ lib/cpPlugins/Pipeline/Functor.cxx | 16 ++ lib/cpPlugins/Pipeline/Functor.h | 42 ++++ plugins/cpExtensions/ImageFunctorFilter.cxx | 60 ++++++ plugins/cpExtensions/ImageFunctorFilter.h | 33 +++ 8 files changed, 514 insertions(+), 58 deletions(-) create mode 100644 lib/cpExtensions/Algorithms/ImageFunctorFilter.hxx create mode 100644 lib/cpExtensions/Algorithms/RGBToSingleChannelFunctor.h create mode 100644 lib/cpExtensions/Algorithms/RGBToSingleChannelFunctor.hxx create mode 100644 lib/cpPlugins/Pipeline/Functor.cxx create mode 100644 lib/cpPlugins/Pipeline/Functor.h create mode 100644 plugins/cpExtensions/ImageFunctorFilter.cxx create mode 100644 plugins/cpExtensions/ImageFunctorFilter.h diff --git a/lib/cpExtensions/Algorithms/ImageFunctorFilter.h b/lib/cpExtensions/Algorithms/ImageFunctorFilter.h index d8a7eca..c1a32b0 100644 --- a/lib/cpExtensions/Algorithms/ImageFunctorFilter.h +++ b/lib/cpExtensions/Algorithms/ImageFunctorFilter.h @@ -2,13 +2,11 @@ // @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) // ------------------------------------------------------------------------- -#ifndef __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTORFILTER__H__ -#define __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTORFILTER__H__ +#ifndef __cpExtensions__Algorithms__ImageFunctorFilter__h__ +#define __cpExtensions__Algorithms__ImageFunctorFilter__h__ +#include #include -#include -#include -#include namespace cpExtensions { @@ -16,73 +14,37 @@ namespace cpExtensions { /** */ - template< class I, class O, class F > + template< class _TInputImage, class _TOutputImage > class ImageFunctorFilter : public itk::ImageToImageFilter< I, O > { public: - typedef ImageFunctorFilter Self; + typedef ImageFunctorFilter Self; typedef itk::ImageToImageFilter< I, O > Superclass; typedef itk::SmartPointer< Self > Pointer; typedef itk::SmartPointer< const Self > ConstPointer; - typedef I TInputImage; - typedef O TOutputImage; - typedef F TFunctor; + typedef _TInputImage TInputImage; + typedef _TOutputImage TOutputImage; + typedef typename TInputImage::PixelType TInputPixel; + typedef typename TOutputImage::PixelType TOutputPixel; + typedef typename TOutputImage::RegionType TRegion; - typedef typename O::RegionType TRegion; + typedef itk::FunctionBase< TInputPixel, TOutputPixel > TFunctor; public: itkNewMacro( Self ); itkTypeMacro( ImageFunctorFilter, itkImageToImageFilter ); - itkGetMacro( Functor, F ); - itkGetConstMacro( Functor, F ); + itkGetObjectMacro( Functor, TFunctor ); + itkGetConstObjectMacro( Functor, TFunctor ); + itkSetObjectMacro( Functor, TFunctor ); protected: - ImageFunctorFilter( ) - : Superclass( ) - { - } - virtual ~ImageFunctorFilter( ) - { - } - - virtual void ThreadedGenerateData( - const TRegion& region, - itk::ThreadIdType threadId - ) - { - const typename TRegion::SizeType& regionSize = region.GetSize( ); - if( regionSize[ 0 ] == 0 ) - return; - const I* in = this->GetInput( ); - O* out = this->GetOutput( 0 ); - - const size_t nLines = region.GetNumberOfPixels( ) / regionSize[ 0 ]; - itk::ProgressReporter progress( this, threadId, nLines ); - - // Define the iterators - itk::ImageScanlineConstIterator< I > inIt( in, region ); - itk::ImageScanlineIterator< O > outIt( out, region ); - - inIt.GoToBegin( ); - outIt.GoToBegin( ); - while( !inIt.IsAtEnd( ) ) - { - while( !inIt.IsAtEndOfLine( ) ) - { - outIt.Set( this->m_Functor( inIt.Get( ) ) ); - ++inIt; - ++outIt; - - } // elihw - inIt.NextLine( ); - outIt.NextLine( ); - progress.CompletedPixel( ); - - } // elihw - } + ImageFunctorFilter( ); + virtual ~ImageFunctorFilter( ); + + virtual void ThreadedGenerateData( const TRegion& region, itk::ThreadIdType threadId ) override; private: // Purposely not implemented. @@ -90,13 +52,17 @@ namespace cpExtensions void operator=( const Self& ); protected: - F m_Functor; + typename TFunctor::Pointer m_Functor; }; } // ecapseman } // ecapseman -#endif // __CPEXTENSIONS__ALGORITHMS__IMAGEFUNCTORFILTER__H__ +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __cpExtensions__Algorithms__ImageFunctorFilter__h__ // eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/ImageFunctorFilter.hxx b/lib/cpExtensions/Algorithms/ImageFunctorFilter.hxx new file mode 100644 index 0000000..73777da --- /dev/null +++ b/lib/cpExtensions/Algorithms/ImageFunctorFilter.hxx @@ -0,0 +1,65 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __cpExtensions__Algorithms__ImageFunctorFilter__hxx__ +#define __cpExtensions__Algorithms__ImageFunctorFilter__hxx__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +cpExtensions::Algorithms::ImageFunctorFilter< _TInputImage, _TOutputImage >:: +ImageFunctorFilter( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +cpExtensions::Algorithms::ImageFunctorFilter< _TInputImage, _TOutputImage >:: +~ImageFunctorFilter( ) +{ +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +void +cpExtensions::Algorithms::ImageFunctorFilter< _TInputImage, _TOutputImage >:: +ThreadedGenerateData( const TRegion& region, itk::ThreadIdType threadId ) +{ + // Configure data for this thread + const typename TRegion::SizeType& regionSize = region.GetSize( ); + if( regionSize[ 0 ] == 0 ) + return; + const TInputImage* in = this->GetInput( ); + TOutputImage* out = this->GetOutput( 0 ); + const size_t nLines = region.GetNumberOfPixels( ) / regionSize[ 0 ]; + itk::ProgressReporter progress( this, threadId, nLines ); + + // Iterate over this region + itk::ImageScanlineConstIterator< TInputImage > iIt( in, region ); + itk::ImageScanlineIterator< TOutputImage > oIt( out, region ); + iIt.GoToBegin( ); + oIt.GoToBegin( ); + while( !iIt.IsAtEnd( ) ) + { + while( !iIt.IsAtEndOfLine( ) ) + { + oIt.Set( this->m_Functor->Evaluate( iIt.Get( ) ) ); + ++iIt; + ++oIt; + + } // elihw + iIt.NextLine( ); + oIt.NextLine( ); + progress.CompletedPixel( ); + + } // elihw +} + +#endif // __cpExtensions__Algorithms__ImageFunctorFilter__hxx__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/RGBToSingleChannelFunctor.h b/lib/cpExtensions/Algorithms/RGBToSingleChannelFunctor.h new file mode 100644 index 0000000..815b936 --- /dev/null +++ b/lib/cpExtensions/Algorithms/RGBToSingleChannelFunctor.h @@ -0,0 +1,86 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __cpExtensions__Algorithms__RGBToSingleChannelFunctor__h__ +#define __cpExtensions__Algorithms__RGBToSingleChannelFunctor__h__ + +#include +#include + +namespace cpExtensions +{ + namespace Algorithms + { + /** + */ + template< class _TScalar > + class RGBToSingleChannelFunctor + : public itk::FunctionBase< itk::RGBPixel< _TScalar >, _TScalar > + { + public: + typedef _TScalar TScalar; + typedef itk::RGBPixel< _TScalar > TPixel; + typedef RGBToSingleChannelFunctor Self; + typedef itk::FunctionBase< TPixel, TScalar > Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + enum ChannelType + { + Red = 0, + Green, + Blue, + Hue, + Saturation, + Value + }; + + public: + itkNewMacro( Self ); + itkTypeMacro( RGBToSingleChannelFunctor, itkFunctionBase ); + + itkGetConstMacro( Channel, ChannelType ); + itkSetMacro( Channel, ChannelType ); + + public: + bool IsChannelRed( ) const; + bool IsChannelGreen( ) const; + bool IsChannelBlue( ) const; + bool IsChannelHue( ) const; + bool IsChannelSaturation( ) const; + bool IsChannelValue( ) const; + + void SetChannelToRed( ); + void SetChannelToGreen( ); + void SetChannelToBlue( ); + void SetChannelToHue( ); + void SetChannelToSaturation( ); + void SetChannelToValue( ); + + virtual TScalar Evaluate( const TPixel& pixel ) const override; + + protected: + RGBToSingleChannelFunctor( ); + virtual ~RGBToSingleChannelFunctor( ); + + private: + // Purposely not implemented. + RGBToSingleChannelFunctor( const Self& ); + void operator=( const Self& ); + + protected: + ChannelType m_Channel; + }; + + } // ecapseman + +} // ecapseman + +#ifndef ITK_MANUAL_INSTANTIATION +# include +#endif // ITK_MANUAL_INSTANTIATION + +#endif // __cpExtensions__Algorithms__RGBToSingleChannelFunctor__h__ + +// eof - $RCSfile$ diff --git a/lib/cpExtensions/Algorithms/RGBToSingleChannelFunctor.hxx b/lib/cpExtensions/Algorithms/RGBToSingleChannelFunctor.hxx new file mode 100644 index 0000000..c99e592 --- /dev/null +++ b/lib/cpExtensions/Algorithms/RGBToSingleChannelFunctor.hxx @@ -0,0 +1,188 @@ +// ------------------------------------------------------------------------- +// @author Leonardo Florez-Valencia (florez-l@javeriana.edu.co) +// ------------------------------------------------------------------------- + +#ifndef __cpExtensions__Algorithms__RGBToSingleChannelFunctor__hxx__ +#define __cpExtensions__Algorithms__RGBToSingleChannelFunctor__hxx__ + +#include +#include +#include + +// ------------------------------------------------------------------------- +template< class _TScalar > +bool cpExtensions::Algorithms::RGBToSingleChannelFunctor< _TScalar >:: +IsChannelRed( ) const +{ + return( this->m_Channel == Self::Red ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar > +bool cpExtensions::Algorithms::RGBToSingleChannelFunctor< _TScalar >:: +IsChannelGreen( ) const +{ + return( this->m_Channel == Self::Green ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar > +bool cpExtensions::Algorithms::RGBToSingleChannelFunctor< _TScalar >:: +IsChannelBlue( ) const +{ + return( this->m_Channel == Self::Blue ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar > +bool cpExtensions::Algorithms::RGBToSingleChannelFunctor< _TScalar >:: +IsChannelHue( ) const +{ + return( this->m_Channel == Self::Hue ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar > +bool cpExtensions::Algorithms::RGBToSingleChannelFunctor< _TScalar >:: +IsChannelSaturation( ) const +{ + return( this->m_Channel == Self::Saturation ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar > +bool cpExtensions::Algorithms::RGBToSingleChannelFunctor< _TScalar >:: +IsChannelValue( ) const +{ + return( this->m_Channel == Self::Value ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar > +void cpExtensions::Algorithms::RGBToSingleChannelFunctor< _TScalar >:: +SetChannelToRed( ) +{ + this->SetChannel( Self::Red ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar > +void cpExtensions::Algorithms::RGBToSingleChannelFunctor< _TScalar >:: +SetChannelToGreen( ) +{ + this->SetChannel( Self::Green ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar > +void cpExtensions::Algorithms::RGBToSingleChannelFunctor< _TScalar >:: +SetChannelToBlue( ) +{ + this->SetChannel( Self::Blue ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar > +void cpExtensions::Algorithms::RGBToSingleChannelFunctor< _TScalar >:: +SetChannelToHue( ) +{ + this->SetChannel( Self::Hue ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar > +void cpExtensions::Algorithms::RGBToSingleChannelFunctor< _TScalar >:: +SetChannelToSaturation( ) +{ + this->SetChannel( Self::Saturation ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar > +void cpExtensions::Algorithms::RGBToSingleChannelFunctor< _TScalar >:: +SetChannelToValue( ) +{ + this->SetChannel( Self::Value ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar > +_TScalar cpExtensions::Algorithms::RGBToSingleChannelFunctor< _TScalar >:: +Evaluate( const TPixel& pixel ) const +{ + _TScalar res; + switch( this->m_Channel ) + { + case Self::Hue: + { + double R = double( pixel.GetRed( ) ); + double G = double( pixel.GetRed( ) ); + double B = double( pixel.GetBlue( ) ); + double RG = R - G; + double RB = R - B; + double GB = G - B; + double A = std::sqrt( ( RG * RG ) + ( RB * GB ) ); + if( A != _0 ) + A = std::acos( ( RG + RB ) / ( double( 2 ) * A ) ); + A /= double( 2 ) * double( vnl_math::pi ); + res = + _TScalar( + double( std::numeric_limits< _TScalar >::max( ) ) * + ( ( G >= B )? A: double( 1 ) - A ) + ); + } + break; + case Self::Saturation: + { + double R = double( r ); + double G = double( g ); + double B = double( b ); + double sRGB = R + G + B; + double RG = R - G; + double RB = R - B; + double GB = G - B; + if( sRGB != double( 0 ) ) + { + double C = ( G < R )? G: R; + C = ( B < C )? B: C; + res = + _TScalar( + double( std::numeric_limits< _TScalar >::max( ) ) * + ( double( 1 ) - ( ( double( 3 ) * C ) / sRGB ) ) + ); + } + else + res = _TScalar( 0 ); + } + break; + case Self::Value: + { + res = ( pixel.GetRed( ) + pixel.GetGreen( ) + pixel.GetBlue( ) ) / 3; + } + break; + case Self::Green: { res = pixel.GetGreen( ); } break; + case Self::Blue: { res = pixel.GetBlue( ); } break; + case Self::Red: default: { res = pixel.GetRed( ); } break; + } // hctiws + return( res ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar > +cpExtensions::Algorithms::RGBToSingleChannelFunctor< _TScalar >:: +RGBToSingleChannelFunctor( ) + : Superclass( ) +{ + this->SetChannelToRed( ); +} + +// ------------------------------------------------------------------------- +template< class _TScalar > +cpExtensions::Algorithms::RGBToSingleChannelFunctor< _TScalar >:: +~RGBToSingleChannelFunctor( ) +{ +} + +#endif // __cpExtensions__Algorithms__RGBToSingleChannelFunctor__hxx__ + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Pipeline/Functor.cxx b/lib/cpPlugins/Pipeline/Functor.cxx new file mode 100644 index 0000000..2d7a883 --- /dev/null +++ b/lib/cpPlugins/Pipeline/Functor.cxx @@ -0,0 +1,16 @@ +#include + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::Functor:: +Functor( ) + : Superclass( ) +{ +} + +// ------------------------------------------------------------------------- +cpPlugins::Pipeline::Functor:: +~Functor( ) +{ +} + +// eof - $RCSfile$ diff --git a/lib/cpPlugins/Pipeline/Functor.h b/lib/cpPlugins/Pipeline/Functor.h new file mode 100644 index 0000000..bac4523 --- /dev/null +++ b/lib/cpPlugins/Pipeline/Functor.h @@ -0,0 +1,42 @@ +#ifndef __cpPlugins__Pipeline__Functor__h__ +#define __cpPlugins__Pipeline__Functor__h__ + +#include + +// ------------------------------------------------------------------------- +namespace cpPlugins +{ + namespace Pipeline + { + /** + */ + class cpPlugins_EXPORT Functor + : public ProcessObject + { + public: + typedef Functor Self; + typedef ProcessObject Superclass; + typedef itk::SmartPointer< Self > Pointer; + typedef itk::SmartPointer< const Self > ConstPointer; + + public: + itkTypeMacro( Functor, ProcessObject ); + cpPlugins_Id_Macro( Functor, Object ); + + protected: + Functor( ); + virtual ~Functor( ); + + private: + // Purposely not implemented + Functor( const Self& ); + Self& operator=( const Self& ); + }; + + } // ecapseman + +} // ecapseman + +#endif // __cpPlugins__Pipeline__Functor__h__ + +// eof - $RCSfile$ diff --git a/plugins/cpExtensions/ImageFunctorFilter.cxx b/plugins/cpExtensions/ImageFunctorFilter.cxx new file mode 100644 index 0000000..85cc494 --- /dev/null +++ b/plugins/cpExtensions/ImageFunctorFilter.cxx @@ -0,0 +1,60 @@ +#include +#include + +/* TODO + #include +*/ + +// ------------------------------------------------------------------------- +cpPluginscpExtensions::ImageFunctorFilter:: +ImageFunctorFilter( ) + : Superclass( ) +{ + typedef cpPlugins::DataObject _TFunctor; + typedef cpInstances::DataObjects::Image _TImage; + + this->_ConfigureInput< _TImage >( "Input", true, false ); + this->_ConfigureInput< _TFunctor >( "Functor", true, false ); + this->_ConfigureOutput< _TImage >( "Output" ); +} + +// ------------------------------------------------------------------------- +cpPluginscpExtensions::ImageFunctorFilter:: +~ImageFunctorFilter( ) +{ +} + +// ------------------------------------------------------------------------- +void cpPluginscpExtensions::ImageFunctorFilter:: +_GenerateData( ) +{ + auto o = this->GetInputData( "Input" ); + cpPlugins_Demangle_Image_ScalarPixels_AllDims_1( o, _GD0 ) + cpPlugins_Demangle_Image_ComplexPixels_AllDims_1( o, _GD0 ) + cpPlugins_Demangle_Image_ColorPixels_AllDims_1( o, _GD0 ) + cpPlugins_Demangle_Image_VectorPixels_AllDims_1( o, _GD0 ) + this->_Error( "Invalid input image pixel type." ); +} + +// ------------------------------------------------------------------------- +template< class _TInputImage > +void cpPluginscpExtensions::ImageFunctorFilter:: +_GD0( _TInputImage* input ) +{ + /* TODO + typedef cpExtensions::Visualization::ImageFunctorFilter< _TPath > _TFilter; + auto filter = this->_CreateVTK< _TFilter >( ); + filter->SetInput( path ); + filter->Update( ); + this->GetOutput( "Output" )->SetVTK( filter->GetOutput( ) ); + */ +} + +// ------------------------------------------------------------------------- +template< class _TInputImage, class _TOutputImage > +void cpPluginscpExtensions::ImageFunctorFilter:: +_GD1( _TInputImage* input ) +{ +} + +// eof - $RCSfile$ diff --git a/plugins/cpExtensions/ImageFunctorFilter.h b/plugins/cpExtensions/ImageFunctorFilter.h new file mode 100644 index 0000000..752d76f --- /dev/null +++ b/plugins/cpExtensions/ImageFunctorFilter.h @@ -0,0 +1,33 @@ +#ifndef __cpPluginscpExtensions__ImageFunctorFilter__h__ +#define __cpPluginscpExtensions__ImageFunctorFilter__h__ + +#include +#include + +namespace cpPluginscpExtensions +{ + /** + */ + class cpPlugins_cpExtensions_EXPORT ImageFunctorFilter + : public cpPlugins::Pipeline::ProcessObject + { + cpPluginsObject( + ImageFunctorFilter, + cpPlugins::Pipeline::ProcessObject, + cpExtensions + ); + + protected: + template< class _TInputImage > + inline void _GD0( _TInputImage* input ); + + template< class _TInputImage, class _TOutputImage > + inline void _GD1( _TInputImage* input ); + }; + +} // ecapseman + +#endif // __cpPluginscpExtensions__ImageFunctorFilter__h__ + + +// eof - $RCSfile$ -- 2.47.1