From eda0b065d716c1d7cd2036fc3e9201bec340b4f7 Mon Sep 17 00:00:00 2001
From: Ludovic Hussonnois <ludovic.hussonnois@c-s.fr>
Date: Mon, 13 Feb 2017 10:38:53 +0100
Subject: [PATCH] ENH: Update Morphological applications According to RFC-81
 comments.

Change typedef to use otbWrapperTypes ones.
AddProcess for the applications.
Add progress Report for otbGeodesicMorphology* filters
Add documentation limits.
Remove unnecessary include and Update* call.
---
 .../app/otbMorphologicalClassification.cxx    | 25 ++++-----
 ...tbMorphologicalMultiScaleDecomposition.cxx | 26 +++------
 .../app/otbMorphologicalProfilesAnalysis.cxx  | 55 +++++++++----------
 ...odesicMorphologyDecompositionImageFilter.h |  2 +
 ...esicMorphologyDecompositionImageFilter.txx | 12 ++++
 ...phologyIterativeDecompositionImageFilter.h |  2 +
 ...ologyIterativeDecompositionImageFilter.txx |  8 +++
 7 files changed, 68 insertions(+), 62 deletions(-)

diff --git a/Modules/Applications/AppMorphology/app/otbMorphologicalClassification.cxx b/Modules/Applications/AppMorphology/app/otbMorphologicalClassification.cxx
index 96c8ded2ad..ea9035da67 100644
--- a/Modules/Applications/AppMorphology/app/otbMorphologicalClassification.cxx
+++ b/Modules/Applications/AppMorphology/app/otbMorphologicalClassification.cxx
@@ -16,8 +16,6 @@
 
 =========================================================================*/
 
-
-#include <geos_c.h>
 #include "otbGeodesicMorphologyDecompositionImageFilter.h"
 #include "otbWrapperApplication.h"
 #include "otbWrapperApplicationFactory.h"
@@ -50,15 +48,15 @@ public:
   typedef itk::SmartPointer<const Self> ConstPointer;
 
   typedef FloatVectorImageType::InternalPixelType InputPixelType;
-  typedef unsigned char OutputPixelType;
+  typedef otb::Image<InputPixelType, 2> FloatImageType;
 
-  typedef otb::Image<InputPixelType, 2> InputImageType;
-  typedef otb::Image<OutputPixelType, 2> OutputImageType;
+  typedef unsigned short LabeledPixelType;
+  typedef otb::Image<LabeledPixelType, 2> LabeledImageType;
 
   typedef otb::MultiToMonoChannelExtractROI<FloatVectorImageType::InternalPixelType, InputPixelType>
           ExtractorFilterType;
 
-  typedef otb::ConvexOrConcaveClassificationFilter<InputImageType, OutputImageType> ClassificationFilterType;
+  typedef otb::ConvexOrConcaveClassificationFilter<FloatImageType, LabeledImageType> ClassificationFilterType;
 
   typedef itk::BinaryBallStructuringElement<InputPixelType, 2> BallStructuringElementType;
   typedef itk::BinaryCrossStructuringElement<InputPixelType, 2> CrossStructuringElementType;
@@ -95,7 +93,7 @@ private:
                                    ":math:`f(n) = \\begin{cases} \\stackrel{\\smile}{k} &:& f-\\psi_{N}(f)>\\sigma \\\\ \\stackrel{\\frown}{k} &:& \\psi_{N}(f)-f>\\sigma\\\\ \\bar{k}&:&\\mid f - \\psi_{N}(f) \\mid \\leq \\sigma \\end{cases}`"
                                    "\n\n"
                                    "This output is a labeled image (0 : Flat, 1 : Convex, 2 : Concave)" );
-    SetDocLimitations( "None" );
+    SetDocLimitations( "Generation of the morphological classification is not streamable, pay attention to this fact when setting the radius size of the structuring element." );
     SetDocAuthors( "OTB-Team" );
     SetDocSeeAlso( "otbConvexOrConcaveClassificationFilter class" );
 
@@ -115,14 +113,12 @@ private:
 
     AddRAMParameter();
 
-    // Strucring Element (Ball | Cross)
+    // Structuring Element (Ball | Cross)
     AddParameter( ParameterType_Choice, "structype", "Structuring Element Type" );
     SetParameterDescription( "structype", "Choice of the structuring element type" );
     AddChoice( "structype.ball", "Ball" );
     AddChoice( "structype.cross", "Cross" );
 
