From afa84dc97029ada678d3fdc4e63ffa2b94e8fa79 Mon Sep 17 00:00:00 2001
From: Jonathan Guinet <jonathan.guinet@c-s.fr>
Date: Fri, 13 May 2011 17:29:20 +0200
Subject: [PATCH] ENH: make the ConnectedComponent/LabelMap filters compatible
 with the pipeline (do not request LargestPossibleRegion)

---
 .../otbLabelObjectOpeningMuParserFilter.h     |   6 +-
 .../otbLabelObjectOpeningMuParserFilter.txx   |  45 ++-
 .../otbRelabelComponentImageFilter.h          | 306 ++++++++++++++++++
 .../otbRelabelComponentImageFilter.txx        | 259 +++++++++++++++
 ...bBandsStatisticsAttributesLabelMapFilter.h |   6 +
 ...andsStatisticsAttributesLabelMapFilter.txx |  33 ++
 ...abelImageToLabelMapWithAdjacencyFilter.txx |  32 +-
 Code/OBIA/otbLabelMapToLabelImageFilter.h     |  95 ++++++
 Code/OBIA/otbLabelMapToLabelImageFilter.txx   |  69 ++++
 Code/OBIA/otbShapeAttributesLabelMapFilter.h  |  26 +-
 .../OBIA/otbShapeAttributesLabelMapFilter.txx |  94 +++++-
 11 files changed, 941 insertions(+), 30 deletions(-)
 create mode 100644 Code/BasicFilters/otbRelabelComponentImageFilter.h
 create mode 100644 Code/BasicFilters/otbRelabelComponentImageFilter.txx
 create mode 100644 Code/OBIA/otbLabelMapToLabelImageFilter.h
 create mode 100644 Code/OBIA/otbLabelMapToLabelImageFilter.txx

diff --git a/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.h b/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.h
index 2f574df3f1..b34c95a2f4 100644
--- a/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.h
+++ b/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.h
@@ -33,7 +33,6 @@
 #include "otbParser.h"
 #include "otbMacro.h"
 #include "itkMacro.h"
-#include "otbMaskMuParserFunctor.h"
 
 #include "itkInPlaceLabelMapFilter.h"
 #include "itkLabelObjectAccessors.h"
@@ -80,6 +79,7 @@ typedef typename ImageType::Pointer         ImagePointer;
 typedef typename ImageType::ConstPointer    ImageConstPointer;
 typedef typename ImageType::PixelType       PixelType;
 typedef typename ImageType::IndexType       IndexType;
+typedef typename ImageType::RegionType     InputImageRegionType;
 typedef typename ImageType::LabelObjectType LabelObjectType;
 typedef typename LabelObjectType::ConstPointer    LabelObjectConstPointer;
 typedef  TFunction                            FunctorType;
@@ -113,6 +113,10 @@ void DisplayVar() const;
 /** return list of Mu Parser varialbes and address**/
 const std::map<std::string, double*>& GetVar() const;
 
+void GenerateInputRequestedRegion();
+
+void EnlargeOutputRequestedRegion(itk::DataObject *){};
+
 void GenerateData();
 
 protected :
diff --git a/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.txx b/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.txx
index 2ce413ce14..364d98f2fb 100644
--- a/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.txx
+++ b/Code/BasicFilters/otbLabelObjectOpeningMuParserFilter.txx
@@ -100,16 +100,7 @@ void LabelObjectOpeningMuParserFilter<TImage, TFunction>::DisplayVar() const
 template< class TImage, class TFunction>
 bool LabelObjectOpeningMuParserFilter<TImage, TFunction>::CheckExpression()
 {
-  try
-  {
-    this->m_Functor.CheckExpression();
-  }
-  catch(itk::ExceptionObject& err)
-  {
-    itkWarningMacro(<< err);
-    return false;
-  }
-  return true;
+  return this->m_Functor.CheckExpression();
 }
 
 template< class TImage, class TFunction>
@@ -118,6 +109,40 @@ void LabelObjectOpeningMuParserFilter<TImage, TFunction>::SetAttributes(std::vec
   this->m_Functor.SetAttributes(shapeAttributes, statAttributes, nbOfBands);
 }
 
