]> Creatis software - clitk.git/commitdiff
new SetBackground filter
authorRomulo Pinho <romulo.pinho@lyon.unicancer.fr>
Fri, 17 Feb 2012 10:02:29 +0000 (11:02 +0100)
committerRomulo Pinho <romulo.pinho@lyon.unicancer.fr>
Fri, 17 Feb 2012 10:02:29 +0000 (11:02 +0100)
- 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
itk/itkFlexibleBinaryFunctorImageFilter.h [new file with mode: 0644]
itk/itkFlexibleBinaryFunctorImageFilter.txx [new file with mode: 0644]

index 97b0bed121d50062e2096e85170b42b1aa7f7d40..e5ac118e58c8bf3a1d6de546b1b54a6dae80f241 100644 (file)
@@ -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 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,
@@ -136,7 +136,7 @@ class ITK_EXPORT SetBackgroundImageFilter :
 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,
@@ -150,7 +150,7 @@ public:
 
   /** 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 ) 
diff --git a/itk/itkFlexibleBinaryFunctorImageFilter.h b/itk/itkFlexibleBinaryFunctorImageFilter.h
new file mode 100644 (file)
index 0000000..c51ab0c
--- /dev/null
@@ -0,0 +1,165 @@
+/*=========================================================================
+
+  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
diff --git a/itk/itkFlexibleBinaryFunctorImageFilter.txx b/itk/itkFlexibleBinaryFunctorImageFilter.txx
new file mode 100644 (file)
index 0000000..0914787
--- /dev/null
@@ -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 <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