-
-
     AddParameter( ParameterType_Int, "radius", "Radius" );
     SetParameterDescription( "radius", "Radius of the structuring element (in pixels)" );
     SetDefaultParameterInt( "radius", 5 );
@@ -150,7 +146,7 @@ private:
   void DoExecute() ITK_OVERRIDE
   {
     FloatVectorImageType::Pointer inImage = GetParameterImage( "in" );
-    inImage->UpdateOutputInformation();
+
     int nBComp = inImage->GetNumberOfComponentsPerPixel();
     int selectedChannel = GetParameterInt( "channel" );
 
@@ -166,7 +162,6 @@ private:
     m_ExtractorFilter->SetSizeX( inImage->GetLargestPossibleRegion().GetSize( 0 ) );
     m_ExtractorFilter->SetSizeY( inImage->GetLargestPossibleRegion().GetSize( 1 ) );
     m_ExtractorFilter->SetChannel( static_cast<unsigned int>(selectedChannel) );
-    m_ExtractorFilter->UpdateOutputInformation();
 
     unsigned int sigma = static_cast<unsigned int>(GetParameterInt( "sigma" ));
     unsigned int radius = static_cast<unsigned int>(GetParameterInt( "radius" ));
@@ -178,7 +173,6 @@ private:
     m_ClassificationFilter->SetConvexLabel( 1 );
     m_ClassificationFilter->SetConcaveLabel( 2 );
 
-
     if ( GetParameterString( "structype" ) == "ball" )
       {
       performClassification<BallStructuringElementType>( radius );
@@ -187,13 +181,14 @@ private:
       performClassification<CrossStructuringElementType>( radius );
       }
 
+    SetParameterOutputImage( "out", m_ClassificationFilter->GetOutput() );
 
   }
 
   template<typename TStructuringElement>
   void performClassification(unsigned int radius_size) {
 
-    typedef otb::GeodesicMorphologyDecompositionImageFilter<InputImageType, InputImageType, TStructuringElement> TDecompositionImageFilter;
+    typedef otb::GeodesicMorphologyDecompositionImageFilter<FloatImageType, FloatImageType, TStructuringElement> TDecompositionImageFilter;
 
     typename TDecompositionImageFilter::Pointer decompositionImageFilter;
     decompositionImageFilter = TDecompositionImageFilter::New();
@@ -202,10 +197,10 @@ private:
     typename TStructuringElement::RadiusType radius;
     radius.Fill( radius_size );
     decompositionImageFilter->SetRadius( radius );
+    AddProcess(decompositionImageFilter, "Image Decomposition");
     decompositionImageFilter->Update();
 
     m_ClassificationFilter->SetInputLeveling( decompositionImageFilter->GetOutput() );
-    SetParameterOutputImage( "out", m_ClassificationFilter->GetOutput() );
   }
 
   ExtractorFilterType::Pointer m_ExtractorFilter;
diff --git a/Modules/Applications/AppMorphology/app/otbMorphologicalMultiScaleDecomposition.cxx b/Modules/Applications/AppMorphology/app/otbMorphologicalMultiScaleDecomposition.cxx
index 9a9946a4cf..592a2fd056 100644
--- a/Modules/Applications/AppMorphology/app/otbMorphologicalMultiScaleDecomposition.cxx
+++ b/Modules/Applications/AppMorphology/app/otbMorphologicalMultiScaleDecomposition.cxx
@@ -16,9 +16,7 @@
 
 =========================================================================*/
 
-
-#include <geos_c.h>
-#include <itkComposeImageFilter.h>
+#include "itkComposeImageFilter.h"
 #include "otbWrapperApplication.h"
 #include "otbWrapperApplicationFactory.h"
 
@@ -50,17 +48,13 @@ public:
   typedef itk::SmartPointer<Self> Pointer;
   typedef itk::SmartPointer<const Self> ConstPointer;
 
-  typedef FloatVectorImageType::InternalPixelType InputPixelType;
-  typedef float OutputPixelType;
-
-  typedef otb::Image<InputPixelType, 2> InputImageType;
-  typedef otb::VectorImage<OutputPixelType, 2> TOutputVectorImage;
+  typedef FloatVectorImageType::InternalPixelType InputVectorPixelType;
 