+template  < class TImage, class TFunction>
+void LabelObjectOpeningMuParserFilter<TImage, TFunction>::GenerateInputRequestedRegion()
+{
+  ImagePointer input = const_cast<ImageType *>(this->GetInput());
+
+      if ( !input )
+       { return; }
+
+  for (unsigned int idx = 0; idx < this->GetNumberOfInputs(); ++idx)
+      {
+       ImagePointer input = const_cast<ImageType *>(this->GetInput(idx));
+      if (!input.IsNull())
+        {
+        input->SetRequestedRegionToLargestPossibleRegion();
+        // Check whether the input is an image of the appropriate
+        // dimension (use ProcessObject's version of the GetInput()
+        // method since it returns the input as a pointer to a
+        // DataObject as opposed to the subclass version which
+        // static_casts the input to an TInputImage).
+
+        // Use the function object RegionCopier to copy the output region
+        // to the input.  The default region copier has default implementations
+        // to handle the cases where the input and output are the same
+        // dimension, the input a higher dimension than the output, and the
+        // input a lower dimension than the output.
+        InputImageRegionType inputRegion;
+        this->CallCopyOutputRegionToInputRegion(inputRegion, this->GetOutput()->GetRequestedRegion());
+        input->SetRequestedRegion( inputRegion );
+        }
+      }
+}
+
+
+
 template  < class TImage, class TFunction>
 void LabelObjectOpeningMuParserFilter<TImage, TFunction>::GenerateData()
     {
diff --git a/Code/BasicFilters/otbRelabelComponentImageFilter.h b/Code/BasicFilters/otbRelabelComponentImageFilter.h
new file mode 100644
index 0000000000..04036749be
--- /dev/null
+++ b/Code/BasicFilters/otbRelabelComponentImageFilter.h
@@ -0,0 +1,306 @@
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkRelabelComponentImageFilter.h,v $
+  Language:  C++
+  Date:      $Date: 2009-04-27 22:58:48 $
+  Version:   $Revision: 1.17 $
+
+  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 __otbRelabelComponentImageFilter_h
+#define __otbRelabelComponentImageFilter_h
+
+#include "itkInPlaceImageFilter.h"
+#include "itkImage.h"
+#include <vector>
+
+namespace otb
+{
+
+/**
+ * \class RelabelComponentImageFilter
+ * \brief Relabel the components in an image such that consecutive labels are used.
+ *
+ * RelabelComponentImageFilter remaps the labels associated with the
+ * objects in an image (as from the output of
+ * ConnectedComponentImageFilter) such that the label numbers are
+ * consecutive with no gaps between the label numbers used.  By
+ * default, the relabeling will also sort the labels based on the size
+ * of the object: the largest object will have label #1, the second
+ * largest will have label #2, etc.
+ *
+ * Label #0 is assumed to be background is left unaltered by the
+ * relabeling. 
+ *
+ * RelabelComponentImageFilter is typically used on the output of the
+ * ConnectedComponentImageFilter for those applications that want to
+ * extract the largest object or the "k" largest objects. Any
+ * particular object can be extracted from the relabeled output using
+ * a BinaryThresholdImageFilter. A group of objects can be extracted
+ * from the relabled output using a ThresholdImageFilter.
+ *
+ * Once all the objects are relabeled, the application can query the
+ * number of objects and the size of each object. Object sizes are
+ * returned in a vector. The size of the background is not
+ * calculated. So the size of object #1 is
+ * GetSizeOfObjectsInPixels()[0], the size of object #2 is
+ * GetSizeOfObjectsInPixels()[1], etc.
+ *
+ * If user sets a minimum object size, all objects with fewer pixelss
+ * than the minimum will be discarded, so that the number of objects
+ * reported will be only those remaining. The
+ * GetOriginalNumberOfObjects method can be called to find out how
+ * many objects were present before the small ones were discarded.
+ *
+ * RelabelComponentImageFilter can be run as an "in place" filter,
+ * where it will overwrite its output.  The default is run out of
+ * place (or generate a separate output).  "In place" operation can be
+ * controlled via methods in the superclass,
+ * InPlaceImageFilter::InPlaceOn() and InPlaceImageFilter::InPlaceOff().
+ *
+ * \sa ConnectedComponentImageFilter, BinaryThresholdImageFilter, ThresholdImageFilter
+ *
+ * \ingroup Singlethreaded
+ */
+
+template <class TInputImage, class TOutputImage>
+class ITK_EXPORT RelabelComponentImageFilter : 
+    public itk::InPlaceImageFilter< TInputImage, TOutputImage >
+{
+public:
+  /**
+   * Standard "Self" & Superclass typedef.
+   */
+  typedef RelabelComponentImageFilter                     Self;
+  typedef itk::InPlaceImageFilter< TInputImage, TOutputImage > Superclass;
+
+  /**
+   * Types from the Superclass
+   */
+  typedef typename Superclass::InputImagePointer InputImagePointer;
+
+  /**
+   * Extract some information from the image types.  Dimensionality
+   * of the two images is assumed to be the same.
+   */
+  typedef typename TOutputImage::PixelType         OutputPixelType;
+  typedef typename TOutputImage::InternalPixelType OutputInternalPixelType;
+  typedef typename TInputImage::PixelType          InputPixelType;
+  typedef typename TInputImage::InternalPixelType  InputInternalPixelType;
+  itkStaticConstMacro(ImageDimension, unsigned int,
+                      TOutputImage::ImageDimension); 
+  itkStaticConstMacro(InputImageDimension, unsigned int,
+                      TInputImage::ImageDimension);
+ 
+  /**
+   * Image typedef support
+   */
+  typedef TInputImage                             InputImageType;
+  typedef TOutputImage                            OutputImageType;
+  typedef   typename TInputImage::IndexType       IndexType;
+  typedef   typename TInputImage::SizeType        SizeType;
+  typedef   typename TOutputImage::RegionType     RegionType;
+
+  /** 
+   * Smart pointer typedef support 
+   */
+  typedef itk::SmartPointer<Self>        Pointer;
+  typedef itk::SmartPointer<const Self>  ConstPointer;
+  
+  /**
+   * Run-time type information (and related methods)
+   */
+  itkTypeMacro(RelabelComponentImageFilter, ImageToImageFilter);
+  
+  /**
+   * Method for creation through the object factory.
+   */
+  itkNewMacro(Self);
+
+  /** Type used as identifier for the different component lables. */
+  typedef unsigned long int    LabelType;
+
+  /** Type used to count number of pixels in objects. */
+  typedef unsigned long int    ObjectSizeType;
+
+  /** Get the number of objects in the image. This information is only
+   * valid after the filter has executed. */
+  itkGetConstMacro(NumberOfObjects, LabelType);
+  
+  /** Get the original number of objects in the image before small
+   * objects were discarded. This information is only valid after
+   * the filter has executed. If the caller has not specified a
+   * minimum object size, OriginalNumberOfObjects is the same as
+   * NumberOfObjects. */
+  itkGetConstMacro(OriginalNumberOfObjects, LabelType);
+
+  /** Get/Set the number of objects enumerated and described when the
+   * filter is printed. */
+  itkSetMacro(NumberOfObjectsToPrint, LabelType);
+  itkGetConstReferenceMacro(NumberOfObjectsToPrint, LabelType);
+
+  /** Set the minimum size in pixels for an object. All objects
+   * smaller than this size will be discarded and will not appear
+   * in the output label map. NumberOfObjects will count only the
+   * objects whose pixel counts are greater than or equal to the
+   * minimum size. Call GetOriginalNumberOfObjects to find out how
+   * many objects were present in the original label map. */
+  itkSetMacro(MinimumObjectSize, ObjectSizeType);
+
+  /** Get the caller-defined minimum size of an object in pixels.
+   * If the caller has not set the minimum, 0 will be returned,
+   * which is to be interpreted as meaning that no minimum exists,
+   * and all objects in the original label map will be passed
+   * through to the output. */
+  itkGetConstMacro(MinimumObjectSize, ObjectSizeType);
+   
+  /** Get the size of each object in pixels. This information is only
+   * valid after the filter has executed.  Size of the background is
+   * not calculated.  Size of object #1 is
+   * GetSizeOfObjectsInPixels()[0]. Size of object #2 is
+   * GetSizeOfObjectsInPixels()[1]. Etc. */
+  const std::vector<ObjectSizeType>& GetSizeOfObjectsInPixels() const
+    { return m_SizeOfObjectsInPixels; }
+
+  /** Get the size of each object in physical space (in units of pixel
+   * size). This information is only valid after the filter has
+   * executed. Size of the background is not calculated.  Size of
+   * object #1 is GetSizeOfObjectsInPhysicalUnits()[0]. Size of object
+   * #2 is GetSizeOfObjectsInPhysicalUnits()[1]. Etc. */
+  const std::vector<float>& GetSizeOfObjectsInPhysicalUnits() const
+    { return m_SizeOfObjectsInPhysicalUnits; }
+
+  /** Get the size of a particular object in pixels. This information is only
+   * valid after the filter has executed.  Size of the background
+   * (object #0) is not calculated.  */
+  ObjectSizeType GetSizeOfObjectInPixels( LabelType obj ) const
+    {
+    if (obj > 0 && obj <= m_NumberOfObjects)
+      {
+      return m_SizeOfObjectsInPixels[obj-1];
+      }
+    else
+      {
+      return 0;
+      }
+    }
+  
+  /** Get the size of a particular object in physical space (in units of pixel
+   * size). This information is only valid after the filter has
+   * executed. Size of the background (object #0) is not calculated.  */
+  float GetSizeOfObjectInPhysicalUnits( LabelType obj ) const
+    { 
+    if (obj > 0 && obj <= m_NumberOfObjects)
+      {
+      return m_SizeOfObjectsInPhysicalUnits[obj-1];
+      }
+    else
+      {
+      return 0;
+      }
+    }
+
+#ifdef ITK_USE_CONCEPT_CHECKING
+  /** Begin concept checking */
+  itkConceptMacro(InputEqualityComparableCheck,
+    (itk::Concept::EqualityComparable<InputPixelType>));
+  itkConceptMacro(UnsignedLongConvertibleToInputCheck,
+    (itk::Concept::Convertible<LabelType, InputPixelType>));
+  itkConceptMacro(OutputLongConvertibleToUnsignedLongCheck,
+    (itk::Concept::Convertible<OutputPixelType, LabelType>));
+  itkConceptMacro(InputConvertibleToOutputCheck,
+    (itk::Concept::Convertible<InputPixelType, OutputPixelType>));
+  itkConceptMacro(SameDimensionCheck,
+    (itk::Concept::SameDimension<InputImageDimension, ImageDimension>));
+  /** End concept checking */
+#endif
+
+protected:
+
+  RelabelComponentImageFilter()
+    : m_NumberOfObjects(0), m_NumberOfObjectsToPrint(10),
+    m_OriginalNumberOfObjects(0), m_MinimumObjectSize(0)
+    { this->InPlaceOff(); }
+  virtual ~RelabelComponentImageFilter() {}
+  RelabelComponentImageFilter(const Self&) {}
+
+  /**
+   * Standard pipeline method. 
+   */
+  void GenerateData();
+
+  /** RelabelComponentImageFilter needs the entire input. Therefore
+   * it must provide an implementation GenerateInputRequestedRegion().
+   * \sa ProcessObject::GenerateInputRequestedRegion(). */
+  void GenerateInputRequestedRegion();
+
+  /**
+    * Initialize parameters.
+    */
+   void Init();
+
+  /** Standard printself method */
+  void PrintSelf(std::ostream& os, itk::Indent indent) const;
+
+  struct RelabelComponentObjectType
+    {
+    LabelType       m_ObjectNumber;
+    ObjectSizeType  m_SizeInPixels;
+    float           m_SizeInPhysicalUnits;
+    };
+
+  // put the function objects here for sorting in descending order
+  class RelabelComponentSizeInPixelsComparator
+    {
+    public:
+      bool operator()(const RelabelComponentObjectType&a, 
+                      const RelabelComponentObjectType &b)
+      {
+      if (a.m_SizeInPixels > b.m_SizeInPixels)
+        {
+        return true;
+        }
+      else if (a.m_SizeInPixels < b.m_SizeInPixels)
+        {
+        return false;
+        }
+      // size in pixels and physical units are the same, sort based on
+      // original object number
+      else if (a.m_ObjectNumber < b.m_ObjectNumber)
+        {
+        return true;
+        }
+      else
+        {
+        return false;
+        }
+      }
+  };
+  
+
+private:
+
+  LabelType       m_NumberOfObjects;
+  LabelType       m_NumberOfObjectsToPrint;
+  LabelType       m_OriginalNumberOfObjects;
+  ObjectSizeType  m_MinimumObjectSize;
+
+  std::vector<ObjectSizeType> m_SizeOfObjectsInPixels;
+  std::vector<float>          m_SizeOfObjectsInPhysicalUnits;
+
+};
+  
+} // end namespace otb
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "otbRelabelComponentImageFilter.txx"
+#endif
+
+#endif
diff --git a/Code/BasicFilters/otbRelabelComponentImageFilter.txx b/Code/BasicFilters/otbRelabelComponentImageFilter.txx
new file mode 100644
index 0000000000..f106cdb35d
--- /dev/null
+++ b/Code/BasicFilters/otbRelabelComponentImageFilter.txx
@@ -0,0 +1,259 @@
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkRelabelComponentImageFilter.txx,v $
+  Language:  C++
+  Date:      $Date: 2009-04-27 22:58:48 $
+  Version:   $Revision: 1.18 $
+
+  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 __otbRelabelComponentImageFilter_txx
+#define __otbRelabelComponentImageFilter_txx
+
+#include "otbRelabelComponentImageFilter.h"
+#include "itkImageRegionIterator.h"
+#include "itkImageRegionConstIterator.h"
+#include "itkNumericTraits.h"
+#include "itkProgressReporter.h"
+#include "itk_hash_map.h"
+#include <map>
+
+namespace otb
+{
+
+template< class TInputImage, class TOutputImage >
+void
+RelabelComponentImageFilter< TInputImage, TOutputImage >
+::GenerateInputRequestedRegion()
+{
+
+  itk::ImageToImageFilter<TInputImage, TOutputImage>::GenerateInputRequestedRegion();
+}
+
+
+template< class TInputImage, class TOutputImage >
+void
+RelabelComponentImageFilter< TInputImage, TOutputImage >
+::GenerateData()
+{
+  unsigned long i;
+  
+  // Use a map to keep track of the size of each object.  Object
+  // number -> ObjectType (which has Object number and the two sizes)
+  typedef itk::hash_map<LabelType, RelabelComponentObjectType> MapType;
+  MapType sizeMap;
+  typename MapType::iterator mapIt;
+  typedef typename MapType::value_type MapValueType;
+
+  // Get the input and the output
+  typename TInputImage::ConstPointer input = this->GetInput();
+  typename TOutputImage::Pointer output = this->GetOutput();
+
+  // Setup a progress reporter.  We have 2 stages to the algorithm so
+  // use the total number of pixels accessed. We walk the entire input
+  // in the first pass, then walk just the output requested region in
+  // the second pass.
+  itk::ProgressReporter progress(this, 0,
+                            input->GetRequestedRegion().GetNumberOfPixels() +
+                            output->GetRequestedRegion().GetNumberOfPixels());
+
+
+  // Calculate the size of pixel
+  float physicalPixelSize = 1.0;
+  for (i=0; i < TInputImage::ImageDimension; ++i)
+    {
+    physicalPixelSize *= input->GetSpacing()[i];
+    }
+
+  RelabelComponentObjectType initialSize;
+  initialSize.m_SizeInPixels = 1;
+  initialSize.m_SizeInPhysicalUnits = physicalPixelSize;
+
+  // First pass: walk the entire input image and determine what
+  // labels are used and the number of pixels used in each label.
+  //
+
+  // walk the input
+  itk::ImageRegionConstIterator<InputImageType> it(input, input->GetRequestedRegion());
+  it.GoToBegin();
+
+  while (!it.IsAtEnd())
+    {
+    // Get the input pixel value
+    const LabelType inputValue = static_cast< LabelType>( it.Get() );
+
+    // if the input pixel is not the background
+    if (inputValue != itk::NumericTraits<LabelType>::Zero)
+      {
+      // Does this label already exist
+      mapIt = sizeMap.find( inputValue );
+      if ( mapIt == sizeMap.end() )
+        {
+        // label is not currently in the map
+        initialSize.m_ObjectNumber = inputValue;
+        sizeMap.insert( MapValueType( inputValue, initialSize ) );
+        }
+      else
+        {
+        // label is already in the map, update the values
+        (*mapIt).second.m_SizeInPixels++;
+        (*mapIt).second.m_SizeInPhysicalUnits += physicalPixelSize;
+        }
+      }
+
+    // increment the iterators
+    ++it;
+    progress.CompletedPixel();
+    }
+
+  // Now we need to reorder the labels. Use the m_ObjectSortingOrder
+  // to determine how to sort the objects. Define a map for converting
+  // input labels to output labels.
+  //
+  typedef std::vector<RelabelComponentObjectType> VectorType;
+  VectorType sizeVector;
+  typename VectorType::iterator vit;
+
+  typedef std::map< LabelType, LabelType > RelabelMapType;
+  RelabelMapType relabelMap;
+
+  // copy the original object map to a vector so we can sort it
+  for (mapIt = sizeMap.begin(); mapIt != sizeMap.end(); ++mapIt)
+    {
+    sizeVector.push_back( (*mapIt).second );
+    }
+
+  // sort the objects by size and define the map to use to relabel the image
+  std::sort(sizeVector.begin(), sizeVector.end(), RelabelComponentSizeInPixelsComparator() );
+
+  // create a lookup table to map the input label to the output label.
+  // cache the object sizes for later access by the user
+  m_NumberOfObjects = sizeVector.size();
+  m_OriginalNumberOfObjects = sizeVector.size();
+  m_SizeOfObjectsInPixels.clear();
+  m_SizeOfObjectsInPixels.resize(m_NumberOfObjects);
+  m_SizeOfObjectsInPhysicalUnits.clear();
+  m_SizeOfObjectsInPhysicalUnits.resize(m_NumberOfObjects);
+  int NumberOfObjectsRemoved = 0;
+  for (i=0, vit = sizeVector.begin(); vit != sizeVector.end(); ++vit, ++i)
+    {
+
+    // if we find an object smaller than the minimum size, we
+    // terminate the loop.
+    if (m_MinimumObjectSize > 0 && (*vit).m_SizeInPixels < m_MinimumObjectSize)
+      {
+      // map small objects to the background
+      NumberOfObjectsRemoved++;
+      relabelMap.insert(RelabelMapType::value_type( (*vit).m_ObjectNumber, 0));
+      }
+    else
+      {
+      // map for input labels to output labels (Note we use i+1 in the
+      // map since index 0 is the background)
+      relabelMap.insert(RelabelMapType::value_type( (*vit).m_ObjectNumber, i+1));
+      
+      // cache object sizes for later access by the user
+      m_SizeOfObjectsInPixels[i] = (*vit).m_SizeInPixels;
+      m_SizeOfObjectsInPhysicalUnits[i] = (*vit).m_SizeInPhysicalUnits;
+      }
+
+    }
+
+  // update number of objects and resize cache vectors if we have removed small objects
+  m_NumberOfObjects -= NumberOfObjectsRemoved;
+  if (NumberOfObjectsRemoved > 0)
+    {
+    m_SizeOfObjectsInPixels.resize(m_NumberOfObjects);
+    m_SizeOfObjectsInPhysicalUnits.resize(m_NumberOfObjects);
+    }
+
+  // Second pass: walk just the output requested region and relabel
+  // the necessary pixels.
+  //
+
+  // Allocate the output
+  this->AllocateOutputs();
+
+  // Remap the labels.  Note we only walk the region of the output
+  // that was requested.  This may be a subset of the input image.
+  OutputPixelType outputValue;
+  itk::ImageRegionIterator<OutputImageType> oit;
+  oit = itk::ImageRegionIterator<OutputImageType>(output,
+                                             output->GetRequestedRegion());
+  it = itk::ImageRegionConstIterator<InputImageType>(input,
+                                                output->GetRequestedRegion());
+
+  it.GoToBegin();
+  oit.GoToBegin();
+  while ( !oit.IsAtEnd() )
+    {
+    const LabelType inputValue = static_cast< LabelType>( it.Get() );
+    
+    if (inputValue != itk::NumericTraits<LabelType>::Zero)
+      {
+
+      // lookup the mapped label
+      outputValue = static_cast<OutputPixelType>(relabelMap[inputValue]); 
+      oit.Set( outputValue );
+      }
+    else
+      {
+      oit.Set( inputValue );
+      }
+
+    // increment the iterators
+    ++it;
+    ++oit;
+    progress.CompletedPixel();
+    }
+}
+
+
+template< class TInputImage, class TOutputImage >
+void
+RelabelComponentImageFilter< TInputImage, TOutputImage >
+::PrintSelf(std::ostream& os, itk::Indent indent) const
+{
+  Superclass::PrintSelf(os, indent);
+
+  os << indent << "NumberOfObjects: " << m_NumberOfObjects << std::endl;
+  os << indent << "OriginalNumberOfObjects: " << m_OriginalNumberOfObjects << std::endl;
+  os << indent << "NumberOfObjectsToPrint: "
+     << m_NumberOfObjectsToPrint << std::endl;
+  os << indent << "MinimumObjectSizez: " << m_MinimumObjectSize << std::endl;
+
+  std::vector<ObjectSizeType>::const_iterator it;
+  std::vector<float>::const_iterator fit;
+  LabelType i;
+
+  // limit the number of objects to print
+  LabelType numPrint = m_NumberOfObjectsToPrint;
+  if (numPrint > m_SizeOfObjectsInPixels.size())
+    {
+    numPrint = m_SizeOfObjectsInPixels.size();
+    }
+
+
+  for (i=0, it = m_SizeOfObjectsInPixels.begin(),
+         fit = m_SizeOfObjectsInPhysicalUnits.begin();
+       i < numPrint; ++it, ++fit, ++i)
+    {
+    os << indent << "Object #" << i+1 << ": " << *it << " pixels, "
+       << *fit << " physical units" << std::endl;
+    }
+  if (numPrint < m_SizeOfObjectsInPixels.size())
+    {
+    os << indent << "..." << std::endl;
+    }
+}
+
+} // end namespace itk
+
+#endif
diff --git a/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.h b/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.h
index eb510a4de3..501e230e82 100644
--- a/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.h
+++ b/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.h
@@ -138,6 +138,7 @@ class ITK_EXPORT BandsStatisticsAttributesLabelMapFilter
 public:
   /** Some convenient typedefs. */
   typedef TImage                                       ImageType;
+  typedef typename ImageType::RegionType     InputImageRegionType;
   typedef typename ImageType::LabelObjectType          LabelObjectType;
   typedef TFeatureImage                                FeatureImageType;
   typedef typename FeatureImageType::InternalPixelType FeatureInternalPixelType;
@@ -154,6 +155,7 @@ public:
   <ImageType, FunctorType>                                Superclass;
   typedef itk::SmartPointer<Self>       Pointer;
   typedef itk::SmartPointer<const Self> ConstPointer;
+  typedef typename ImageType::Pointer         ImagePointer;
 
   /** ImageDimension constants */
   itkStaticConstMacro(ImageDimension, unsigned int, TImage::ImageDimension);
@@ -184,6 +186,10 @@ protected:
   /** Destructor */
   ~BandsStatisticsAttributesLabelMapFilter() {}
 
+  void GenerateInputRequestedRegion();
+
+  void EnlargeOutputRequestedRegion(itk::DataObject *){};
+
   /** Before threaded data generation */
   virtual void BeforeThreadedGenerateData();
 
diff --git a/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.txx b/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.txx
index 77fe216133..5309e0ff66 100644
--- a/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.txx
+++ b/Code/OBIA/otbBandsStatisticsAttributesLabelMapFilter.txx
@@ -210,6 +210,39 @@ BandsStatisticsAttributesLabelMapFilter<TImage, TFeatureImage>
   return this->GetFunctor().GetReducedAttributeSet();
 }
 
