From a0b469cb6663824df2afd555fc901c52f77235c4 Mon Sep 17 00:00:00 2001 From: Romulo Pinho Date: Fri, 17 Feb 2012 11:02:29 +0100 Subject: [PATCH] new SetBackground filter - Accepts inputs and masks with different origins/spacings/dimensions. Only matching pixels are then processed. Non-mathcing pixels are directly copied from the input to the output. - Inhreits from new filter: itk::FlexibleBinaryFunctorImageFilter --- itk/clitkSetBackgroundImageFilter.h | 8 +- itk/itkFlexibleBinaryFunctorImageFilter.h | 165 ++++++++++++++++++++ itk/itkFlexibleBinaryFunctorImageFilter.txx | 159 +++++++++++++++++++ 3 files changed, 328 insertions(+), 4 deletions(-) create mode 100644 itk/itkFlexibleBinaryFunctorImageFilter.h create mode 100644 itk/itkFlexibleBinaryFunctorImageFilter.txx diff --git a/itk/clitkSetBackgroundImageFilter.h b/itk/clitkSetBackgroundImageFilter.h index 97b0bed..e5ac118 100644 --- a/itk/clitkSetBackgroundImageFilter.h +++ b/itk/clitkSetBackgroundImageFilter.h @@ -17,7 +17,7 @@ ===========================================================================**/ #ifndef __clitkSetBackgroundImageFilter_h #define __clitkSetBackgroundImageFilter_h -#include "itkBinaryFunctorImageFilter.h" +#include "itkFlexibleBinaryFunctorImageFilter.h" #include "itkNumericTraits.h" @@ -125,7 +125,7 @@ private: template class ITK_EXPORT SetBackgroundImageFilter : public - itk::BinaryFunctorImageFilter +class ITK_EXPORT FlexibleBinaryFunctorImageFilter : + public InPlaceImageFilter +{ +public: + /** Standard class typedefs. */ + typedef FlexibleBinaryFunctorImageFilter Self; + typedef InPlaceImageFilter Superclass; + typedef SmartPointer Pointer; + typedef SmartPointer ConstPointer; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(FlexibleBinaryFunctorImageFilter, InPlaceImageFilter); + + /** Some convenient typedefs. */ + typedef TFunction FunctorType; + typedef TInputImage1 Input1ImageType; + typedef typename Input1ImageType::ConstPointer Input1ImagePointer; + typedef typename Input1ImageType::RegionType Input1ImageRegionType; + typedef typename Input1ImageType::PixelType Input1ImagePixelType; + + typedef TInputImage2 Input2ImageType; + typedef typename Input2ImageType::ConstPointer Input2ImagePointer; + typedef typename Input2ImageType::RegionType Input2ImageRegionType; + typedef typename Input2ImageType::PixelType Input2ImagePixelType; + + typedef TOutputImage OutputImageType; + typedef typename OutputImageType::Pointer OutputImagePointer; + typedef typename OutputImageType::RegionType OutputImageRegionType; + typedef typename OutputImageType::PixelType OutputImagePixelType; + + /** Connect one of the operands for pixel-wise addition */ + void SetInput1( const TInputImage1 * image1); + + /** Connect one of the operands for pixel-wise addition */ + void SetInput2( const TInputImage2 * image2); + + /** Get the functor object. The functor is returned by reference. + * (Functors do not have to derive from itk::LightObject, so they do + * not necessarily have a reference count. So we cannot return a + * SmartPointer.) */ + FunctorType& GetFunctor() { return m_Functor; } + + /** Get the functor object. The functor is returned by reference. + * (Functors do not have to derive from itk::LightObject, so they do + * not necessarily have a reference count. So we cannot return a + * SmartPointer.) */ + const FunctorType& GetFunctor() const + { + return m_Functor; + } + + /** Set the functor object. This replaces the current Functor with a + * copy of the specified Functor. This allows the user to specify a + * functor that has ivars set differently than the default functor. + * This method requires an operator!=() be defined on the functor + * (or the compiler's default implementation of operator!=() being + * appropriate). */ + void SetFunctor(const FunctorType& functor) + { + if (m_Functor != functor) + { + m_Functor = functor; + this->Modified(); + } + } + + virtual void GenerateOutputInformation(); + virtual void GenerateInputRequestedRegion(); + + /** ImageDimension constants */ + itkStaticConstMacro( + InputImage1Dimension, unsigned int, TInputImage1::ImageDimension); + itkStaticConstMacro( + InputImage2Dimension, unsigned int, TInputImage2::ImageDimension); + itkStaticConstMacro( + OutputImageDimension, unsigned int, TOutputImage::ImageDimension); + +#ifdef ITK_USE_CONCEPT_CHECKING + /** Begin concept checking */ + itkConceptMacro(SameDimensionCheck1, + (Concept::SameDimension)); + itkConceptMacro(SameDimensionCheck2, + (Concept::SameDimension)); + /** End concept checking */ +#endif + +protected: + FlexibleBinaryFunctorImageFilter(); + virtual ~FlexibleBinaryFunctorImageFilter() {} + + /** FlexibleBinaryFunctorImageFilter can be implemented as a multithreaded filter. + * Therefore, this implementation provides a ThreadedGenerateData() routine + * which is called for each processing thread. The output image data is + * allocated automatically by the superclass prior to calling + * ThreadedGenerateData(). ThreadedGenerateData can only write to the + * portion of the output image specified by the parameter + * "outputRegionForThread" + * + * \sa ImageToImageFilter::ThreadedGenerateData(), + * ImageToImageFilter::GenerateData() */ + void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, + int threadId ); + +private: + FlexibleBinaryFunctorImageFilter(const Self&); //purposely not implemented + void operator=(const Self&); //purposely not implemented + + FunctorType m_Functor; + Input2ImagePointer m_Input2; +}; + +} // end namespace itk + +#ifndef ITK_MANUAL_INSTANTIATION +#include "itkFlexibleBinaryFunctorImageFilter.txx" +#endif + +#endif diff --git a/itk/itkFlexibleBinaryFunctorImageFilter.txx b/itk/itkFlexibleBinaryFunctorImageFilter.txx new file mode 100644 index 0000000..0914787 --- /dev/null +++ b/itk/itkFlexibleBinaryFunctorImageFilter.txx @@ -0,0 +1,159 @@ +/*========================================================================= + + Program: Insight Segmentation & Registration Toolkit + Module: $RCSfile: itkFlexibleBinaryFunctorImageFilter.txx,v $ + Language: C++ + Date: $Date: 2008-10-07 17:31:02 $ + Version: $Revision: 1.40 $ + + Copyright (c) Insight Software Consortium. All rights reserved. + See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __itkFlexibleBinaryFunctorImageFilter_txx +#define __itkFlexibleBinaryFunctorImageFilter_txx + +#include "itkFlexibleBinaryFunctorImageFilter.h" +#include "itkImageRegionIterator.h" +#include "itkImageRegionConstIterator.h" +#include "itkProgressReporter.h" + +namespace itk +{ + +/** + * Constructor + */ +template +FlexibleBinaryFunctorImageFilter +::FlexibleBinaryFunctorImageFilter() +{ + this->SetNumberOfRequiredInputs( 1 ); + this->SetInPlace(false); +} + + +/** + * Connect one of the operands for pixel-wise addition + */ +template +void +FlexibleBinaryFunctorImageFilter +::SetInput1( const TInputImage1 * image1 ) +{ + // Process object is not const-correct so the const casting is required. + this->SetNthInput(0, const_cast( image1 )); +} + + +/** + * Connect one of the operands for pixel-wise addition + */ +template +void +FlexibleBinaryFunctorImageFilter +::SetInput2( const TInputImage2 * image2 ) +{ + // Process object is not const-correct so the const casting is required. + //this->SetNthInput(1, const_cast( image2 )); + + m_Input2 = image2; +} + +template +void +FlexibleBinaryFunctorImageFilter +::GenerateInputRequestedRegion() +{ + Superclass::GenerateInputRequestedRegion(); + + // Process object is not const-correct so the const casting is required. + // This "manual" update step is necessary because m_Input2 is not in the pipeline, since + // it's dimensions can be different from input 1. + TInputImage2* image2 = const_cast( m_Input2.GetPointer() ); + image2->Update(); +} + +template +void +FlexibleBinaryFunctorImageFilter +::GenerateOutputInformation() +{ + Superclass::GenerateOutputInformation() ; +} + +/** + * ThreadedGenerateData Performs the pixel-wise addition + */ +template +void +FlexibleBinaryFunctorImageFilter +::ThreadedGenerateData( const OutputImageRegionType &outputRegionForThread, + int threadId) +{ + const unsigned int dim = Input1ImageType::ImageDimension; + + // We use dynamic_cast since inputs are stored as DataObjects. The + // ImageToImageFilter::GetInput(int) always returns a pointer to a + // TInputImage1 so it cannot be used for the second input. + Input1ImagePointer inputPtr1 + = dynamic_cast(ProcessObject::GetInput(0)); + Input2ImagePointer inputPtr2 = m_Input2; +/* = dynamic_cast(ProcessObject::GetInput(1));*/ + OutputImagePointer outputPtr = this->GetOutput(0); + + typename Input1ImageType::RegionType region2 = inputPtr2->GetLargestPossibleRegion(); + + typename Input1ImageType::IndexType index1; + typename Input2ImageType::IndexType index2; + typename Input1ImageType::PointType point1; + typename Input2ImageType::PointType point2; + + ImageRegionConstIterator inputIt1(inputPtr1, outputRegionForThread); + ImageRegionConstIterator inputIt2(inputPtr2, outputRegionForThread); + + ImageRegionIterator outputIt(outputPtr, outputRegionForThread); + + ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels()); + + inputIt1.GoToBegin(); + index1 = inputIt1.GetIndex(); + inputPtr1->TransformIndexToPhysicalPoint(index1, point1); + for (unsigned int i = 0; i < dim; i++) + point2[i] = point1[i]; + inputPtr2->TransformPhysicalPointToIndex(point2, index2); + inputIt2.SetIndex(index2); + outputIt.GoToBegin(); + + while( !inputIt1.IsAtEnd() ) { + + if (region2.IsInside(index2)) + outputIt.Set( m_Functor( inputIt1.Get(), inputIt2.Get() ) ); + else + outputIt.Set(inputIt1.Get()); + + ++inputIt1; + index1 = inputIt1.GetIndex(); + inputPtr1->TransformIndexToPhysicalPoint(index1, point1); + for (unsigned int i = 0; i < dim; i++) + point2[i] = point1[i]; + inputPtr2->TransformPhysicalPointToIndex(point2, index2); + inputIt2.SetIndex(index2); + ++outputIt; + + progress.CompletedPixel(); // potential exception thrown here + } +} + +} // end namespace itk + +#endif -- 2.45.1