From 96a664b06108918f2a154cb776b55dc32a6e3aea Mon Sep 17 00:00:00 2001
From: Julien Malik <julien.malik@c-s.fr>
Date: Thu, 15 Nov 2012 13:37:27 +0100
Subject: [PATCH] ENH: add class StreamingStatisticsMapFromLabelImageFilter

---
 ...reamingStatisticsMapFromLabelImageFilter.h | 256 ++++++++++++++++++
 ...amingStatisticsMapFromLabelImageFilter.txx | 208 ++++++++++++++
 2 files changed, 464 insertions(+)
 create mode 100644 Code/BasicFilters/otbStreamingStatisticsMapFromLabelImageFilter.h
 create mode 100644 Code/BasicFilters/otbStreamingStatisticsMapFromLabelImageFilter.txx

diff --git a/Code/BasicFilters/otbStreamingStatisticsMapFromLabelImageFilter.h b/Code/BasicFilters/otbStreamingStatisticsMapFromLabelImageFilter.h
new file mode 100644
index 0000000000..6a4bb4693f
--- /dev/null
+++ b/Code/BasicFilters/otbStreamingStatisticsMapFromLabelImageFilter.h
@@ -0,0 +1,256 @@
+/*=========================================================================
+
+  Program:   ORFEO Toolbox
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+
+  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+  See OTBCopyright.txt for details.
+
+Some parts of this code are derived from ITK. See ITKCopyright.txt
+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 __otbStreamingStatisticsMapFromLabelImageFilter_h
+#define __otbStreamingStatisticsMapFromLabelImageFilter_h
+
+#include "otbPersistentImageFilter.h"
+#include "itkNumericTraits.h"
+#include "itkArray.h"
+#include "itkSimpleDataObjectDecorator.h"
+#include "otbPersistentFilterStreamingDecorator.h"
+
+
+namespace otb
+{
+
+/** \class PersistentStreamingStatisticsMapFromLabelImageFilter
+ * \brief Computes mean radiometric value for each label of a label image, based on a support VectorImage
+ *
+ * This filter persists its temporary data. It means that if you Update it n times on n different
+ * requested regions, the output statistics will be the statitics of the whole set of n regions.
+ *
+ * To reset the temporary data, one should call the Reset() function.
+ *
+ * To get the statistics once the regions have been processed via the pipeline, use the Synthetize() method.
+ *
+ * \todo Implement other statistics (min, max, stddev...)
+ *
+ * \sa StreamingStatisticsMapFromLabelImageFilter
+ * \ingroup Streamed
+ * \ingroup Multithreaded
+ * \ingroup MathematicalStatisticsImageFilters
+ */
+template<class TInputVectorImage, class TLabelImage>
+class ITK_EXPORT PersistentStreamingStatisticsMapFromLabelImageFilter :
+  public PersistentImageFilter<TInputVectorImage, TInputVectorImage>
+{
+public:
+  /** Standard Self typedef */
+  typedef PersistentStreamingStatisticsMapFromLabelImageFilter               Self;
+  typedef PersistentImageFilter<TInputVectorImage, TInputVectorImage> Superclass;
+  typedef itk::SmartPointer<Self>                         Pointer;
+  typedef itk::SmartPointer<const Self>                   ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Runtime information support. */
+  itkTypeMacro(PersistentStreamingStatisticsMapFromLabelImageFilter, PersistentImageFilter);
+
+  /** Image related typedefs. */
+  typedef TInputVectorImage                   VectorImageType;
+  typedef typename TInputVectorImage::Pointer InputVectorImagePointer;
+  typedef TLabelImage                         LabelImageType;
+  typedef typename TLabelImage::Pointer       LabelImagePointer;
+
+  typedef typename VectorImageType::PixelType         VectorPixelType;
+  typedef typename LabelImageType::PixelType          LabelPixelType;
+  typedef std::map<LabelPixelType, VectorPixelType>   MeanValueMapType;
+  
+  itkStaticConstMacro(InputImageDimension, unsigned int,
+                      TInputVectorImage::ImageDimension);
+
+  /** Image related typedefs. */
+  itkStaticConstMacro(ImageDimension, unsigned int,
+                      TInputVectorImage::ImageDimension);
+
+  /** Smart Pointer type to a DataObject. */
+  typedef typename itk::DataObject::Pointer DataObjectPointer;
+
+  /** Type of DataObjects used for scalar outputs */
+  typedef itk::SimpleDataObjectDecorator<MeanValueMapType>  MeanValueMapObjectType;
+
+  /** Set input label image */
+  virtual void SetInputLabelImage( const LabelImageType *image);
+
+  /** Get input label image */
+  virtual const LabelImageType * GetInputLabelImage();
+  
+  /** Return the computed Mean for each label in the input label image */
+  MeanValueMapType GetMeanValueMap() const
+  {
+    return this->GetMeanValueMap()->Get();
+  }
+
+  /** Return the computed Mean for each label in the input label image */
+  MeanValueMapObjectType* GetMeanValueMap();
+
+  /** Return the computed Mean for each label in the input label image */
+  const MeanValueMapObjectType* GetMeanValueMap() const;
+
+  /** Make a DataObject of the correct type to be used as the specified
+   * output. */
+  virtual DataObjectPointer MakeOutput(unsigned int idx);
+
+  /** Pass the input through unmodified. Do this by Grafting in the
+   *  AllocateOutputs method.
+   */
+  void AllocateOutputs();
+
+  virtual void GenerateOutputInformation();
+
+  void Synthetize(void);
+
+  void Reset(void);
+
+protected:
+  PersistentStreamingStatisticsMapFromLabelImageFilter();
+  virtual ~PersistentStreamingStatisticsMapFromLabelImageFilter() {}
+  void PrintSelf(std::ostream& os, itk::Indent indent) const;
+
+  /** GenerateData. */
+  void  GenerateData();
+
+private:
+  PersistentStreamingStatisticsMapFromLabelImageFilter(const Self &); //purposely not implemented
+  void operator =(const Self&); //purposely not implemented
+  
+  MeanValueMapType                       m_RadiometricValueAccumulator;
+  std::map<LabelPixelType, unsigned int> m_LabelPopulation;
+}; // end of class PersistentStreamingStatisticsMapFromLabelImageFilter
+
+
+/*===========================================================================*/
+
+/** \class StreamingStatisticsMapFromLabelImageFilter
+ * \brief Computes mean radiometric value for each label of a label image, based on a support VectorImage
+ *
+ * Currently the class only computes the mean value.
+ *
+ * This class streams the whole input image through the PersistentStreamingStatisticsMapFromLabelImageFilter.
+ *
+ * This way, it allows to compute the first order global statistics of this image.
+ * It calls the Reset() method of the PersistentStatisticsImageFilter before streaming
+ * the image and the Synthetize() method of the PersistentStatisticsImageFilter
+ * after having streamed the image to compute the statistics.
+ * The accessor on the results are wrapping the accessors of the
+ * internal PersistentStatisticsImageFilter.
+ *
+ * This filter can be used as:
+ * \code
+ * typedef otb::StreamingStatisticsMapFromLabelImageFilter<ImageType> StatisticsType;
+ * StatisticsType::Pointer statistics = StatisticsType::New();
+ * statistics->SetInput(reader->GetOutput());
+ * statistics->Update();
+ * StatisticsType::MeanValueMapType meanValueMap = statistics->GetMeanValueMap();
+ * StatisticsType::MeanValueMapType::const_iterator end = meanValueMap();
+ * for (StatisticsType::MeanValueMapType::const_iterator it = meanValueMap.begin(); it != end; ++it)
+ * {
+ *       std::cout << "label : " << it->first << " , ";
+ *                 << "mean value : " << it->second << std::endl;
+ * }
+ * \endcode
+ *
+ * \todo Implement other statistics (min, max, stddev...)
+ * \todo Reimplement as a multi-threaded filter
+ *
+ * \sa PersistentStatisticsImageFilter
+ * \sa PersistentImageFilter
+ * \sa PersistentFilterStreamingDecorator
+ * \sa StreamingImageVirtualWriter
+ *
+ * \ingroup Streamed
+ * \ingroup Multithreaded
+ * \ingroup MathematicalStatisticsImageFilters
+ */
+
+template<class TInputVectorImage, class TLabelImage>
+class ITK_EXPORT StreamingStatisticsMapFromLabelImageFilter :
+  public PersistentFilterStreamingDecorator<PersistentStreamingStatisticsMapFromLabelImageFilter<TInputVectorImage, TLabelImage> >
+{
+public:
+  /** Standard Self typedef */
+  typedef StreamingStatisticsMapFromLabelImageFilter Self;
+  typedef PersistentFilterStreamingDecorator
+  <PersistentStreamingStatisticsMapFromLabelImageFilter<TInputVectorImage, TLabelImage> > Superclass;
+  typedef itk::SmartPointer<Self>       Pointer;
+  typedef itk::SmartPointer<const Self> ConstPointer;
+
+  /** Type macro */
+  itkNewMacro(Self);
+
+  /** Creation through object factory macro */
+  itkTypeMacro(StreamingStatisticsMapFromLabelImageFilter, PersistentFilterStreamingDecorator);
+
+  typedef TInputVectorImage                   VectorImageType;
+  typedef TLabelImage                         LabelImageType;
+  
+  typedef typename Superclass::FilterType::MeanValueMapType          MeanValueMapType;
+  typedef typename Superclass::FilterType::MeanValueMapObjectType    MeanValueMapObjectType;
+
+  /** Set input multispectral image */
+  void SetInput(const VectorImageType * input)
+  {
+    this->GetFilter()->SetInput(input);
+  }
+
+  /** Get input multispectral image */
+  const VectorImageType * GetInput()
+  {
+    return this->GetFilter()->GetInput();
+  }
+
+  /** Set input label image (monoband) */
+  void SetInputLabelImage(const LabelImageType * input)
+  {
+    this->GetFilter()->SetInputLabelImage(input);
+  }
+
+  /** Get input label image (monoband) */
+  const LabelImageType * GetInputLabelImage()
+  {
+    return this->GetFilter()->GetInputLabelImage();
+  }
+
+  /** Return the computed Mean for each label */
+  MeanValueMapType GetMeanValueMap() const
+  {
+    return this->GetFilter()->GetMeanValueMap();
+  }
+
+protected:
+  /** Constructor */
+  StreamingStatisticsMapFromLabelImageFilter() {}
+  /** Destructor */
+  virtual ~StreamingStatisticsMapFromLabelImageFilter() {}
+
+private:
+  StreamingStatisticsMapFromLabelImageFilter(const Self &); //purposely not implemented
+  void operator =(const Self&); //purposely not implemented
+};
+
+} // end namespace otb
+
+#ifndef OTB_MANUAL_INSTANTIATION
+#include "otbStreamingStatisticsMapFromLabelImageFilter.txx"
+#endif
+
+#endif
diff --git a/Code/BasicFilters/otbStreamingStatisticsMapFromLabelImageFilter.txx b/Code/BasicFilters/otbStreamingStatisticsMapFromLabelImageFilter.txx
new file mode 100644
index 0000000000..84ce6674d4
--- /dev/null
+++ b/Code/BasicFilters/otbStreamingStatisticsMapFromLabelImageFilter.txx
@@ -0,0 +1,208 @@
+/*=========================================================================
+
+  Program:   ORFEO Toolbox
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+
+  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+  See OTBCopyright.txt for details.
+
+Some parts of this code are derived from ITK. See ITKCopyright.txt
+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 __otbStreamingStatisticsMapFromLabelImageFilter_txx
+#define __otbStreamingStatisticsMapFromLabelImageFilter_txx
+#include "otbStreamingStatisticsMapFromLabelImageFilter.h"
+
+#include "itkImageRegionIterator.h"
+#include "itkImageRegionConstIterator.h"
+#include "itkNumericTraits.h"
+#include "itkProgressReporter.h"
+#include "otbMacro.h"
+
+
+namespace otb
+{
+
+template<class TInputVectorImage, class TLabelImage>
+PersistentStreamingStatisticsMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
+::PersistentStreamingStatisticsMapFromLabelImageFilter()
+{
+  // first output is a copy of the image, DataObject created by
+  // superclass
+  //
+  // allocate the data objects for the outputs which are
+  // just decorators around pixel types
+  typename MeanValueMapObjectType::Pointer output
+      = static_cast<MeanValueMapObjectType*>(this->MakeOutput(1).GetPointer());
+  this->itk::ProcessObject::SetNthOutput(1, output.GetPointer());
+
+  this->Reset();
+
+}
+
+template<class TInputVectorImage, class TLabelImage>
+typename itk::DataObject::Pointer
+PersistentStreamingStatisticsMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
+::MakeOutput(unsigned int output)
+{
+  switch (output)
+    {
+    case 0:
+      return static_cast<itk::DataObject*>(TInputVectorImage::New().GetPointer());
+      break;
+    case 1:
+      return static_cast<itk::DataObject*>(MeanValueMapObjectType::New().GetPointer());
+      break;
+    default:
+      // might as well make an image
+      return static_cast<itk::DataObject*>(TInputVectorImage::New().GetPointer());
+      break;
+    }
+}
+
+template<class TInputVectorImage, class TLabelImage>
+void
+PersistentStreamingStatisticsMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
+::SetInputLabelImage(const LabelImageType *input)
+{
+  // Process object is not const-correct so the const_cast is required here
+  this->itk::ProcessObject::SetNthInput(1,
+                                   const_cast< LabelImageType * >( input ) );
+
+}
+
+template<class TInputVectorImage, class TLabelImage>
+const typename PersistentStreamingStatisticsMapFromLabelImageFilter<TInputVectorImage, TLabelImage>::LabelImageType*
+PersistentStreamingStatisticsMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
+::GetInputLabelImage()
+{
+  return static_cast< const TLabelImage * >
+    (this->itk::ProcessObject::GetInput(1));
+}
+
+template<class TInputVectorImage, class TLabelImage>
+typename PersistentStreamingStatisticsMapFromLabelImageFilter<TInputVectorImage, TLabelImage>::MeanValueMapObjectType*
+PersistentStreamingStatisticsMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
+::GetMeanValueMap()
+{
+  return static_cast<MeanValueMapObjectType*>(this->itk::ProcessObject::GetOutput(1));
+}
+
+template<class TInputVectorImage, class TLabelImage>
+const typename PersistentStreamingStatisticsMapFromLabelImageFilter<TInputVectorImage, TLabelImage>::MeanValueMapObjectType*
+PersistentStreamingStatisticsMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
+::GetMeanValueMap() const
+{
+  return static_cast<const MeanValueMapObjectType*>(this->itk::ProcessObject::GetOutput(1));
+}
+
+template<class TInputVectorImage, class TLabelImage>
+void
+PersistentStreamingStatisticsMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
+::GenerateOutputInformation()
+{
+  Superclass::GenerateOutputInformation();
+  
+  if (this->GetInput())
+    {
+    this->GetOutput()->CopyInformation(this->GetInput());
+    this->GetOutput()->SetLargestPossibleRegion(this->GetInput()->GetLargestPossibleRegion());
+
+    if (this->GetOutput()->GetRequestedRegion().GetNumberOfPixels() == 0)
+      {
+      this->GetOutput()->SetRequestedRegion(this->GetOutput()->GetLargestPossibleRegion());
+      }
+    }
+}
+
+template<class TInputVectorImage, class TLabelImage>
+void
+PersistentStreamingStatisticsMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
+::AllocateOutputs()
+{
+  // This is commented to prevent the streaming of the whole image for the first stream strip
+  // It shall not cause any problem because the output image of this filter is not intended to be used.
+  //InputImagePointer image = const_cast< TInputImage * >( this->GetInput() );
+  //this->GraftOutput( image );
+  // Nothing that needs to be allocated for the remaining outputs
+}
+
+template<class TInputVectorImage, class TLabelImage>
+void
+PersistentStreamingStatisticsMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
+::Synthetize()
+{
+   typename MeanValueMapType::iterator it;
+   for(it = m_RadiometricValueAccumulator.begin(); it != m_RadiometricValueAccumulator.end(); it++)
+   {
+      it->second = it->second / m_LabelPopulation[it->first];
+   }
+   this->GetMeanValueMap()->Set(m_RadiometricValueAccumulator);
+}
+
+template<class TInputVectorImage, class TLabelImage>
+void
+PersistentStreamingStatisticsMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
+::Reset()
+{
+  m_RadiometricValueAccumulator.clear();
+}
+
+template<class TInputVectorImage, class TLabelImage>
+void
+PersistentStreamingStatisticsMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
+::GenerateData()
+{
+  /**
+   * Grab the input
+   */
+  InputVectorImagePointer inputPtr =  const_cast<TInputVectorImage *>(this->GetInput());
+  LabelImagePointer labelInputPtr =  const_cast<TLabelImage *>(this->GetInputLabelImage());
+  
+  itk::ImageRegionConstIterator<TInputVectorImage> inIt(inputPtr, inputPtr->GetRequestedRegion());
+  itk::ImageRegionConstIterator<TLabelImage> labelIt(labelInputPtr, labelInputPtr->GetRequestedRegion());
+  
+
+
+  typename VectorImageType::PixelType value;
+  typename LabelImageType::PixelType label;
+  // do the work
+  for (inIt.GoToBegin(), labelIt.GoToBegin();
+       !inIt.IsAtEnd() && !labelIt.IsAtEnd();
+       ++inIt, ++labelIt)
+    {
+      value = inIt.Get();
+      label = labelIt.Get();
+      if (m_RadiometricValueAccumulator.count(label)<=0) //add new element to the map
+      {
+        m_RadiometricValueAccumulator[label] = value;
+        m_LabelPopulation[label] = 1;
+      }
+      else
+      {
+        m_RadiometricValueAccumulator[label] += value;
+        m_LabelPopulation[label] ++;
+      }
+
+    }
+}
+
+template<class TInputVectorImage, class TLabelImage>
+void
+PersistentStreamingStatisticsMapFromLabelImageFilter<TInputVectorImage, TLabelImage>
+::PrintSelf(std::ostream& os, itk::Indent indent) const
+{
+  Superclass::PrintSelf(os, indent);
+}
+
+} // end namespace otb
+#endif
-- 
GitLab