+template <class TImage, class TFeatureImage>
+void
+BandsStatisticsAttributesLabelMapFilter<TImage, TFeatureImage>
+::GenerateInputRequestedRegion()
+{
+
+  for (unsigned int idx = 0; idx < this->GetNumberOfInputs(); ++idx)
+      {
+       ImagePointer input = const_cast<ImageType *>(this->GetInput(idx));
+      if (!input.IsNull())
+        {
+        input->SetRequestedRegionToLargestPossibleRegion();
+        // Check whether the input is an image of the appropriate
+        // dimension (use ProcessObject's version of the GetInput()
+        // method since it returns the input as a pointer to a
+        // DataObject as opposed to the subclass version which
+        // static_casts the input to an TInputImage).
+
+        // Use the function object RegionCopier to copy the output region
+        // to the input.  The default region copier has default implementations
+        // to handle the cases where the input and output are the same
+        // dimension, the input a higher dimension than the output, and the
+        // input a lower dimension than the output.
+        InputImageRegionType inputRegion;
+        this->CallCopyOutputRegionToInputRegion(inputRegion, this->GetOutput()->GetRequestedRegion());
+        input->SetRequestedRegion( inputRegion );
+        }
+      }
+}
+
+
+
+
 template <class TImage, class TFeatureImage>
 void
 BandsStatisticsAttributesLabelMapFilter<TImage, TFeatureImage>
