- 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
===========================================================================**/
#ifndef __clitkSetBackgroundImageFilter_h
#define __clitkSetBackgroundImageFilter_h
-#include "itkBinaryFunctorImageFilter.h"
+#include "itkFlexibleBinaryFunctorImageFilter.h"
#include "itkNumericTraits.h"
template <class TInputImage, class TMaskImage, class TOutputImage=TInputImage>
class ITK_EXPORT SetBackgroundImageFilter :
public
- itk::BinaryFunctorImageFilter<TInputImage,TMaskImage,TOutputImage,
+ itk::FlexibleBinaryFunctorImageFilter<TInputImage,TMaskImage,TOutputImage,
Functor::SetBackground<
typename TInputImage::PixelType,
typename TMaskImage::PixelType,
public:
/** Standard class typedefs. */
typedef SetBackgroundImageFilter Self;
- typedef itk::BinaryFunctorImageFilter<TInputImage,TMaskImage,TOutputImage,
+ typedef itk::FlexibleBinaryFunctorImageFilter<TInputImage,TMaskImage,TOutputImage,
Functor::SetBackground<
typename TInputImage::PixelType,
typename TMaskImage::PixelType,
/** Runtime information support. */
itkTypeMacro(SetBackgroundImageFilter,
- BinaryFunctorImageFilter);
+ FlexibleBinaryFunctorImageFilter);
/** Method to explicitly set the outside value of the mask. Defaults to 0 */
void SetOutsideValue( const typename TOutputImage::PixelType & outsideValue )
--- /dev/null
+/*=========================================================================
+
+ Program: Insight Segmentation & Registration Toolkit
+ Module: $RCSfile: itkFlexibleBinaryFunctorImageFilter.h,v $
+ Language: C++
+ Date: $Date: 2012-02-17 11:01:02 $
+ Version: $Revision: 1.37 $
+
+ 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_h
+#define __itkFlexibleBinaryFunctorImageFilter_h
+
+#include "itkInPlaceImageFilter.h"
+#include "itkImageRegionIteratorWithIndex.h"
+
+namespace itk
+{
+
+/** \class FlexibleBinaryFunctorImageFilter
+ * \brief Implements pixel-wise generic operation of two images.
+ *
+ * This class is parameterized over the types of the two input images
+ * and the type of the output image. It is also parameterized by the
+ * operation to be applied. A Functor style is used. The main difference
+ * wrt the standard BinaryFunctorImageFilter is that the second input's
+ * dimensions/spacing/origin can differ from those of the first. The
+ * functor is then only called if the pixel from input1 is inside
+ * input2's largest region.
+ *
+ * \sa UnaryFunctorImageFilter BinaryFunctorImageFilter TernaryFunctorImageFilter
+ *
+ * \ingroup IntensityImageFilters Multithreaded
+ */
+template <class TInputImage1, class TInputImage2,
+ class TOutputImage, class TFunction >
+class ITK_EXPORT FlexibleBinaryFunctorImageFilter :
+ public InPlaceImageFilter<TInputImage1,TOutputImage>
+{
+public:
+ /** Standard class typedefs. */
+ typedef FlexibleBinaryFunctorImageFilter Self;
+ typedef InPlaceImageFilter<TInputImage1,TOutputImage> Superclass;
+ typedef SmartPointer<Self> Pointer;
+ typedef SmartPointer<const Self> 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<itkGetStaticConstMacro(InputImage1Dimension),
+ itkGetStaticConstMacro(InputImage2Dimension)>));
+ itkConceptMacro(SameDimensionCheck2,
+ (Concept::SameDimension<itkGetStaticConstMacro(InputImage1Dimension),
+ itkGetStaticConstMacro(OutputImageDimension)>));
+ /** 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
--- /dev/null
+/*=========================================================================
+
+ 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 <class TInputImage1, class TInputImage2,
+ class TOutputImage, class TFunction >
+FlexibleBinaryFunctorImageFilter<TInputImage1,TInputImage2,TOutputImage,TFunction>
+::FlexibleBinaryFunctorImageFilter()
+{
+ this->SetNumberOfRequiredInputs( 1 );
+ this->SetInPlace(false);
+}
+
+
+/**
+ * Connect one of the operands for pixel-wise addition
+ */
+template <class TInputImage1, class TInputImage2,
+ class TOutputImage, class TFunction >
+void
+FlexibleBinaryFunctorImageFilter<TInputImage1,TInputImage2,TOutputImage,TFunction>
+::SetInput1( const TInputImage1 * image1 )
+{
+ // Process object is not const-correct so the const casting is required.
+ this->SetNthInput(0, const_cast<TInputImage1 *>( image1 ));
+}
+
+
+/**
+ * Connect one of the operands for pixel-wise addition
+ */
+template <class TInputImage1, class TInputImage2,
+ class TOutputImage, class TFunction >
+void
+FlexibleBinaryFunctorImageFilter<TInputImage1,TInputImage2,TOutputImage,TFunction>
+::SetInput2( const TInputImage2 * image2 )
+{
+ // Process object is not const-correct so the const casting is required.
+ //this->SetNthInput(1, const_cast<TInputImage2 *>( image2 ));
+
+ m_Input2 = image2;
+}
+
+template <class TInputImage1, class TInputImage2,
+ class TOutputImage, class TFunction >
+void
+FlexibleBinaryFunctorImageFilter<TInputImage1,TInputImage2,TOutputImage,TFunction>
+::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<TInputImage2 *>( m_Input2.GetPointer() );
+ image2->Update();
+}
+
+template <class TInputImage1, class TInputImage2,
+ class TOutputImage, class TFunction >
+void
+FlexibleBinaryFunctorImageFilter<TInputImage1,TInputImage2,TOutputImage,TFunction>
+::GenerateOutputInformation()
+{
+ Superclass::GenerateOutputInformation() ;
+}
+
+/**
+ * ThreadedGenerateData Performs the pixel-wise addition
+ */
+template <class TInputImage1, class TInputImage2, class TOutputImage, class TFunction >
+void
+FlexibleBinaryFunctorImageFilter<TInputImage1, TInputImage2, TOutputImage, TFunction>
+::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<const TInputImage1*>(ProcessObject::GetInput(0));
+ Input2ImagePointer inputPtr2 = m_Input2;
+/* = dynamic_cast<const TInputImage2*>(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<TInputImage1> inputIt1(inputPtr1, outputRegionForThread);
+ ImageRegionConstIterator<TInputImage2> inputIt2(inputPtr2, outputRegionForThread);
+
+ ImageRegionIterator<TOutputImage> 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