-  typedef otb::MultiToMonoChannelExtractROI<FloatVectorImageType::InternalPixelType, InputPixelType>
+  typedef otb::MultiToMonoChannelExtractROI<FloatVectorImageType::InternalPixelType, InputVectorPixelType>
           ExtractorFilterType;
 
-  typedef itk::BinaryBallStructuringElement<InputPixelType, 2> BallStructuringElementType;
-  typedef itk::BinaryCrossStructuringElement<InputPixelType, 2> CrossStructuringElementType;
+  typedef itk::BinaryBallStructuringElement<InputVectorPixelType, 2> BallStructuringElementType;
+  typedef itk::BinaryCrossStructuringElement<InputVectorPixelType, 2> CrossStructuringElementType;
 
 /** Standard macro */
   itkNewMacro( Self );
@@ -101,7 +95,7 @@ private:
                     "\n"
                     "Output convex, concave and leveling images with N bands, where N is the number of levels." );
 
-    SetDocLimitations( "None" );
+    SetDocLimitations( "Generation of the multi scale decomposition is not streamable, pay attention to this fact when setting the number of iterating levels." );
     SetDocAuthors( "OTB-Team" );
     SetDocSeeAlso( "otbGeodesicMorphologyDecompositionImageFilter class" );
 
@@ -166,7 +160,6 @@ private:
   void DoExecute() ITK_OVERRIDE
   {
     FloatVectorImageType::Pointer inImage = GetParameterImage( "in" );
-    inImage->UpdateOutputInformation();
     int nBComp = inImage->GetNumberOfComponentsPerPixel();
     int selectedChannel = GetParameterInt( "channel" );
 
@@ -182,8 +175,6 @@ private:
     m_ExtractorFilter->SetSizeX( inImage->GetLargestPossibleRegion().GetSize( 0 ) );
     m_ExtractorFilter->SetSizeY( inImage->GetLargestPossibleRegion().GetSize( 1 ) );
     m_ExtractorFilter->SetChannel( static_cast<unsigned int>(GetParameterInt( "channel" )) );
-    m_ExtractorFilter->UpdateOutputInformation();
-
 
     unsigned int numberOfLevels = static_cast<unsigned int>(GetParameterInt( "levels" ));
     unsigned int initValue = static_cast<unsigned int>(GetParameterInt( "radius" ));
@@ -202,9 +193,9 @@ private:
   template<typename StructuringElement>
   void performDecomposition(unsigned int numberOfLevels, unsigned int step, unsigned int initValue) {
 
-    typedef otb::GeodesicMorphologyIterativeDecompositionImageFilter<InputImageType, StructuringElement> TDecompositionImageFilter;
+    typedef otb::GeodesicMorphologyIterativeDecompositionImageFilter<FloatImageType, StructuringElement> TDecompositionImageFilter;
     typedef typename TDecompositionImageFilter::OutputImageListType TImageList;
-    typedef otb::ImageListToVectorImageFilter<TImageList, TOutputVectorImage> TListToVectorImageFilter;
+    typedef otb::ImageListToVectorImageFilter<TImageList, FloatVectorImageType> TListToVectorImageFilter;
 
     typename TDecompositionImageFilter::Pointer decompositionImageFilter;
     decompositionImageFilter = TDecompositionImageFilter::New();
@@ -212,6 +203,7 @@ private:
     decompositionImageFilter->SetNumberOfIterations( numberOfLevels );
     decompositionImageFilter->SetInitialValue( initValue );
     decompositionImageFilter->SetStep( step );
+    AddProcess(decompositionImageFilter, "Image Decomposition");
     decompositionImageFilter->Update();
 
     typename TListToVectorImageFilter::Pointer levelingListToVectorImageFilter = TListToVectorImageFilter::New();
diff --git a/Modules/Applications/AppMorphology/app/otbMorphologicalProfilesAnalysis.cxx b/Modules/Applications/AppMorphology/app/otbMorphologicalProfilesAnalysis.cxx
index ee124caef0..432053c3b5 100644
--- a/Modules/Applications/AppMorphology/app/otbMorphologicalProfilesAnalysis.cxx
+++ b/Modules/Applications/AppMorphology/app/otbMorphologicalProfilesAnalysis.cxx
@@ -17,7 +17,6 @@
 =========================================================================*/
 
 
-#include <geos_c.h>
 #include <itkComposeImageFilter.h>
 #include "otbWrapperApplication.h"
 #include "otbWrapperApplicationFactory.h"
@@ -39,10 +38,13 @@
 #include "otbMorphologicalProfilesSegmentationFilter.h"
 #include "otbGeodesicMorphologyIterativeDecompositionImageFilter.h"
 
-namespace otb {
-namespace Wrapper {
+namespace otb
+{
+namespace Wrapper
+{
 
-class MorphologicalProfilesAnalysis : public Application {
+class MorphologicalProfilesAnalysis : public Application
+{
 public:
 /** Standard class typedefs. */
   typedef MorphologicalProfilesAnalysis Self;
@@ -51,16 +53,11 @@ public:
   typedef itk::SmartPointer<const Self> ConstPointer;
 
   typedef FloatVectorImageType::InternalPixelType InputPixelType;
-  typedef float OutputPixelType;
-  typedef unsigned short LabeledPixelType;
 
-  typedef otb::Image<InputPixelType, 2> InputImageType;
-  typedef otb::Image<OutputPixelType, 2> OutputImageType;
+  typedef unsigned short LabeledPixelType;
   typedef otb::Image<LabeledPixelType, 2> LabeledImageType;
-  typedef otb::VectorImage<OutputPixelType, 2> TOutputVectorImage;
 
-  typedef otb::MultiToMonoChannelExtractROI<FloatVectorImageType::InternalPixelType, InputPixelType>
-          ExtractorFilterType;
+  typedef otb::MultiToMonoChannelExtractROI<InputPixelType, InputPixelType> ExtractorFilterType;
 
   typedef itk::BinaryBallStructuringElement<InputPixelType, 2> BallStructuringElementType;
   typedef itk::BinaryCrossStructuringElement<InputPixelType, 2> CrossStructuringElementType;
@@ -104,7 +101,7 @@ private:
                                    "- A :math:`N` multi band image for the opening/closing normal or derivative profiles.\n"
                                    "- A mono band image for the opening/closing characteristics.\n"
                                    "- A labeled image for the classification\n" );
-    SetDocLimitations( "None" );
+    SetDocLimitations( "Generation of the morphological profile is not streamable, pay attention to this fact when setting the radius initial size and step of the structuring element." );
     SetDocAuthors( "OTB-Team" );
     SetDocSeeAlso( "otbMorphologicalOpeningProfileFilter, otbMorphologicalClosingProfileFilter, otbProfileToProfileDerivativeFilter, otbProfileDerivativeToMultiScaleCharacteristicsFilter, otbMultiScaleConvexOrConcaveClassificationFilter, classes" );
 
@@ -123,7 +120,7 @@ private:
 
     AddRAMParameter();
 
-    // Strucring Element (Ball | Cross)
+    // Structuring Element (Ball | Cross)
     AddParameter( ParameterType_Choice, "structype", "Structuring Element Type" );
     SetParameterDescription( "structype", "Choice of the structuring element type" );
     AddChoice( "structype.ball", "Ball" );
@@ -179,18 +176,16 @@ private:
   void DoExecute() ITK_OVERRIDE
   {
 
-
     FloatVectorImageType::Pointer inImage = GetParameterImage( "in" );
-    inImage->UpdateOutputInformation();
+
     int nBComp = inImage->GetNumberOfComponentsPerPixel();
     int selectedChannel = GetParameterInt( "channel" );
 
-    if ( selectedChannel > nBComp )
+    if( selectedChannel > nBComp )
       {
       itkExceptionMacro( << "The specified channel index for input image is invalid." );
       }
 
-
     m_ExtractorFilter = ExtractorFilterType::New();
     m_ExtractorFilter->SetInput( inImage );
     m_ExtractorFilter->SetStartX( static_cast<unsigned int>(inImage->GetLargestPossibleRegion().GetIndex( 0 )) );
@@ -198,7 +193,6 @@ private:
     m_ExtractorFilter->SetSizeX( inImage->GetLargestPossibleRegion().GetSize( 0 ) );
     m_ExtractorFilter->SetSizeY( inImage->GetLargestPossibleRegion().GetSize( 1 ) );
     m_ExtractorFilter->SetChannel( static_cast<unsigned int>(GetParameterInt( "channel" )) );
-    m_ExtractorFilter->UpdateOutputInformation();
 
     unsigned int profileSize = static_cast<unsigned int>(GetParameterInt( "size" ));
     unsigned short initValue = static_cast<unsigned short>(GetParameterInt( "radius" ));
@@ -210,7 +204,8 @@ private:
     if ( GetParameterString( "structype" ) == "ball" )
       {
       performProfileAnalysis<BallStructuringElementType>( profile, profileSize, initValue, step, sigma );
-      } else // Cross
+      }
+    else // Cross
       {
       performProfileAnalysis<CrossStructuringElementType>( profile, profileSize, initValue, step, sigma );
       }
@@ -221,16 +216,12 @@ private:
   performProfileAnalysis(std::string profile, unsigned int profileSize, unsigned short initValue,
                          unsigned short step, float sigma) {
 
-    typedef otb::MorphologicalOpeningProfileFilter<InputImageType, InputImageType, StructuringElementType>
-            OpeningProfileFilterType;
-    typedef otb::MorphologicalClosingProfileFilter<InputImageType, InputImageType, StructuringElementType>
-            ClosingProfileFilterType;
-    typedef otb::ProfileToProfileDerivativeFilter<InputImageType, InputImageType> DerivativeFilterType;
+    typedef otb::MorphologicalOpeningProfileFilter<FloatImageType, FloatImageType, StructuringElementType> OpeningProfileFilterType;
+    typedef otb::MorphologicalClosingProfileFilter<FloatImageType, FloatImageType, StructuringElementType> ClosingProfileFilterType;
+    typedef otb::ProfileToProfileDerivativeFilter<FloatImageType, FloatImageType> DerivativeFilterType;
 
-    typedef otb::MultiScaleConvexOrConcaveClassificationFilter<InputImageType, LabeledImageType>
-            MultiScaleClassificationFilterType;
-    typedef otb::ProfileDerivativeToMultiScaleCharacteristicsFilter<InputImageType, OutputImageType, LabeledImageType>
-            MultiScaleCharacteristicsFilterType;
+    typedef otb::MultiScaleConvexOrConcaveClassificationFilter<FloatImageType, LabeledImageType> MultiScaleClassificationFilterType;
+    typedef otb::ProfileDerivativeToMultiScaleCharacteristicsFilter<FloatImageType, FloatImageType, LabeledImageType> MultiScaleCharacteristicsFilterType;
 
     // Instantiation
     typename OpeningProfileFilterType::Pointer oprofileFilter;
@@ -279,6 +270,7 @@ private:
     classificationFilter->SetClosingProfileCharacteristics( cmsCharFilter->GetOutputCharacteristics() );
     classificationFilter->SetSigma( sigma );
     classificationFilter->SetLabelSeparator( static_cast<unsigned short>(initValue + profileSize * step) );
+    AddProcess(classificationFilter, "Classification");
     classificationFilter->Update();
     SetParameterOutputImage( "out", classificationFilter->GetOutput() );
   }
@@ -292,8 +284,8 @@ private:
                     bool profile, bool derivative, bool characteristics,
                     unsigned int profileSize, unsigned short initValue, unsigned short step) {
 
-    typedef ImageList<InputImageType> TImageList;
-    typedef otb::ImageListToVectorImageFilter<TImageList, TOutputVectorImage> TListToVectorImageFilter;
+    typedef ImageList<FloatImageType> TImageList;
+    typedef otb::ImageListToVectorImageFilter<TImageList, FloatVectorImageType> TListToVectorImageFilter;
 
     profileFilter = TProfileFilter::New();
     profileFilter->SetInput( m_ExtractorFilter->GetOutput() );
@@ -305,6 +297,7 @@ private:
       {
       TListToVectorImageFilter::Pointer listToVectorImageFilter = TListToVectorImageFilter::New();
       listToVectorImageFilter->SetInput( profileFilter->GetOutput() );
+      AddProcess(listToVectorImageFilter, "Profile");
       listToVectorImageFilter->Update();
       SetParameterOutputImage( "out", listToVectorImageFilter->GetOutput() );
       return;
@@ -317,6 +310,7 @@ private:
       {
       TListToVectorImageFilter::Pointer listToVectorImageFilter = TListToVectorImageFilter::New();
       listToVectorImageFilter->SetInput( derivativeFilter->GetOutput() );
+      AddProcess(listToVectorImageFilter, "Derivative");
       listToVectorImageFilter->Update();
       SetParameterOutputImage( "out", listToVectorImageFilter->GetOutput() );
       return;
@@ -329,6 +323,7 @@ private:
 
     if ( characteristics )
       {
+      AddProcess(msCharFilter, "Characteristics");
       msCharFilter->Update();
       SetParameterOutputImage( "out", msCharFilter->GetOutputCharacteristics() );
       }
diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.h b/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.h
index bc8a2915b3..b8f6c1c996 100644
--- a/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.h
+++ b/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.h
@@ -174,6 +174,8 @@ private:
   bool m_PreserveIntensities;
   /** Use fully connected morphological operators */
   bool m_FullyConnected;
+  /** Progress accumulator to report internal filter progress */
+  itk::ProgressAccumulator::Pointer m_Progress;
 
 };
 } // End namespace otb
diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.txx b/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.txx
index bb910c8192..adec859e7b 100644
--- a/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.txx
+++ b/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.txx
@@ -36,12 +36,24 @@ GeodesicMorphologyDecompositionImageFilter<TInputImage, TOutputImage, TStructuri
 
   m_Radius.Fill(1);
 
+  // Create a process accumulator for tracking the progress of minipipeline
+  m_Progress = itk::ProgressAccumulator::New();
+  m_Progress->SetMiniPipelineFilter(this);
+
   m_OpeningFilter  = OpeningFilterType::New();
   m_ClosingFilter  = ClosingFilterType::New();
   m_LevelingFilter = LevelingFilterType::New();
   m_ConvexFilter   = ConvexFilterType::New();
   m_ConcaveFilter  = ConcaveFilterType::New();
 
+  // Register Internal Filter for progress
+  m_Progress->RegisterInternalFilter(m_OpeningFilter, 0.2);
+  m_Progress->RegisterInternalFilter(m_ClosingFilter, 0.2);
+  m_Progress->RegisterInternalFilter(m_LevelingFilter, 0.2);
+  m_Progress->RegisterInternalFilter(m_ConvexFilter, 0.2);
+  m_Progress->RegisterInternalFilter(m_ConcaveFilter, 0.2);
+
+
   m_FullyConnected = true;
   m_PreserveIntensities = true;
 }
diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyIterativeDecompositionImageFilter.h b/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyIterativeDecompositionImageFilter.h
index e37c89b1a7..a15b08f2fe 100644
--- a/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyIterativeDecompositionImageFilter.h
+++ b/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyIterativeDecompositionImageFilter.h
@@ -146,6 +146,8 @@ private:
   unsigned int m_InitialValue;
   /** The number of iterations */
   unsigned int m_NumberOfIterations;
+  /** Progress accumulator to report internal filter progress */
+  itk::ProgressAccumulator::Pointer m_Progress;
 
 };
 } // End namespace otb
diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyIterativeDecompositionImageFilter.txx b/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyIterativeDecompositionImageFilter.txx
index 650a9b917a..06da40f579 100644
--- a/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyIterativeDecompositionImageFilter.txx
+++ b/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyIterativeDecompositionImageFilter.txx
@@ -32,6 +32,10 @@ template <class TImage, class TStructuringElement>
 GeodesicMorphologyIterativeDecompositionImageFilter<TImage, TStructuringElement>
 ::GeodesicMorphologyIterativeDecompositionImageFilter()
 {
+  // Create a process accumulator for tracking the progress of minipipeline
+  m_Progress = itk::ProgressAccumulator::New();
+  m_Progress->SetMiniPipelineFilter(this);
+
   this->SetNumberOfRequiredInputs(1);
   this->SetNumberOfRequiredOutputs(3);
   m_NumberOfIterations  = 2;
@@ -185,6 +189,10 @@ GeodesicMorphologyIterativeDecompositionImageFilter<TImage, TStructuringElement>
   while (i < m_NumberOfIterations)
     {
     filter = DecompositionFilterType::New();
+
+    // Register Internal Filter for progress
+    m_Progress->RegisterInternalFilter(filter, 1./m_NumberOfIterations);
+
     typename StructuringElementType::RadiusType radius;
     radius.Fill(m_InitialValue + i * m_Step);
     filter->SetRadius(radius);
-- 
GitLab