diff --git a/Code/OBIA/otbLabelImageToLabelMapWithAdjacencyFilter.txx b/Code/OBIA/otbLabelImageToLabelMapWithAdjacencyFilter.txx
index 9dfc10494c..c6fef88335 100644
--- a/Code/OBIA/otbLabelImageToLabelMapWithAdjacencyFilter.txx
+++ b/Code/OBIA/otbLabelImageToLabelMapWithAdjacencyFilter.txx
@@ -40,14 +40,28 @@ void
 LabelImageToLabelMapWithAdjacencyFilter<TInputImage, TOutputImage>
 ::GenerateInputRequestedRegion()
 {
-  // call the superclass' implementation of this method
-  Superclass::GenerateInputRequestedRegion();
-  
-  // We need all the input.
-  InputImagePointer input = const_cast<InputImageType *>(this->GetInput());
-  if ( !input )
-    { return; }
-  input->SetRequestedRegion( input->GetLargestPossibleRegion() );
+  for (unsigned int idx = 0; idx < this->GetNumberOfInputs(); ++idx)
+        {
+         InputImagePointer input = const_cast<InputImageType *>(this->GetInput(idx));
+        if (!input.IsNull())
+          {
+          input->SetRequestedRegionToLargestPossibleRegion();
+          // Check whether the input is an image of the appropriate
+          // dimension (use ProcessObject's version of the GetInput()
+          // method since it returns the input as a pointer to a
+          // DataObject as opposed to the subclass version which
+          // static_casts the input to an TInputImage).
+
+          // Use the function object RegionCopier to copy the output region
+          // to the input.  The default region copier has default implementations
+          // to handle the cases where the input and output are the same
+          // dimension, the input a higher dimension than the output, and the
+          // input a lower dimension than the output.
+          InputImageRegionType inputRegion;
+          this->CallCopyOutputRegionToInputRegion(inputRegion, this->GetOutput()->GetRequestedRegion());
+          input->SetRequestedRegion( inputRegion );
+          }
+        }
 }
 
 
@@ -56,8 +70,6 @@ void
 LabelImageToLabelMapWithAdjacencyFilter<TInputImage, TOutputImage>
 ::EnlargeOutputRequestedRegion(itk::DataObject *)
 {
-  this->GetOutput()
-    ->SetRequestedRegion( this->GetOutput()->GetLargestPossibleRegion() );
 }
 
 
diff --git a/Code/OBIA/otbLabelMapToLabelImageFilter.h b/Code/OBIA/otbLabelMapToLabelImageFilter.h
new file mode 100644
index 0000000000..d67db14f6b
--- /dev/null
+++ b/Code/OBIA/otbLabelMapToLabelImageFilter.h
@@ -0,0 +1,95 @@
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkLabelMapToLabelImageFilter.h,v $
+  Language:  C++
+  Date:      $Date: 2009-07-30 22:54:24 $
+  Version:   $Revision: 1.3 $
+
+  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 __otbLabelMapToLabelImageFilter_h
+#define __otbLabelMapToLabelImageFilter_h
+
+#include "itkLabelMapToLabelImageFilter.h"
+
+namespace otb {
+
+/** \class LabelMapToLabelImageFilter
+ * \brief Converts a LabelMap to a labeled image.
+ *
+ * LabelMapToBinaryImageFilter to a label image.
+ *
+ * \author Gaetan Lehmann. Biologie du Developpement et de la Reproduction, INRA de Jouy-en-Josas, France.
+ *
+ * This implementation was taken from the Insight Journal paper:
+ * http://hdl.handle.net/1926/584  or 
+ * http://www.insight-journal.org/browse/publication/176
+ *
+ * \sa LabelMapToBinaryImageFilter, LabelMapMaskImageFilter
+ * \ingroup ImageEnhancement  MathematicalMorphologyImageFilters
+ * \ingroup LabeledImageFilters
+ */
+template<class TInputImage, class TOutputImage>
+class ITK_EXPORT LabelMapToLabelImageFilter : 
+    public itk::LabelMapToLabelImageFilter<TInputImage, TOutputImage>
+{
+public:
+  /** Standard class typedefs. */
+  typedef LabelMapToLabelImageFilter                Self;
+  typedef itk::LabelMapToLabelImageFilter<TInputImage, TOutputImage> Superclass;
+  typedef itk::SmartPointer<Self>                        Pointer;
+  typedef itk::SmartPointer<const Self>                  ConstPointer;
+
+  /** Some convenient typedefs. */
+  typedef TInputImage                              InputImageType;
+  typedef TOutputImage                             OutputImageType;
+  typedef typename InputImageType::Pointer         InputImagePointer;
+  typedef typename InputImageType::ConstPointer    InputImageConstPointer;
+  typedef typename InputImageType::RegionType      InputImageRegionType;
+  typedef typename InputImageType::PixelType       InputImagePixelType;
+  typedef typename InputImageType::LabelObjectType LabelObjectType;
+  
+  typedef typename OutputImageType::Pointer        OutputImagePointer;
+  typedef typename OutputImageType::ConstPointer   OutputImageConstPointer;
+  typedef typename OutputImageType::RegionType     OutputImageRegionType;
+  typedef typename OutputImageType::PixelType      OutputImagePixelType;
+  typedef typename OutputImageType::IndexType      IndexType;
+  
+  /** ImageDimension constants */
+  itkStaticConstMacro(InputImageDimension, unsigned int, TInputImage::ImageDimension);
+  itkStaticConstMacro(OutputImageDimension, unsigned int, TOutputImage::ImageDimension);
+
+  /** Standard New method. */
+  itkNewMacro(Self);  
+
+  /** Runtime information support. */
+  itkTypeMacro(LabelMapToLabelImageFilter, ImageToImageFilter);
+
+protected:
+  LabelMapToLabelImageFilter();
+  ~LabelMapToLabelImageFilter() {};
+
+  void GenerateInputRequestedRegion();
+
+  void EnlargeOutputRequestedRegion(itk::DataObject *){};
+
+private:
+  LabelMapToLabelImageFilter(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+
+}; // end of class
+
+} // end namespace otb
+  
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "otbLabelMapToLabelImageFilter.txx"
+#endif
+
+#endif
diff --git a/Code/OBIA/otbLabelMapToLabelImageFilter.txx b/Code/OBIA/otbLabelMapToLabelImageFilter.txx
new file mode 100644
index 0000000000..719438d048
--- /dev/null
+++ b/Code/OBIA/otbLabelMapToLabelImageFilter.txx
@@ -0,0 +1,69 @@
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkLabelMapToLabelImageFilter.txx,v $
+  Language:  C++
+  Date:      $Date: 2009-05-16 22:19:31 $
+  Version:   $Revision: 1.2 $
+
+  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 __otbLabelMapToLabelImageFilter_txx
+#define __otbLabelMapToLabelImageFilter_txx
+
+#include "otbLabelMapToLabelImageFilter.h"
+#include "itkNumericTraits.h"
+#include "itkProgressReporter.h"
+#include "itkImageRegionConstIteratorWithIndex.h"
+
+namespace otb {
+
+template <class TInputImage, class TOutputImage>
+LabelMapToLabelImageFilter<TInputImage, TOutputImage>
+::LabelMapToLabelImageFilter()
+{
+}
+
+template<class TInputImage, class TOutputImage>
+void
+LabelMapToLabelImageFilter<TInputImage, TOutputImage>
+::GenerateInputRequestedRegion()
+{
+
+
+  for (unsigned int idx = 0; idx < this->GetNumberOfInputs(); ++idx)
+      {
+       InputImagePointer input = const_cast<InputImageType *>(this->GetInput(idx));
+      if (!input.IsNull())
+        {
+        input->SetRequestedRegionToLargestPossibleRegion();
+        // Check whether the input is an image of the appropriate
+        // dimension (use ProcessObject's version of the GetInput()
+        // method since it returns the input as a pointer to a
+        // DataObject as opposed to the subclass version which
+        // static_casts the input to an TInputImage).
+
+        // Use the function object RegionCopier to copy the output region
+        // to the input.  The default region copier has default implementations
+        // to handle the cases where the input and output are the same
+        // dimension, the input a higher dimension than the output, and the
+        // input a lower dimension than the output.
+        InputImageRegionType inputRegion;
+        this->CallCopyOutputRegionToInputRegion(inputRegion, this->GetOutput()->GetRequestedRegion());
+        input->SetRequestedRegion( inputRegion );
+        }
+      }
+
+
+}
+
+
+
+}// end namespace otb
+#endif
diff --git a/Code/OBIA/otbShapeAttributesLabelMapFilter.h b/Code/OBIA/otbShapeAttributesLabelMapFilter.h
index 0e7c514283..ed4b358604 100644
--- a/Code/OBIA/otbShapeAttributesLabelMapFilter.h
+++ b/Code/OBIA/otbShapeAttributesLabelMapFilter.h
@@ -81,6 +81,13 @@ public:
   /** Get the compute perimeter flag */
   bool GetComputePerimeter() const;
 
+  /** Set the polygonalisation flag */
+  void SetComputePolygon(bool flag);
+
+  /** Get the polygonalisation flag */
+  bool GetComputePolygon() const;
+
+
   /** Set the compute feret diameter flag */
   void SetComputeFeretDiameter(bool flag);
 
@@ -130,9 +137,12 @@ private:
   /** Do we compute the feret diameter ? */
   bool m_ComputeFeretDiameter;
 
-  /** Du we compute the perimeter ? */
+  /** Do we compute the perimeter ? */
   bool m_ComputePerimeter;
 
+  /** Do we polygonise ? */
+  bool m_ComputePolygon;
+
   /** Compute only a reduced attribute set */
   bool m_ReducedAttributeSet;
 
@@ -181,6 +191,7 @@ public:
   /** Template parameters typedefs */
   typedef TImage                              ImageType;
   typedef typename ImageType::LabelObjectType LabelObjectType;
+  typedef typename ImageType::RegionType     InputImageRegionType;
   typedef TLabelImage                         LabelImageType;
   typedef Functor::ShapeAttributesLabelObjectFunctor
   <LabelObjectType, LabelImageType>                      FunctorType;
@@ -193,6 +204,7 @@ public:
   typedef itk::SmartPointer<Self>       Pointer;
   typedef itk::SmartPointer<const Self> ConstPointer;
 
+  typedef typename ImageType::Pointer         ImagePointer;
   /** ImageDimension constants */
   itkStaticConstMacro(ImageDimension, unsigned int, TImage::ImageDimension);
 
@@ -218,6 +230,14 @@ public:
   bool GetComputePerimeter() const;
   itkBooleanMacro(ComputePerimeter);
 
+  /**
+   * Set/Get whether the  polygonalisation process should be computed or not. The defaut value
+   * is true, to assure backward compatibility.
+   */
+  void SetComputePolygon(bool flag);
+  bool GetComputePolygon() const;
+  itkBooleanMacro(ComputePolygon);
+
   /** Set/get the ReducedAttributesSet flag */
   void SetReducedAttributeSet(bool flag);
   bool GetReducedAttributeSet() const;
@@ -241,6 +261,10 @@ protected:
   /** Things to to before threaded data generation */
   virtual void BeforeThreadedGenerateData();
 
+  void GenerateInputRequestedRegion();
+
+  void EnlargeOutputRequestedRegion(itk::DataObject *){};
+
 private:
   ShapeAttributesLabelMapFilter(const Self &); //purposely not implemented
   void operator =(const Self&); //purposely not implemented
diff --git a/Code/OBIA/otbShapeAttributesLabelMapFilter.txx b/Code/OBIA/otbShapeAttributesLabelMapFilter.txx
index b36acc9260..fc8615dc49 100644
--- a/Code/OBIA/otbShapeAttributesLabelMapFilter.txx
+++ b/Code/OBIA/otbShapeAttributesLabelMapFilter.txx
@@ -40,6 +40,7 @@ template <class TLabelObject, class TLabelImage>
 ShapeAttributesLabelObjectFunctor<TLabelObject, TLabelImage>
 ::ShapeAttributesLabelObjectFunctor() : m_ComputeFeretDiameter(false),
   m_ComputePerimeter(false),
+  m_ComputePolygon(true),
   m_ReducedAttributeSet(true),
   m_PerimeterCalculator(NULL),
   m_LabelImage(NULL)
@@ -92,6 +93,27 @@ ShapeAttributesLabelObjectFunctor<TLabelObject, TLabelImage>
   return m_ComputePerimeter;
 }
 
+/** Set the compute perimeter flag */
+template <class TLabelObject, class TLabelImage>
+void
+ShapeAttributesLabelObjectFunctor<TLabelObject, TLabelImage>
+::SetComputePolygon(bool flag)
+{
+  m_ComputePolygon = flag;
+}
+
+/** Get the compute perimeter flag */
+template <class TLabelObject, class TLabelImage>
+bool
+ShapeAttributesLabelObjectFunctor<TLabelObject, TLabelImage>
+::GetComputePolygon() const
+{
+  return m_ComputePolygon;
+}
+
+
+
+
 /** Set the compute feret diameter flag */
 template <class TLabelObject, class TLabelImage>
 void
@@ -499,13 +521,16 @@ ShapeAttributesLabelObjectFunctor<TLabelObject, TLabelImage>
     }
 
   // Set the attributes
-  PolygonFunctorType polygonFunctor;
-  SimplifyPolygonFunctorType simplifyFunctor;
-  polygonFunctor.SetStartIndex(m_LabelImage->GetLargestPossibleRegion().GetIndex());
-  polygonFunctor.SetOrigin(m_LabelImage->GetOrigin());
-  polygonFunctor.SetSpacing(m_LabelImage->GetSpacing());
-  typename PolygonType::Pointer polygon = simplifyFunctor(polygonFunctor(lo));
-  lo->SetPolygon(polygon);
+  if (m_ComputePolygon)
+    {
+    PolygonFunctorType polygonFunctor;
+    SimplifyPolygonFunctorType simplifyFunctor;
+    polygonFunctor.SetStartIndex(m_LabelImage->GetLargestPossibleRegion().GetIndex());
+    polygonFunctor.SetOrigin(m_LabelImage->GetOrigin());
+    polygonFunctor.SetSpacing(m_LabelImage->GetSpacing());
+    typename PolygonType::Pointer polygon = simplifyFunctor(polygonFunctor(lo));
+    lo->SetPolygon(polygon);
+    }
 
   // Physical size
   lo->SetAttribute("SHAPE::PhysicalSize", physicalSize);
@@ -747,6 +772,27 @@ ShapeAttributesLabelMapFilter<TImage, TLabelImage>
   return this->GetFunctor().GetComputePerimeter();
 }
 
+template<class TImage, class TLabelImage>
+void
+ShapeAttributesLabelMapFilter<TImage, TLabelImage>
+::SetComputePolygon(bool flag)
+{
+  if (this->GetFunctor().GetComputePolygon() != flag)
+    {
+    this->GetFunctor().SetComputePolygon(flag);
+    this->Modified();
+    }
+}
+
+template<class TImage, class TLabelImage>
+bool
+ShapeAttributesLabelMapFilter<TImage, TLabelImage>
+::GetComputePolygon() const
+{
+  return this->GetFunctor().GetComputePolygon();
+}
+
+
 template<class TImage, class TLabelImage>
 void
 ShapeAttributesLabelMapFilter<TImage, TLabelImage>
@@ -787,13 +833,45 @@ ShapeAttributesLabelMapFilter<TImage, TLabelImage>
   return this->GetFunctor().GetLabelImage();
 }
 
+template <class TImage, class TLabelImage>
+void
+ShapeAttributesLabelMapFilter<TImage, TLabelImage>
+::GenerateInputRequestedRegion()
+{
+
+  for (unsigned int idx = 0; idx < this->GetNumberOfInputs(); ++idx)
+      {
+       ImagePointer input = const_cast<ImageType *>(this->GetInput(idx));
+      if (!input.IsNull())
+        {
+        input->SetRequestedRegionToLargestPossibleRegion();
+        // Check whether the input is an image of the appropriate
+        // dimension (use ProcessObject's version of the GetInput()
+        // method since it returns the input as a pointer to a
+        // DataObject as opposed to the subclass version which
+        // static_casts the input to an TInputImage).
+
+        // Use the function object RegionCopier to copy the output region
+        // to the input.  The default region copier has default implementations
+        // to handle the cases where the input and output are the same
+        // dimension, the input a higher dimension than the output, and the
+        // input a lower dimension than the output.
+        InputImageRegionType inputRegion;
+        this->CallCopyOutputRegionToInputRegion(inputRegion, this->GetOutput()->GetRequestedRegion());
+        input->SetRequestedRegion( inputRegion );
+        }
+      }
+
+
+}
+
+
 template<class TImage, class TLabelImage>
 void
 ShapeAttributesLabelMapFilter<TImage, TLabelImage>
 ::BeforeThreadedGenerateData()
 {
   Superclass::BeforeThreadedGenerateData();
-
   if (!this->GetFunctor().GetLabelImage())
     {
     // generate an image of the labelized image
-- 
GitLab