diff --git a/Documentation/SoftwareGuide/Latex/Installation.tex b/Documentation/SoftwareGuide/Latex/Installation.tex
index 8ccfa9df9a6088ba295fd4b910c173a3af70f16c..b4ad2a3145da54529041519df2f1632c8fe07d50 100644
--- a/Documentation/SoftwareGuide/Latex/Installation.tex
+++ b/Documentation/SoftwareGuide/Latex/Installation.tex
@@ -86,7 +86,7 @@ See table \ref{tab:otb-dependencies} for the full list of dependencies.
 \hline
 \textbf{ITK} & \url{http://www.itk.org} & yes & 4.6.0 \\
 \hline
-\textbf{GDAL} & \url{http://www.gdal.org} & yes & 1.10 (2.x also supported) \\
+\textbf{GDAL} & \url{http://www.gdal.org} & yes & 2.0 \\
 \hline
 \textbf{OSSIM} & \url{http://www.ossim.org} & yes & 1.8.20-3 \\
 \hline
diff --git a/Examples/Filtering/GeometriesChangeSpatialReference.cxx b/Examples/Filtering/GeometriesChangeSpatialReference.cxx
index 082f426cf796a0be81df428fcff46d70a44a8aa9..e57e8c866d5cf82591d1152fa7b1d23baa611142 100644
--- a/Examples/Filtering/GeometriesChangeSpatialReference.cxx
+++ b/Examples/Filtering/GeometriesChangeSpatialReference.cxx
@@ -209,10 +209,10 @@ int main (int argc, char **argv)
       = options.workingInplace ? input
       : options.outputIsStdout ? nullptr
       : otb::ogr::DataSource::New( options.outputFile, otb::ogr::DataSource::Modes::Update_LayerCreateOnly);
-    std::cout << "input: " << otb::ogr::version_proxy::GetFileListAsStringVector(&input->ogr())[0] << " should be: " << options.inputFile << "\n";
+    std::cout << "input: " << otb::ogr::GetFileListAsStringVector(&input->ogr())[0] << " should be: " << options.inputFile << "\n";
     if (output)
       {
-      std::cout << "output: " << otb::ogr::version_proxy::GetFileListAsStringVector(&output->ogr())[0] << " should be: " << options.outputFile << "\n";
+      std::cout << "output: " << otb::ogr::GetFileListAsStringVector(&output->ogr())[0] << " should be: " << options.outputFile << "\n";
       }
     // std::cout << "\n";
 
diff --git a/Examples/Filtering/GeometriesFilter.cxx b/Examples/Filtering/GeometriesFilter.cxx
index 922d05e5eccf83481f797b94e89cc9569765f660..bd59d09dfeb04fa9834d8b04d1411d4607af31dc 100644
--- a/Examples/Filtering/GeometriesFilter.cxx
+++ b/Examples/Filtering/GeometriesFilter.cxx
@@ -76,10 +76,10 @@ int main (int argc, char **argv)
       = workingInplace ? input
       : outputIsStdout ? nullptr
       :                  otb::ogr::DataSource::New( outputFile, otb::ogr::DataSource::Modes::Update_LayerCreateOnly);
-    std::cout << "input: " << otb::ogr::version_proxy::GetFileListAsStringVector(&input->ogr())[0] << " should be: " << inputFile << "\n";
+    std::cout << "input: " << otb::ogr::GetFileListAsStringVector(&input->ogr())[0] << " should be: " << inputFile << "\n";
     if (output)
       {
-      std::cout << "output: " << otb::ogr::version_proxy::GetFileListAsStringVector(&output->ogr())[0] << " should be: " << outputFile << "\n";
+      std::cout << "output: " << otb::ogr::GetFileListAsStringVector(&output->ogr())[0] << " should be: " << outputFile << "\n";
       }
     // std::cout << "\n";
 
diff --git a/Modules/Adapters/GdalAdapters/include/otbOGRDataSourceWrapper.h b/Modules/Adapters/GdalAdapters/include/otbOGRDataSourceWrapper.h
index f75d86e7847099a0c757f3e0b239f48fa47ad51b..f3a149a974367e652a821ada687d731096bca4cb 100644
--- a/Modules/Adapters/GdalAdapters/include/otbOGRDataSourceWrapper.h
+++ b/Modules/Adapters/GdalAdapters/include/otbOGRDataSourceWrapper.h
@@ -45,7 +45,6 @@
 #include "itkObjectFactory.h" // that should have been included by itkMacro.h
 
 #include "otbOGRLayerWrapper.h"
-#include "otbOGRVersionProxy.h"
 #include "otbOGRExtendedFilenameToOptions.h"
 
 class OGRLayer;
@@ -164,7 +163,7 @@ public:
    * \note No condition is assumed on the non-nullity of \c source.
    * \see \c DataSource(GDALDataset *)
    */
-  static Pointer New(ogr::version_proxy::GDALDatasetType * sourcemode, Modes::type mode = Modes::Read , const std::vector< std::string > & layerOptions = std::vector< std::string >() );
+  static Pointer New(GDALDataset * sourcemode, Modes::type mode = Modes::Read , const std::vector< std::string > & layerOptions = std::vector< std::string >() );
   //@}
 
   /**\name Projection Reference property */
@@ -301,7 +300,7 @@ public:
    * \throw None
    * \post Assumes ownership of the \c source.
    */
-  void Reset(ogr::version_proxy::GDALDatasetType * source);
+  void Reset(GDALDataset * source);
 
   /**\name Layers modification */
   //@{
@@ -477,8 +476,6 @@ public:
     }
 
   /** Flushes all changes to disk.
-   * \throw itd::ExceptionObject in case the flush operation failed.
-   * \sa \c GDALDataset::SyncToDisk()
    */
   void SyncToDisk();
 
@@ -497,7 +494,7 @@ public:
    * \warning You must under no circumstance try to delete the \c GDALDataset
    * obtained this way.
    */
-    ogr::version_proxy::GDALDatasetType & ogr();
+    GDALDataset & ogr();
 
     void SetLayerCreationOptions( const std::vector< std::string > & options );
     void AddLayerCreationOptions( std::vector< std::string > options );
@@ -517,7 +514,7 @@ protected:
   /** Init constructor.
    * \post The newly constructed object owns the \c source parameter.
    */
-  DataSource(ogr::version_proxy::GDALDatasetType * source, Modes::type mode , const std::vector< std::string > & layerOption = std::vector< std::string >() );
+  DataSource(GDALDataset * source, Modes::type mode , const std::vector< std::string > & layerOption = std::vector< std::string >() );
   /** Destructor.
    * \post The \c GDALDataset owned is released (if not null).
    */
@@ -554,7 +551,7 @@ private:
   std::string GetDatasetDescription() const;
 
 private:
-  ogr::version_proxy::GDALDatasetType *m_DataSource;
+  GDALDataset *m_DataSource;
   std::vector< std::string > m_LayerOptions;
   Modes::type    m_OpenMode;
   int            m_FirstModifiableLayerID;
diff --git a/Modules/Adapters/GdalAdapters/include/otbOGRDataSourceWrapper.hxx b/Modules/Adapters/GdalAdapters/include/otbOGRDataSourceWrapper.hxx
index e2990958c6d871df3e433ca66732cd5e77c0b760..acfea3a977c90c7c4738f1716e7a7c4be5cd37ef 100644
--- a/Modules/Adapters/GdalAdapters/include/otbOGRDataSourceWrapper.hxx
+++ b/Modules/Adapters/GdalAdapters/include/otbOGRDataSourceWrapper.hxx
@@ -43,7 +43,7 @@
 // to the compilation mode of the client code.
 
 inline
-otb::ogr::version_proxy::GDALDatasetType & otb::ogr::DataSource::ogr()
+GDALDataset & otb::ogr::DataSource::ogr()
 {
   assert(m_DataSource && "GDALDataset not initialized");
   return *m_DataSource;
diff --git a/Modules/Adapters/GdalAdapters/include/otbOGRFieldWrapper.hxx b/Modules/Adapters/GdalAdapters/include/otbOGRFieldWrapper.hxx
index 258db5172ef7632fa454444bababb233abae9129..2ac3137985b80832f7db3ba60b7d0f1d68d059af 100644
--- a/Modules/Adapters/GdalAdapters/include/otbOGRFieldWrapper.hxx
+++ b/Modules/Adapters/GdalAdapters/include/otbOGRFieldWrapper.hxx
@@ -97,10 +97,9 @@ typedef mpl::map
   , mpl::pair<char*                   , mpl::int_<OFTString> >
   , mpl::pair<char const*             , mpl::int_<OFTString> >
   , mpl::pair<std::vector<std::string>, mpl::int_<OFTStringList> >
-  #ifdef OTB_USE_GDAL_20
-    , mpl::pair<GIntBig, mpl::int_<OFTInteger64> >
-    , mpl::pair<std::vector<GIntBig>, mpl::int_<OFTInteger64List> >
-  #endif
+  , mpl::pair<GIntBig, mpl::int_<OFTInteger64> >
+  , mpl::pair<std::vector<GIntBig>, mpl::int_<OFTInteger64List> >
+
   // OFTBinary
   // OFTDate
   // OFTTime
@@ -341,10 +340,8 @@ typedef mpl::map
   , mpl::pair<mpl::int_<OFTRealList>,    MemberContainerGetterPtr<double, &OGRFeature::GetFieldAsDoubleList> >
   , mpl::pair<mpl::int_<OFTString>,      MemberGetterPtr<char const*,     &OGRFeature::GetFieldAsString, std::string> >
   , mpl::pair<mpl::int_<OFTStringList>,  StringListMemberGetterPtr<std::vector<std::string> > >
-  #ifdef OTB_USE_GDAL_20
   , mpl::pair<mpl::int_<OFTInteger64>, MemberGetterPtr<GIntBig, &OGRFeature::GetFieldAsInteger64> >
   , mpl::pair<mpl::int_<OFTInteger64List>, MemberContainerGetterPtr<GIntBig, &OGRFeature::GetFieldAsInteger64List> >
-  #endif
   > FieldGetters_Map;
 
 /**\ingroup GeometryInternals
@@ -360,10 +357,8 @@ typedef mpl::map
   , mpl::pair<mpl::int_<OFTRealList>,    MemberContainerSetterPtr<double, &OGRFeature::SetField> >
   , mpl::pair<mpl::int_<OFTString>,      MemberSetterPtr<char const*,     &OGRFeature::SetField/*, std::string*/> >
   , mpl::pair<mpl::int_<OFTStringList>,  StringListMemberSetterPtr<std::vector<std::string> > >
-  #ifdef OTB_USE_GDAL_20
   , mpl::pair<mpl::int_<OFTInteger64>, MemberSetterPtr<GIntBig, &OGRFeature::SetField> >
   , mpl::pair<mpl::int_<OFTInteger64List>, MemberContainerSetterPtr<const GIntBig, &OGRFeature::SetField> >
-  #endif
   > FieldSetters_Map;
 
 /**\ingroup GeometryInternals
diff --git a/Modules/Adapters/GdalAdapters/include/otbOGRHelpers.h b/Modules/Adapters/GdalAdapters/include/otbOGRHelpers.h
index e693c942805efa8abfaed49e6cf12c77240e86a2..c490e9ce62204b80440594294c129ccaf5a9691b 100644
--- a/Modules/Adapters/GdalAdapters/include/otbOGRHelpers.h
+++ b/Modules/Adapters/GdalAdapters/include/otbOGRHelpers.h
@@ -27,6 +27,7 @@
 #include <cassert>
 #include <boost/range/begin.hpp>
 #include <boost/range/end.hpp>
+#include "ogr_feature.h"
 #if defined(__GNUC__) || defined(__clang__)
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wunused-local-typedefs"
@@ -43,6 +44,8 @@
 
 #include "OTBGdalAdaptersExport.h"
 
+class GDALDataset;
+
 namespace otb
 {
 namespace ogr
@@ -105,6 +108,35 @@ private:
   std::vector<char const*> m_raw;
 };
 
+/** 
+  * Return the list of available drivers.
+  *
+  * \return A vector of string containing the list of available drivers.
+*/  
+OTBGdalAdapters_EXPORT
+std::vector<std::string> GetAvailableDriversAsStringVector();
+
+/**
+  * Return the list of files composing the dataset.
+  * 
+  * \param dataset Pointer to the dataset to get the file list from. Will not be
+  * checked for null pointer.
+  * 
+  * \return A vector of string containing the list of files.
+*/
+   
+OTBGdalAdapters_EXPORT 
+std::vector<std::string> GetFileListAsStringVector(GDALDataset * dataset);
+
+/**
+  * Returns true if the field 'index' is set and not-null in the given feature
+  *
+  * Before gdal 2.2, it calls OGRFeature::IsFieldSet().
+  * After gdal 2.2, it calls OGRFeature::IsFieldSetAndNotNull()
+*/
+OTBGdalAdapters_EXPORT
+bool IsFieldSetAndNotNull(OGRFeature *feat, int index);
+
 } // ogr namespace
 } // end namespace otb
 
diff --git a/Modules/Adapters/GdalAdapters/include/otbOGRLayerWrapper.h b/Modules/Adapters/GdalAdapters/include/otbOGRLayerWrapper.h
index 880832a3dace41a2eb827857479fa9c23517d1da..7cce53313186f56794aef3ccec545542dbba5722 100644
--- a/Modules/Adapters/GdalAdapters/include/otbOGRLayerWrapper.h
+++ b/Modules/Adapters/GdalAdapters/include/otbOGRLayerWrapper.h
@@ -36,7 +36,6 @@
 #endif
 // #include "itkIndent.h", included from field
 #include "otbOGRFeatureWrapper.h"
-#include "otbOGRVersionProxy.h"
 #include <string>
 
 // #include "ogr_core.h" // OGRwkbGeometryType, included from feature -> field
@@ -119,7 +118,7 @@ public:
    * OGRDataSource::ExecuteSQL(). It's actually the constructor called by \c
    * DataSource::ExecuteSQL().
    */
-    Layer(OGRLayer* layer, otb::ogr::version_proxy::GDALDatasetType& sourceInChargeOfLifeTime, bool modifiable);
+    Layer(OGRLayer* layer, GDALDataset& sourceInChargeOfLifeTime, bool modifiable);
   //@}
 
   /**\name Features collection */
diff --git a/Modules/Adapters/GdalAdapters/include/otbOGRVersionProxy.h b/Modules/Adapters/GdalAdapters/include/otbOGRVersionProxy.h
deleted file mode 100644
index 7cae3f6dba4cf94203bfcb7e3cd52f431a5309c9..0000000000000000000000000000000000000000
--- a/Modules/Adapters/GdalAdapters/include/otbOGRVersionProxy.h
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
- *
- * This file is part of Orfeo Toolbox
- *
- *     https://www.orfeo-toolbox.org/
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef otbOGRVersionProxy_h
-#define otbOGRVersionProxy_h
-
-#include <string>
-#include <vector>
-#include "otbConfigure.h"
-#include "itkMacro.h"
-
-#if defined(_MSC_VER)
-#pragma warning ( push )
-#pragma warning ( disable: 4251 )
-#include "ogr_core.h" // OGR enums
-#pragma warning ( pop )
-#else
-#include "ogr_core.h" // OGR enums
-#endif
-
-
-#ifdef OTB_USE_GDAL_20
-class GDALDataset;
-class GDALDriver;
-#else
-class OGRDataSource;
-class OGRSFDriver;
-#endif
-
-class OGRFeature;
-
-#include "OTBGdalAdaptersExport.h"
-
-namespace otb
-{
-namespace ogr
-{
-namespace version_proxy
-{
-
-/**
-* With Gdal >= 2.0, this function will test equality between type and
-* OFTInteger64 enum. Otherwise, it returns false. 
-*/
-OTBGdalAdapters_EXPORT bool IsOFTInteger64(OGRFieldType type);
-
-/** 
- * This namespace holds proxy functions hiding interface changes in gdal 2.0 
- *
- * This namespace holds proxy functions hiding interface changes in OGR
- * dataset between gdal 1.x (x>10) and gdal 2.x. It defines a common
- * interface that should be used in place of calling directly the
- * wrapped gdal functions.
- * 
- * Whenever GDALDataset and GDALDriver have to be used to open a
- * vector dataset (or OGRDataSource an OGRSFDriver for gdal 1.x), one
- * should use ogr::version_proxy types GDALDatasetType and
- * GDALDriverType.
- * 
- * See function documentation for details.
- */
-
-  #ifdef OTB_USE_GDAL_20
-  typedef GDALDataset GDALDatasetType;
-  typedef GDALDriver GDALDriverType;
-  #else
-  typedef OGRDataSource GDALDatasetType;
-  typedef OGRSFDriver   GDALDriverType;
-#endif
-
-  /** 
-   * This function opens a file, possibly in read-only mode, and returns
-   * a dataset.
-   *
-   * Calls OGRSFDriverRegistrar::Open for gdal 1.x implementation and GDALopenEx for
-   * gdal 2.x implementation.
-
-   * \param filename Filename of the file to open
-   * \param readOnly: If true, dataset is open in read-only mode.
-   * \return NULL if file could not be open.
-   */
-  OTBGdalAdapters_EXPORT   
-  GDALDatasetType * Open(const char * filename, bool readOnly = true , std::vector< std::string > const & options = std::vector< std::string >() );
-
-  /**
-   * This function closes a dataset.
-   *
-   * Calls OGRDataSource::DestroyDataSource for gdal 1.x
-   * implementation and GDALClose for gdal 2.x implementation.
-   *
-   * \param dataset Pointer to the dataset to close. Will not be
-   * checked for null pointer.
-   */
-  OTBGdalAdapters_EXPORT
-  void Close(GDALDatasetType * dataset);
-
-  /**
-   * This function creates a new dataset.
-   *
-   * Calls OGRSFDriver::CreateDataSource for gdal 1.x implementation
-   * and GDALDriver::Create with (0,0) raster size for gdal 2.x
-   * implementation
-   * 
-   * \param driver Pointer to the driver used for creation. Will not
-   * be checked for null pointer.
-   *
-   * \param name Name of the dataset to create.
-   * 
-   * \return NULL if dataset could not be created.
-   */
-  OTBGdalAdapters_EXPORT
-  GDALDatasetType * Create(GDALDriverType * driver, const char * name , std::vector< std::string > const & options = std::vector< std::string >() );
-
-
-  /**
-   * This function physically deletes an existing dataset.
-   * 
-   * Calls OGRDataSource::DeleteDataSource for gdal 1.x implementation
-   * and GDALDriver::Delete for gdal 2.x implementation.
-   *
-   * \param name Name of the dataset to destroy.
-   */
-  OTBGdalAdapters_EXPORT   
-  bool Delete(const char * name);
-
-  /**
-   * This function returns a pointer to the driver from its name.
-   * 
-   * Calls OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName() for
-   * gdal 1.x implementation and
-   * GetGDALDriverManager()->GetDriverByName() for gdal 2.x
-   * implementation.
-   * 
-   * \param name Name of the driver to retrieve
-   * 
-   * \return NULL if no driver could be retrieved.
-   */
-  OTBGdalAdapters_EXPORT 
-  GDALDriverType *  GetDriverByName(const char * name);
-
-  OTBGdalAdapters_EXPORT
-  std::string GetDriverNameFromDataSource(const GDALDatasetType * ds);
-
-  /**
-   * Sync dataset to disk.
-   *
-   * Calls OGRDataSource::SyncToDisk() for gdal 1.x implementation and
-   * GDALDataset::FlushCache() for gdal 2.x  implementation.
-   *
-   * \param dataset Pointer to the dataset to sync. Will not be
-   * checked for null pointer.
-   *
-   * \return True if sync went on without any error.
-   */
-   OTBGdalAdapters_EXPORT
-   bool SyncToDisk(GDALDatasetType * dataset);
-
-  /**
-   * \return The name of the dataset class behind the implementation
-   * (OGRDataSource for gdal 1.x and GdalDataset for gdal 2.x)
-   */
-  OTBGdalAdapters_EXPORT
-  std::string GetDatasetClassName();
-
-  /**
-   * \return The name of the driver class behind the implementation
-   * (OGRSFDriver for gdal 1.x and GDALDriver for gdal 2.x)
-   */
-  OTBGdalAdapters_EXPORT 
-  std::string GetDriverClassName();
-
-  /**
-   * Return the list of files composing the dataset.
-   * 
-   * Calls OGRDataSource::GetName() and wrap in string vector for gdal
-   * 1.x implementation, and GDALDataset::GetFileList and wrap in
-   * string vector for gdal 2.x implementation.
-   *  
-   * \param dataset Pointer to the dataset to get the file list from. Will not be
-   * checked for null pointer.
-   * 
-   * \return A vector of string containing the list of files.
-   */
-   
-  OTBGdalAdapters_EXPORT 
-  std::vector<std::string> GetFileListAsStringVector(GDALDatasetType * dataset);
-
-  /** 
-   * Return the list of available drivers.
-   *
-   * Calls OGRSFDriverRegistrar::GetRegistrar() for gdal 1.x
-   * implementation and GetGDALDriverManager() for gdal 2.x
-   * implementation.
-   *
-   * \return A vector of string containing the list of available drivers.
-   */  
-  OTBGdalAdapters_EXPORT
-  std::vector<std::string> GetAvailableDriversAsStringVector();
-
-  /**
-   * Returns true if the field 'index' is set and not-null in the given feature
-   *
-   * Before gdal 2.2, it calls OGRFeature::IsFieldSet().
-   * After gdal 2.2, it calls OGRFeature::IsFieldSetAndNotNull()
-   */
-   OTBGdalAdapters_EXPORT
-   bool IsFieldSetAndNotNull(OGRFeature *feat, int index);
-
-}
-}
-} // end namespace otb
-
-#endif
diff --git a/Modules/Adapters/GdalAdapters/src/CMakeLists.txt b/Modules/Adapters/GdalAdapters/src/CMakeLists.txt
index 0f73c07a03e044b6c89d6a19b5df6fc6b9ae4851..b5d09907dbcbf31712526d4547566d76496c2595 100644
--- a/Modules/Adapters/GdalAdapters/src/CMakeLists.txt
+++ b/Modules/Adapters/GdalAdapters/src/CMakeLists.txt
@@ -28,8 +28,8 @@ set(OTBGdalAdapters_SRC
   otbOGRDriversInit.cxx
   otbGeometriesToGeometriesFilter.cxx
   otbOGRDataSourceWrapper.cxx
-  otbOGRVersionProxy.cxx
   otbOGRExtendedFilenameToOptions.cxx
+  otbOGRHelpers.cxx
   )
 
 add_library(OTBGdalAdapters ${OTBGdalAdapters_SRC})
diff --git a/Modules/Adapters/GdalAdapters/src/otbOGRDataSourceWrapper.cxx b/Modules/Adapters/GdalAdapters/src/otbOGRDataSourceWrapper.cxx
index ea65a5c2c577a97ed2f967418816ac2b1a17a6d0..d60378e47920a41d5ffa567902fb3d06e7e7c6e0 100644
--- a/Modules/Adapters/GdalAdapters/src/otbOGRDataSourceWrapper.cxx
+++ b/Modules/Adapters/GdalAdapters/src/otbOGRDataSourceWrapper.cxx
@@ -48,13 +48,13 @@ bool otb::ogr::DataSource::Clear()
   return true;
 }
 
-void otb::ogr::DataSource::Reset(otb::ogr::version_proxy::GDALDatasetType * source)
+void otb::ogr::DataSource::Reset(GDALDataset * source)
 {
   if (m_DataSource) {
     // OGR makes a pointless check for non-nullity in
     // GDALDataset::DestroyDataSource (pointless because "delete 0" is
     // perfectly valid -> it's a no-op)
-    ogr::version_proxy::Close(m_DataSource); // void, noexcept
+    GDALClose(m_DataSource); // void, noexcept
   }
   m_DataSource = source;
 }
@@ -108,7 +108,7 @@ char const* DeduceDriverName(std::string filename)
   ExtensionDriverAssociation const* whichIt =
     std::find_if(
       boost::begin(k_ExtensionDriverMap), boost::end(k_ExtensionDriverMap),
-      boost::bind(&ExtensionDriverAssociation::Matches, _1, extension));
+      [&](auto const & x) { return x.Matches(extension); } );
   if (whichIt ==  boost::end(k_ExtensionDriverMap))
     {
     return nullptr; // nothing found
@@ -126,10 +126,16 @@ otb::ogr::DataSource::DataSource()
 {
   Drivers::Init();
 
-  ogr::version_proxy::GDALDriverType * d = 
-    ogr::version_proxy::GetDriverByName("Memory");
+  GDALDriver * d = 
+    GetGDALDriverManager()->GetDriverByName("Memory");
   assert(d && "OGR Memory driver not found");
-  m_DataSource = ogr::version_proxy::Create(d,"in-memory");
+  m_DataSource = d->Create( "in-memory" ,
+                         0 ,
+                         0 ,
+                         0 ,
+                         GDT_Unknown ,
+                         0 );
+
   if (!m_DataSource) {
     itkExceptionMacro(<< "Failed to create OGRMemDataSource: " 
                       << CPLGetLastErrorMsg());
@@ -137,7 +143,7 @@ otb::ogr::DataSource::DataSource()
 }
 
 otb::ogr::DataSource::DataSource( 
-    otb::ogr::version_proxy::GDALDatasetType * source ,
+    GDALDataset * source ,
     Modes::type mode ,
     const std::vector< std::string > & options /*NULL*/ )
 : m_DataSource(source) ,
@@ -155,10 +161,12 @@ otb::ogr::DataSource::Pointer otb::ogr::DataSource::OpenDataSource(std::string c
   std::string simpleFileName = fileNameHelper->GetSimpleFileName();
 
   bool update = (mode != Modes::Read);
-  ogr::version_proxy::GDALDatasetType * source = 
-    ogr::version_proxy::Open( simpleFileName.c_str() ,
-                              !update ,
-                              fileNameHelper->GetGDALOpenOptions() );
+  GDALDataset * source = (GDALDataset *)GDALOpenEx(
+      simpleFileName.c_str(), 
+      (update? GDAL_OF_UPDATE: GDAL_OF_READONLY) | GDAL_OF_VECTOR,
+      NULL,
+      otb::ogr::StringListConverter( fileNameHelper->GetGDALOpenOptions() ).to_ogr(),
+      NULL);
   if (!source)
     {
     // In read mode, this is a failure
@@ -178,8 +186,8 @@ otb::ogr::DataSource::Pointer otb::ogr::DataSource::OpenDataSource(std::string c
         <<simpleFileName<<">.");
       }
 
-    ogr::version_proxy::GDALDriverType * d = 
-      ogr::version_proxy::GetDriverByName(  driverName  );
+    GDALDriver * d = 
+      GetGDALDriverManager()->GetDriverByName(  driverName  );
 
     if(!d)
       {
@@ -187,10 +195,13 @@ otb::ogr::DataSource::Pointer otb::ogr::DataSource::OpenDataSource(std::string c
         << ", check your OGR configuration for available drivers." );
       }
 
-    source = ogr::version_proxy::Create( 
-                  d ,
-                  simpleFileName.c_str() ,
-                  fileNameHelper->GetGDALCreationOptions() );
+    source = d->Create( simpleFileName.c_str() ,
+                         0 ,
+                         0 ,
+                         0 ,
+                         GDT_Unknown ,
+                         otb::ogr::StringListConverter( 
+                          fileNameHelper->GetGDALCreationOptions() ).to_ogr() );
     if (!source) {
       itkGenericExceptionMacro(<< "Failed to create GDALDataset <"
         << simpleFileName << "> (driver name: <" << driverName 
@@ -207,12 +218,40 @@ void DeleteDataSource(std::string const& datasourceName)
   fileNameHelper->SetExtendedFileName( datasourceName.c_str() );
   std::string simpleFileName = fileNameHelper->GetSimpleFileName();
 
-  bool ret = otb::ogr::version_proxy::Delete(simpleFileName.c_str());
-  if (!ret)
+  // Open dataset
+  GDALDataset * poDS = (GDALDataset *)GDALOpenEx(
+      simpleFileName.c_str(), 
+       GDAL_OF_UPDATE | GDAL_OF_VECTOR,
+      NULL,
+      NULL,
+      NULL);
+
+  GDALDriver * poDriver = NULL;
+  if(poDS)
     {
-    itkGenericExceptionMacro(<< "Deletion of data source " << simpleFileName
+    poDriver = poDS->GetDriver();
+    GDALClose(poDS);
+    }
+  else
+    {
+    itkGenericExceptionMacro(<< "Cannot open data source " << simpleFileName
+                             << ": " << CPLGetLastErrorMsg());
+    }
+  if(poDriver)
+    {
+    OGRErr ret = poDriver->Delete(simpleFileName.c_str());
+    if (ret != OGRERR_NONE)
+      {
+      itkGenericExceptionMacro(<< "Deletion of data source " << simpleFileName
                              << " failed: " << CPLGetLastErrorMsg());
+      }
     }
+  else 
+    {
+    itkGenericExceptionMacro(<< "Cannot get driver associated with data source " << simpleFileName
+                             << ": " << CPLGetLastErrorMsg());
+    }
+
 }
 
 otb::ogr::DataSource::Pointer
@@ -228,12 +267,15 @@ otb::ogr::DataSource::New(std::string const& datasourceName, Modes::type mode)
     }
 
   Drivers::Init();
-  ogr::version_proxy::GDALDatasetType * ds = 
-    ogr::version_proxy::Open( simpleFileName.c_str() , true );
-
+  GDALDataset * ds = (GDALDataset *)GDALOpenEx(
+      simpleFileName.c_str(), 
+      GDAL_OF_READONLY | GDAL_OF_VECTOR,
+      NULL,
+      NULL,
+      NULL);
   bool ds_exists = (ds!=nullptr);
 
-  ogr::version_proxy::Close(ds);
+  GDALClose(ds);
 
 
   if (ds_exists && mode == Modes::Overwrite)
@@ -246,7 +288,7 @@ otb::ogr::DataSource::New(std::string const& datasourceName, Modes::type mode)
 
 /*static*/
 otb::ogr::DataSource::Pointer
-otb::ogr::DataSource::New(otb::ogr::version_proxy::GDALDatasetType * source , Modes::type mode , const std::vector< std::string > & layerOptions )
+otb::ogr::DataSource::New(GDALDataset * source , Modes::type mode , const std::vector< std::string > & layerOptions )
 {
   Pointer res = new DataSource( source , mode , layerOptions );
   res->UnRegister();
@@ -727,12 +769,7 @@ OGREnvelope otb::ogr::DataSource::GetGlobalExtent(bool force/* = false */, std::
       cExtent.MaxX = real_maxx;
       cExtent.MaxY = real_maxy;
 
-#if GDAL_VERSION_NUM >= 1700
       OGRCoordinateTransformation::DestroyCT(coordTransformation);
-#else
-#warning the following resource release may crash, please update your version of GDAL
-      delete coordTransformation; // note there is no garanty
-#endif
       }
     // else: If srs are invalid, we assume that extent are coherent
 
@@ -785,20 +822,14 @@ bool otb::ogr::DataSource::HasCapability(std::string const& capabilityName) cons
 void otb::ogr::DataSource::SyncToDisk()
 {
   assert(m_DataSource && "Datasource not initialized");
-  bool ret = otb::ogr::version_proxy::SyncToDisk(m_DataSource);
-
-  if(!ret)
-    {
-    itkExceptionMacro( << "Cannot flush the pending of the OGRDataSource <"
-      << GetDatasetDescription() << ">: " << CPLGetLastErrorMsg());
-    }
+  m_DataSource->FlushCache();
 }
 
 
 std::string otb::ogr::DataSource::GetDatasetDescription() const
 {
   std::vector<std::string> files = 
-    otb::ogr::version_proxy::GetFileListAsStringVector( m_DataSource );
+    otb::ogr::GetFileListAsStringVector( m_DataSource );
   std::string description = "";
   for( std::vector<std::string>::const_iterator it = files.begin() ; 
        it!=files.end() ; ++it )
diff --git a/Modules/Adapters/GdalAdapters/src/otbOGRFeatureWrapper.cxx b/Modules/Adapters/GdalAdapters/src/otbOGRFeatureWrapper.cxx
index 8c4abc16a33d819ed4c700221fd8007972eb887e..20cb96ce876236d6b1384daf42a7b9659ddd7c47 100644
--- a/Modules/Adapters/GdalAdapters/src/otbOGRFeatureWrapper.cxx
+++ b/Modules/Adapters/GdalAdapters/src/otbOGRFeatureWrapper.cxx
@@ -43,7 +43,7 @@
 otb::ogr::Feature::Feature(OGRFeatureDefn & definition)
 : m_Feature(
   OGRFeature::CreateFeature(&definition),
-  boost::bind(&OGRFeature::DestroyFeature, _1))
+  [&](auto const & x) {return OGRFeature::DestroyFeature(x);})
 {
   CheckInvariants();
 }
@@ -52,7 +52,7 @@ otb::ogr::Feature::Feature(OGRFeature * feature)
 {
   if (feature)
     {
-    m_Feature.reset(feature, boost::bind(&OGRFeature::DestroyFeature, _1));
+    m_Feature.reset(feature, [&](auto const & x) {return OGRFeature::DestroyFeature(x);});
     }
   // else default is perfect -> delete null
 }
@@ -78,16 +78,11 @@ void otb::ogr::Feature::UncheckedSetFrom(Feature const& rhs, bool mustForgive)
 
 void otb::ogr::Feature::UncheckedSetFrom(Feature const& rhs, int * map, bool mustForgive)
 {
-#if GDAL_VERSION_NUM >= 1900
   const OGRErr res = m_Feature->SetFrom(&rhs.ogr(), map, mustForgive);
   if (res != OGRERR_NONE)
     {
     itkGenericExceptionMacro(<<"Cannot assign from another feature: " << CPLGetLastErrorMsg());
     }
-#else
-  itkGenericExceptionMacro("OGRLayer::SetFrom(feature, fieldmap, forgive) is not supported by OGR v"
-    << GDAL_VERSION_NUM << ". Upgrade to a version >= 1.9.0, and recompile OTB.")
-#endif
 }
 
 /*===========================================================================*/
diff --git a/Modules/Adapters/GdalAdapters/src/otbOGRFieldWrapper.cxx b/Modules/Adapters/GdalAdapters/src/otbOGRFieldWrapper.cxx
index 49f95f053546c6f59190ef88ae6d28cee0f19110..7bf292e9015bb3de1c4d51f109840300014a0acc 100644
--- a/Modules/Adapters/GdalAdapters/src/otbOGRFieldWrapper.cxx
+++ b/Modules/Adapters/GdalAdapters/src/otbOGRFieldWrapper.cxx
@@ -37,7 +37,6 @@
 #endif
 #include "otbOGRFeatureWrapper.h"
 #include "otbJoinContainer.h"
-#include "otbOGRVersionProxy.h"
 #include <boost/array.hpp>
 /*===========================================================================*/
 /*===========================[ Static Assertions ]===========================*/
@@ -167,7 +166,7 @@ std::ostream & otb::ogr::Field::UncheckedPrintSelf(
 
 bool otb::ogr::Field::UncheckedHasBeenSet() const
 {
-  return otb::ogr::version_proxy::IsFieldSetAndNotNull(m_Feature.get(), m_index);
+  return otb::ogr::IsFieldSetAndNotNull(m_Feature.get(), m_index);
 }
 
 void otb::ogr::Field::UncheckedUnset() const
diff --git a/Modules/Adapters/GdalAdapters/src/otbOGRGeometryWrapper.cxx b/Modules/Adapters/GdalAdapters/src/otbOGRGeometryWrapper.cxx
index 740aaa766a3f496fde86fc59d33a780d089494a9..ad03e5a2be515641a45ee6c0e1c247d55bebd8e8 100644
--- a/Modules/Adapters/GdalAdapters/src/otbOGRGeometryWrapper.cxx
+++ b/Modules/Adapters/GdalAdapters/src/otbOGRGeometryWrapper.cxx
@@ -25,10 +25,6 @@
 #include "otbOGRGeometryWrapper.h"
 #include "ogr_geometry.h"
 
-#if GDAL_VERSION_NUM < 1900
-#  include "itkMacro.h"
-#endif
-
 #ifdef _MSC_VER
 // warning conversion int -> bool
 #pragma warning ( disable : 4800 )
@@ -105,12 +101,7 @@ otb::ogr::UniqueGeometryPtr otb::ogr::Union(OGRGeometry const& lhs, OGRGeometry
 
 otb::ogr::UniqueGeometryPtr otb::ogr::UnionCascaded(OGRGeometry const& this_)
 {
-#if GDAL_VERSION_NUM >= 1800
   return UniqueGeometryPtr(this_.UnionCascaded());
-#else
-  itkGenericExceptionMacro("OGRGeometry::UnionCascaded is not supported by OGR v"
-    << GDAL_VERSION_NUM << ". Upgrade to a version >= 1.8.0, and recompile OTB.");
-#endif
 }
 
 otb::ogr::UniqueGeometryPtr otb::ogr::Difference(OGRGeometry const& lhs, OGRGeometry const& rhs)
@@ -120,41 +111,20 @@ otb::ogr::UniqueGeometryPtr otb::ogr::Difference(OGRGeometry const& lhs, OGRGeom
 
 otb::ogr::UniqueGeometryPtr otb::ogr::SymDifference(OGRGeometry const& lhs, OGRGeometry const& rhs)
 {
-#if GDAL_VERSION_NUM >= 1800
   return UniqueGeometryPtr(lhs.SymDifference(&rhs));
-#else
-  return UniqueGeometryPtr(lhs.SymmetricDifference(&rhs));
-#endif
 }
 
 otb::ogr::UniqueGeometryPtr otb::ogr::SimplifyDontPreserveTopology(OGRGeometry const& g, double tolerance)
 {
-#if GDAL_VERSION_NUM >= 1800
   return UniqueGeometryPtr(g.Simplify(tolerance));
-#else
-  itkGenericExceptionMacro("OGRGeometry::Simplify is not supported by OGR v"
-    << GDAL_VERSION_NUM << ". Upgrade to a version >= 1.8.0, and recompile OTB.");
-#endif
 }
 
 otb::ogr::UniqueGeometryPtr otb::ogr::SimplifyPreserveTopology(OGRGeometry const& g, double tolerance)
 {
-#if GDAL_VERSION_NUM >= 1900
   return UniqueGeometryPtr(g.SimplifyPreserveTopology(tolerance));
-#else
-  itkGenericExceptionMacro("OGRGeometry::Simplify is not supported by OGR v"
-    << GDAL_VERSION_NUM << ". Upgrade to a version >= 1.9.0, and recompile OTB.");
-#endif
 }
 
 otb::ogr::UniqueGeometryPtr otb::ogr::Simplify(OGRGeometry const& g, double tolerance)
 {
-#if   GDAL_VERSION_NUM >= 1900
   return UniqueGeometryPtr(g.SimplifyPreserveTopology(tolerance));
-#elif GDAL_VERSION_NUM >= 1800
-  return UniqueGeometryPtr(g.Simplify(tolerance));
-#else
-  itkGenericExceptionMacro("OGRGeometry::Simplify(PreserveTopology) is not supported by OGR v"
-    << GDAL_VERSION_NUM << ". Upgrade to a version >= 1.9.0, and recompile OTB.");
-#endif
 }
diff --git a/Modules/Adapters/GdalAdapters/src/otbOGRHelpers.cxx b/Modules/Adapters/GdalAdapters/src/otbOGRHelpers.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..8bb2e064520c19b355cf76f6f4d787b0ff5e8031
--- /dev/null
+++ b/Modules/Adapters/GdalAdapters/src/otbOGRHelpers.cxx
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "otbOGRHelpers.h"
+
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
+#include "gdal_priv.h"
+#include "ogr_feature.h"
+#pragma GCC diagnostic pop
+#else
+#include "gdal_priv.h"
+#include "ogr_feature.h"
+#endif // __GNUC__ || __clang__
+
+namespace otb
+{
+namespace ogr
+{
+
+std::vector<std::string> GetAvailableDriversAsStringVector()
+{
+  std::vector<std::string> ret;
+
+  int nbDrivers = GetGDALDriverManager()->GetDriverCount();
+
+  for(int i = 0; i < nbDrivers;++i)
+    {
+    ret.push_back(GDALGetDriverShortName(GetGDALDriverManager()->GetDriver(i)));
+    }
+  return ret;
+}
+
+namespace raii
+{
+// This class is used in the next function, so as to prevent any
+// resource leak on char ** returned by dataset->GetFileList()
+class CharPPCapsule
+{
+public:
+  CharPPCapsule(char ** in)
+    : m_P(in)
+  {}
+
+  const char ** P() const
+  {
+    return const_cast<const char **>(m_P);
+  }
+
+  ~CharPPCapsule()
+  {
+    if(m_P)
+      CSLDestroy(m_P);
+  }
+
+private:
+  char ** m_P;
+};
+}
+
+std::vector<std::string> GetFileListAsStringVector(GDALDataset * dataset)
+{
+  std::vector<std::string> ret;
+  raii::CharPPCapsule capsule(dataset->GetFileList());
+  std::string files_str="";
+
+  if(capsule.P())
+    {
+    unsigned int i = 0;
+    while(capsule.P()[i]!=NULL)
+      {
+      ret.push_back(std::string(capsule.P()[i]));
+      ++i;
+      }
+    }
+  return ret;
+}
+
+/*----------------------[GDAL 2.2 change on IsFieldSet()]---------------------*/
+bool IsFieldSetAndNotNull(OGRFeature *feat, int index)
+{
+#if GDAL_VERSION_NUM<2020000
+  return feat->IsFieldSet(index);
+#else
+  return feat->IsFieldSetAndNotNull(index);
+#endif
+}
+
+}
+} // end namespaces
\ No newline at end of file
diff --git a/Modules/Adapters/GdalAdapters/src/otbOGRLayerWrapper.cxx b/Modules/Adapters/GdalAdapters/src/otbOGRLayerWrapper.cxx
index 4a9596a021a1fc4eb876508084a13a77e2a3722b..ff0d528171aceda6bb2164576e62ab7316d0437e 100644
--- a/Modules/Adapters/GdalAdapters/src/otbOGRLayerWrapper.cxx
+++ b/Modules/Adapters/GdalAdapters/src/otbOGRLayerWrapper.cxx
@@ -69,8 +69,8 @@ otb::ogr::Layer::Layer(OGRLayer* layer, bool modifiable)
 {
 }
 
-otb::ogr::Layer::Layer(OGRLayer* layer, otb::ogr::version_proxy::GDALDatasetType& sourceInChargeOfLifeTime, bool modifiable)
-:   m_Layer(layer,  boost::bind(&otb::ogr::version_proxy::GDALDatasetType::ReleaseResultSet, boost::ref(sourceInChargeOfLifeTime), _1))
+otb::ogr::Layer::Layer(OGRLayer* layer, GDALDataset& sourceInChargeOfLifeTime, bool modifiable)
+:   m_Layer(layer, [&](auto const& x) { return sourceInChargeOfLifeTime.ReleaseResultSet(x); })
   , m_Modifiable(modifiable)
 {
   assert(layer && "A null OGRlayer cannot belong to an OGRDataSource" );
@@ -192,11 +192,7 @@ void otb::ogr::Layer::SetFeature(Feature feature)
 std::string otb::ogr::Layer::GetName() const
 {
   assert(m_Layer && "null layer");
-#if GDAL_VERSION_NUM >= 1800
   return m_Layer->GetName();
-#else
-  return GetLayerDefn().GetName();
-#endif
 }
 
 OGREnvelope otb::ogr::Layer::GetExtent(bool force/* = false */) const
@@ -339,17 +335,12 @@ void otb::ogr::Layer::DeleteField(int fieldIndex)
       <<GetName()<<">: layer is not modifiable");
     }
 
-#if GDAL_VERSION_NUM < 1900
-  itkGenericExceptionMacro("OGRLayer::DeleteField is not supported by OGR v"
-    << GDAL_VERSION_NUM << ". Upgrade to a version >= 1.9.0, and recompile OTB.")
-#else
   const OGRErr res = m_Layer->DeleteField(fieldIndex);
   if (res != OGRERR_NONE)
     {
     itkGenericExceptionMacro(<< "Cannot delete the "<<fieldIndex << "th field in the layer <"
       <<GetName() <<">: " << CPLGetLastErrorMsg());
     }
-#endif
 }
 
 void otb::ogr::Layer::AlterFieldDefn(
@@ -363,10 +354,6 @@ void otb::ogr::Layer::AlterFieldDefn(
       <<GetName()<<">: layer is not modifiable");
     }
 
-#if GDAL_VERSION_NUM < 1900
-  itkGenericExceptionMacro("OGRLayer::AlterFieldDefn is not supported by OGR v"
-    << GDAL_VERSION_NUM << ". Upgrade to a version >= 1.9.0, and recompile OTB.")
-#else
   const OGRErr res = m_Layer->AlterFieldDefn(
     int(fieldIndex),
     &newFieldDefn.ogr(),
@@ -376,7 +363,6 @@ void otb::ogr::Layer::AlterFieldDefn(
     itkGenericExceptionMacro(<< "Cannot alter the "<<fieldIndex << "th field in the layer <"
       <<GetName() <<">: " << CPLGetLastErrorMsg());
     }
-#endif
 }
 
 void otb::ogr::Layer::ReorderField(size_t oldPos, size_t newPos)
@@ -389,17 +375,12 @@ void otb::ogr::Layer::ReorderField(size_t oldPos, size_t newPos)
       <<GetName()<<">: layer is not modifiable");
     }
 
-#if GDAL_VERSION_NUM < 1900
-  itkGenericExceptionMacro("OGRLayer::ReorderField is not supported by OGR v"
-    << GDAL_VERSION_NUM << ". Upgrade to a version >= 1.9.0, and recompile OTB.")
-#else
   const OGRErr res = m_Layer->ReorderField(int(oldPos), int(newPos));
   if (res != OGRERR_NONE)
     {
     itkGenericExceptionMacro(<< "Cannot move the "<<oldPos << "th field to the "
       << newPos << "th position in the layer <" <<GetName() <<">: " << CPLGetLastErrorMsg());
     }
-#endif
 }
 
 void otb::ogr::Layer::ReorderFields(int * map)
@@ -412,42 +393,28 @@ void otb::ogr::Layer::ReorderFields(int * map)
       <<GetName()<<">: layer is not modifiable");
     }
 
-#if GDAL_VERSION_NUM < 1900
-  itkGenericExceptionMacro("OGRLayer::ReorderField is not supported by OGR v"
-    << GDAL_VERSION_NUM << ". Upgrade to a version >= 1.9.0, and recompile OTB.")
-#else
   const OGRErr res = m_Layer->ReorderFields(map);
   if (res != OGRERR_NONE)
     {
     itkGenericExceptionMacro(<< "Cannot reorder the fields of the layer <"
       <<GetName() <<">: " << CPLGetLastErrorMsg());
     }
-#endif
 }
 
 void otb::ogr::Layer::SetIgnoredFields(char const** fieldNames)
 {
   assert(m_Layer && "OGRLayer not initialized");
-#if GDAL_VERSION_NUM >= 1900
   const OGRErr res = m_Layer->SetIgnoredFields(fieldNames);
   if (res != OGRERR_NONE)
     {
     itkGenericExceptionMacro(<< "Cannot set fields to ignore on the layer <"
       <<GetName() <<">: " << CPLGetLastErrorMsg());
     }
-#else
-  itkGenericExceptionMacro("OGRLayer::SetIgnoredFields is not supported by OGR v"
-    << GDAL_VERSION_NUM << ". Upgrade to a version >= 1.9.0, and recompile OTB.")
-#endif
 }
 
 OGRwkbGeometryType otb::ogr::Layer::GetGeomType() const
 {
   assert(m_Layer && "OGRLayer not initialized");
-#if GDAL_VERSION_NUM < 1800
-  return GetLayerDefn().GetGeomType();
-#else
   return m_Layer->GetGeomType();
-#endif
 }
 
diff --git a/Modules/Adapters/GdalAdapters/src/otbOGRVersionProxy.cxx b/Modules/Adapters/GdalAdapters/src/otbOGRVersionProxy.cxx
deleted file mode 100644
index b616fe752698e68c3731b5ef6bf822802468a33c..0000000000000000000000000000000000000000
--- a/Modules/Adapters/GdalAdapters/src/otbOGRVersionProxy.cxx
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
- *
- * This file is part of Orfeo Toolbox
- *
- *     https://www.orfeo-toolbox.org/
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "otbOGRVersionProxy.h"
-#include "otbOGRHelpers.h"
-
-#include "itkMacro.h"
-
-#if defined(__GNUC__) || defined(__clang__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wshadow"
-#if GDAL_VERSION_NUM<2000000
-#include "ogrsf_frmts.h"
-#else
-#include "gdal_priv.h"
-#endif
-#include "ogr_feature.h"
-#pragma GCC diagnostic pop
-#else
-#if GDAL_VERSION_NUM<2000000
-#include "ogrsf_frmts.h"
-#else
-#include "gdal_priv.h"
-#endif
-#include "ogr_feature.h"
-#endif // __GNUC__ || __clang__
-
-namespace otb
-{
-namespace ogr
-{
-namespace version_proxy
-{
-
-/*-------------------------[GDAL v2 API change]-------------------------------*/
-OTBGdalAdapters_EXPORT bool IsOFTInteger64(OGRFieldType type)
-{
-#if GDAL_VERSION_NUM<2000000
-  (void)type;
-  return false;
-#else
-  return type == OFTInteger64;
-#endif
-}
-
-
-GDALDatasetType * Open(const char * filename, bool readOnly , std::vector< std::string > const & options )
-{
-#if GDAL_VERSION_NUM<2000000
-  (void)options;
-  return OGRSFDriverRegistrar::Open(filename,!readOnly);
-#else
-  return (GDALDatasetType *)GDALOpenEx(
-      filename, 
-      (readOnly? GDAL_OF_READONLY : GDAL_OF_UPDATE) | GDAL_OF_VECTOR,
-      NULL,
-      otb::ogr::StringListConverter( options ).to_ogr(),
-      NULL);
-#endif
-}
-
-void Close(GDALDatasetType * dataset)
-{
-#if GDAL_VERSION_NUM<2000000
-  OGRDataSource::DestroyDataSource(dataset);
-#else
-  GDALClose(dataset);
-#endif
-}
-
-GDALDatasetType * Create(GDALDriverType * driver, const char * name ,  std::vector< std::string > const & options )
-{
-#if GDAL_VERSION_NUM<2000000
-  (void)options;
-  GDALDatasetType * ds = driver->CreateDataSource(name);
-
-  if(ds)
-    ds->SetDriver(driver);
-
-  return ds;
-#else
-  return driver->Create( name ,
-                         0 ,
-                         0 ,
-                         0 ,
-                         GDT_Unknown ,
-                         otb::ogr::StringListConverter( options ).to_ogr() );
-#endif
-}
-
-bool Delete(const char * name)
-{
-  // Open dataset
-  GDALDatasetType * poDS = otb::ogr::version_proxy::Open(name,false);
-  GDALDriverType * poDriver = NULL;
-  if(poDS)
-    {
-    poDriver = poDS->GetDriver();
-    Close(poDS);
-    }
-#if GDAL_VERSION_NUM<2000000
-  if(poDriver && poDriver->TestCapability(ODrCDeleteDataSource))
-    {
-    OGRErr ret = poDriver->DeleteDataSource(name);
-    return (ret == OGRERR_NONE);
-    }
-#else
-  if(poDriver)
-    {
-    OGRErr ret = poDriver->Delete(name);
-    return (ret == OGRERR_NONE);
-    }
-#endif
-  return false;
-}
-
-GDALDriverType *  GetDriverByName(const char * name)
-{
-#if GDAL_VERSION_NUM<2000000
-  return OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(name);
-#else
-  return GetGDALDriverManager()->GetDriverByName(name);
-#endif
-}
-
-std::string GetDatasetClassName()
-{
-#if GDAL_VERSION_NUM<2000000
-  return std::string("OGRDataSource");
-#else
-  return std::string("GDALDataset");
-#endif
-}
-
-std::string GetDriverClassName()
-{
-#if GDAL_VERSION_NUM<2000000
-  return std::string("OGRSFDriver");
-#else
-  return std::string("GDALDriver");
-#endif
-}
-
-#if GDAL_VERSION_NUM>=2000000
-namespace raii
-{
-// This class is used in the next function, so as to prevent any
-// resource leak on char ** returned by dataset->GetFileList()
-class CharPPCapsule
-{
-public:
-  CharPPCapsule(char ** in)
-    : m_P(in)
-  {}
-
-  const char ** P() const
-  {
-    return const_cast<const char **>(m_P);
-  }
-
-  ~CharPPCapsule()
-  {
-    if(m_P)
-      CSLDestroy(m_P);
-  }
-
-private:
-  char ** m_P;
-};
-}
-#endif
-
-std::vector<std::string> GetFileListAsStringVector(GDALDatasetType * dataset)
-{
-  std::vector<std::string> ret;
-#if GDAL_VERSION_NUM<2000000
-  ret.push_back(std::string(dataset->GetName()));
-#else
-  raii::CharPPCapsule capsule(dataset->GetFileList());
-
-  std::string files_str="";
-
-  if(capsule.P())
-    {
-    unsigned int i = 0;
-    while(capsule.P()[i]!=NULL)
-      {
-      ret.push_back(std::string(capsule.P()[i]));
-      ++i;
-      }
-    }
-#endif
-  return ret;
-}
-
-bool SyncToDisk(GDALDatasetType * dataset)
-{
-#if GDAL_VERSION_NUM<2000000
-  const OGRErr res= dataset->SyncToDisk();
-  return (res == OGRERR_NONE);
-#else
-  dataset->FlushCache();
-  return true;
-#endif
-}
-
-std::vector<std::string> GetAvailableDriversAsStringVector()
-{
-  std::vector<std::string> ret;
-#if GDAL_VERSION_NUM<2000000
-  int nbDrivers = OGRSFDriverRegistrar::GetRegistrar()->GetDriverCount();
-
-  for(int i = 0; i < nbDrivers;++i)
-    {
-    ret.push_back(OGRSFDriverRegistrar::GetRegistrar()->GetDriver(i)->GetName());
-    }
-#else
-  int nbDrivers = GetGDALDriverManager()->GetDriverCount();
-
-  for(int i = 0; i < nbDrivers;++i)
-    {
-    ret.push_back(GDALGetDriverShortName(GetGDALDriverManager()->GetDriver(i)));
-    }
-#endif
-  return ret;
-}
-
-std::string GetDriverNameFromDataSource(const GDALDatasetType * ds)
-{
-#if GDAL_VERSION_NUM<2000000
-  return std::string(const_cast<GDALDatasetType *>(ds)->GetDriver()->GetName());
-#else
-  return std::string(const_cast<GDALDatasetType *>(ds)->GetDriverName());
-#endif
-}
-
-/*----------------------[GDAL 2.2 change on IsFieldSet()]---------------------*/
-bool IsFieldSetAndNotNull(OGRFeature *feat, int index)
-{
-#if GDAL_VERSION_NUM<2020000
-  return feat->IsFieldSet(index);
-#else
-  return feat->IsFieldSetAndNotNull(index);
-#endif
-}
-
-}
-}
-} // end namespace
-
diff --git a/Modules/Adapters/GdalAdapters/test/otbOGRDataSourceWrapperNew.cxx b/Modules/Adapters/GdalAdapters/test/otbOGRDataSourceWrapperNew.cxx
index 791733d41d40d2e558831a4b04b3c18d91d4badc..4dccbdd0b96d0a43c18937b8af73785ca6595f98 100644
--- a/Modules/Adapters/GdalAdapters/test/otbOGRDataSourceWrapperNew.cxx
+++ b/Modules/Adapters/GdalAdapters/test/otbOGRDataSourceWrapperNew.cxx
@@ -681,7 +681,6 @@ BOOST_AUTO_TEST_CASE(Add_n_Del_Fields)
     BOOST_CHECK_EQUAL(defn.GetFieldDefn(6), (void*)nullptr);
     }
 
-#if GDAL_VERSION_NUM >= 1900
   l.DeleteField(1);
   BOOST_CHECK_EQUAL(defn.GetFieldCount(), 5);
 
@@ -697,7 +696,6 @@ BOOST_AUTO_TEST_CASE(Add_n_Del_Fields)
     ogr::FieldDefn f4(*defn.GetFieldDefn(4));
     BOOST_CHECK_EQUAL(f4, k_f5);
     }
-#endif
   // todo: add reoder tests
 }
 
@@ -725,9 +723,7 @@ BOOST_AUTO_TEST_CASE(Add_n_Read_Fields)
 
   // ----[ int
   ogr::Field f0 = g0[0];
-#if GDAL_VERSION_NUM >= 1800
   BOOST_CHECK_EQUAL(f0.GetName(), k_f0.GetName());
-#endif
   f0.SetValue(42);
   BOOST_ASSERT(f0.HasBeenSet());
   BOOST_CHECK_EQUAL(f0.GetValue<int>(), 42);
@@ -737,9 +733,7 @@ BOOST_AUTO_TEST_CASE(Add_n_Read_Fields)
 
   // ----[ double
   ogr::Field f1 = g0["OFTReal"];
-#if GDAL_VERSION_NUM >= 1800
   BOOST_CHECK_EQUAL(f1.GetName(), k_f1.GetName());
-#endif
   // f1.SetValue(42); // need to support types promotion
   f1.SetValue(42.0); // need to support types promotion
   BOOST_ASSERT(f1.HasBeenSet());
@@ -747,9 +741,7 @@ BOOST_AUTO_TEST_CASE(Add_n_Read_Fields)
 
   // ----[ string
   ogr::Field f2 = g0["OFTString"];
-#if GDAL_VERSION_NUM >= 1800
   BOOST_CHECK_EQUAL(f2.GetName(), k_f2.GetName());
-#endif
   f2.SetValue(("foobar")); // need to support types promotion
   BOOST_ASSERT(f2.HasBeenSet());
   BOOST_CHECK_EQUAL(f2.GetValue<std::string>(), "foobar");
diff --git a/Modules/Adapters/OSSIMAdapters/include/otbSarSensorModelAdapter.h b/Modules/Adapters/OSSIMAdapters/include/otbSarSensorModelAdapter.h
index 3c1321e04a0de9af05693b0c78a7252be5b33303..f96615cc11cc4634991727f00fedd2c4d2533126 100644
--- a/Modules/Adapters/OSSIMAdapters/include/otbSarSensorModelAdapter.h
+++ b/Modules/Adapters/OSSIMAdapters/include/otbSarSensorModelAdapter.h
@@ -82,7 +82,18 @@ public:
   bool IsValidSensorModel() const;
 
   /** Deburst metadata if possible and return lines to keep in image file */
-  bool Deburst(std::vector<std::pair<unsigned long, unsigned long> > & lines);
+  bool Deburst(std::vector<std::pair<unsigned long, unsigned long> > & lines,
+	       std::pair<unsigned long,unsigned long> & samples, bool onlyValidSample=false);
+
+  /** Burst extraction and return lines/samples to keep into image file (the required burst) */
+  bool BurstExtraction(const unsigned int burst_index, std::pair<unsigned long,unsigned long> & lines, 
+		       std::pair<unsigned long,unsigned long> & samples, bool allPixels=false);
+
+  
+  /** Deburst metadata if possible and prepare the burst concatenation */	
+  bool DeburstAndConcatenate(std::vector<std::pair<unsigned long, unsigned long> > & linesBursts,
+			     std::vector<std::pair<unsigned long,unsigned long> > & samplesBursts);
+
 
   /** Transform world point (lat,lon,hgt) to input image point
   (col,row) and YZ frame */
diff --git a/Modules/Adapters/OSSIMAdapters/src/otbSarSensorModelAdapter.cxx b/Modules/Adapters/OSSIMAdapters/src/otbSarSensorModelAdapter.cxx
index 5e351bea4b17591fcb9a55966878836dabf46c2e..35517a83805cc9eb4f29dc8d2b629905f247d874 100644
--- a/Modules/Adapters/OSSIMAdapters/src/otbSarSensorModelAdapter.cxx
+++ b/Modules/Adapters/OSSIMAdapters/src/otbSarSensorModelAdapter.cxx
@@ -89,11 +89,37 @@ bool SarSensorModelAdapter::IsValidSensorModel() const
   return m_SensorModel.get() != nullptr;
 }
 
-bool SarSensorModelAdapter::Deburst(std::vector<std::pair<unsigned long, unsigned long> > & lines)
+bool SarSensorModelAdapter::Deburst(std::vector<std::pair<unsigned long, unsigned long> > & lines,
+				      std::pair<unsigned long,unsigned long> & samples, 
+				      bool onlyValidSample)
 {
   if(m_SensorModel.get() != nullptr)
     {
-    return m_SensorModel->deburst(lines);
+      return m_SensorModel->deburst(lines, samples, onlyValidSample);
+    }
+  
+  return false;
+}
+
+bool SarSensorModelAdapter::BurstExtraction(const unsigned int burst_index, 
+					    std::pair<unsigned long,unsigned long> & lines, 
+					    std::pair<unsigned long,unsigned long> & samples, bool allPixels)
+{
+   if(m_SensorModel.get())
+    {
+      return m_SensorModel->burstExtraction(burst_index, lines, samples, allPixels);
+    }
+
+   return false;
+}
+
+bool 
+SarSensorModelAdapter::DeburstAndConcatenate(std::vector<std::pair<unsigned long, unsigned long> > & linesBursts,
+					     std::vector<std::pair<unsigned long,unsigned long> >& samplesBursts)
+{
+  if(m_SensorModel.get())
+    {
+      return m_SensorModel->deburstAndConcatenate(linesBursts, samplesBursts);
     }
   
   return false;
diff --git a/Modules/Adapters/OSSIMAdapters/test/otbSarSensorModelAdapterTest.cxx b/Modules/Adapters/OSSIMAdapters/test/otbSarSensorModelAdapterTest.cxx
index 6f29a60ef2f2c5d19f41e5683ecbf4faff8a7484..734c55ce3b98d9e50a4631547e24edda0783083c 100644
--- a/Modules/Adapters/OSSIMAdapters/test/otbSarSensorModelAdapterTest.cxx
+++ b/Modules/Adapters/OSSIMAdapters/test/otbSarSensorModelAdapterTest.cxx
@@ -43,7 +43,8 @@ int otbSarSensorModelAdapterTest(int itkNotUsed(argc), char* argv[])
     }
 
   std::vector<std::pair<unsigned long, unsigned long> > lines;
-  success = sensorModel->Deburst(lines);
+  std::pair<unsigned long, unsigned long> samples;
+  success = sensorModel->Deburst(lines, samples);
 
   if(!success)
     {
diff --git a/Modules/Applications/AppClassification/app/otbComputeConfusionMatrix.cxx b/Modules/Applications/AppClassification/app/otbComputeConfusionMatrix.cxx
index da9a2e3c48c9d2f36d40fdca08f05bcb26dd27f5..f2a87a11617a8d47812153f7285047b133eb7094 100644
--- a/Modules/Applications/AppClassification/app/otbComputeConfusionMatrix.cxx
+++ b/Modules/Applications/AppClassification/app/otbComputeConfusionMatrix.cxx
@@ -204,7 +204,7 @@ private:
         
         OGRFieldType fieldType = feature.ogr().GetFieldDefnRef(iField)->GetType();
         
-        if(fieldType == OFTString || fieldType == OFTInteger || ogr::version_proxy::IsOFTInteger64(fieldType))
+        if(fieldType == OFTString || fieldType == OFTInteger || fieldType == OFTInteger64)
           {
           std::string tmpKey="ref.vector.field."+key.substr(0, end - key.begin());
           AddChoice(tmpKey,item);
diff --git a/Modules/Applications/AppClassification/app/otbImageClassifier.cxx b/Modules/Applications/AppClassification/app/otbImageClassifier.cxx
index e05dcc1964584268ebe1b6318b907cd6188462db..49bae7fd69dcbb466437cef0c0f86c2bc1b9f4bf 100644
--- a/Modules/Applications/AppClassification/app/otbImageClassifier.cxx
+++ b/Modules/Applications/AppClassification/app/otbImageClassifier.cxx
@@ -64,6 +64,7 @@ public:
   typedef ClassificationFilterType::LabelType                                                  LabelType;
   typedef otb::MachineLearningModelFactory<ValueType, LabelType>                               MachineLearningModelFactoryType;
   typedef ClassificationFilterType::ConfidenceImageType                                        ConfidenceImageType;
+  typedef ClassificationFilterType::ProbaImageType                                             ProbaImageType;
 
 protected:
 
@@ -111,6 +112,7 @@ private:
     SetDefaultParameterInt("nodatalabel", 0);
     MandatoryOff("nodatalabel");
 
+   
     AddParameter(ParameterType_OutputImage, "out",  "Output Image");
     SetParameterDescription( "out", "Output image containing class labels");
     SetDefaultOutputPixelType( "out", ImagePixelType_uint8);
@@ -129,8 +131,16 @@ private:
     SetDefaultOutputPixelType( "confmap", ImagePixelType_double);
     MandatoryOff("confmap");
 
+    AddParameter(ParameterType_OutputImage,"probamap", "Probability map");
+    SetParameterDescription("probamap","Probability of each class for each pixel. This is an image having a number of bands equal to the number of classes in the model. This is only implemented for the Shark Random Forest classifier at this point.");
+    SetDefaultOutputPixelType("probamap",ImagePixelType_uint16);
+    MandatoryOff("probamap");
     AddRAMParameter();
 
+    AddParameter(ParameterType_Int, "nbclasses", "Number of classes in the model");
+    SetDefaultParameterInt("nbclasses", 20);
+    SetParameterDescription("nbclasses","The number of classes is needed for the probamap output in order to set the number of output bands.");
+   
    // Doc example parameter settings
     SetDocExampleParameterValue("in", "QB_1_ortho.tif");
     SetDocExampleParameterValue("imstat", "EstimateImageStatisticsQB1.xml");
@@ -173,7 +183,7 @@ private:
     // Classify
     m_ClassificationFilter = ClassificationFilterType::New();
     m_ClassificationFilter->SetModel(m_Model);
-
+    
     m_ClassificationFilter->SetDefaultLabel(GetParameterInt("nodatalabel"));
 
     // Normalize input image if asked
@@ -208,9 +218,9 @@ private:
 
       m_ClassificationFilter->SetInputMask(inMask);
       }
-
     SetParameterOutputImage<OutputImageType>("out", m_ClassificationFilter->GetOutput());
-
+   
+    
     // output confidence map
     if (IsParameterEnabled("confmap") && HasValue("confmap"))
       {
@@ -225,6 +235,21 @@ private:
         this->DisableParameter("confmap");
         }
       }
+    if(IsParameterEnabled("probamap") && HasValue("probamap"))
+      {
+      m_ClassificationFilter->SetUseProbaMap(true);
+      if(m_Model->HasProbaIndex())
+	{
+	  m_ClassificationFilter->SetNumberOfClasses(GetParameterInt("nbclasses"));
+	  SetParameterOutputImage<ProbaImageType>("probamap",m_ClassificationFilter->GetOutputProba());
+	}
+      else
+	{
+	  otbAppLogWARNING("Probability map requested but the classifier doesn't support it!");
+	  this->DisableParameter("probamap");
+	}
+      }
+    
   }
 
   ClassificationFilterType::Pointer m_ClassificationFilter;
diff --git a/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx b/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx
index 4dd494df258f41328bd48fa0b959a40923670fb9..2134db123a5fbff6425004aec2bb19aba0722dca 100644
--- a/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx
+++ b/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx
@@ -148,7 +148,7 @@ private:
         
         OGRFieldType fieldType = feature.ogr().GetFieldDefnRef(iField)->GetType();
         
-        if(fieldType == OFTString || fieldType == OFTInteger || ogr::version_proxy::IsOFTInteger64(fieldType))
+        if(fieldType == OFTString || fieldType == OFTInteger || fieldType == OFTInteger64)
           {
           std::string tmpKey="field."+key.substr(0, end - key.begin());
           AddChoice(tmpKey,item);
diff --git a/Modules/Applications/AppClassification/app/otbSampleAugmentation.cxx b/Modules/Applications/AppClassification/app/otbSampleAugmentation.cxx
index e36e22b8b2e97f0291559ef5a1a2d6b7a2fcaafb..dd6e4b67a9fe04dab5679965cde7b6df5a42d4aa 100644
--- a/Modules/Applications/AppClassification/app/otbSampleAugmentation.cxx
+++ b/Modules/Applications/AppClassification/app/otbSampleAugmentation.cxx
@@ -167,7 +167,7 @@ private:
         
         OGRFieldType fieldType = feature.ogr().GetFieldDefnRef(iField)->GetType();
         
-        if(fieldType == OFTString || fieldType == OFTInteger || ogr::version_proxy::IsOFTInteger64(fieldType))
+        if(fieldType == OFTString || fieldType == OFTInteger || fieldType == OFTInteger64)
           {
           std::string tmpKey="field."+key.substr(0, end - key.begin());
           AddChoice(tmpKey,item);
diff --git a/Modules/Applications/AppClassification/app/otbSampleExtraction.cxx b/Modules/Applications/AppClassification/app/otbSampleExtraction.cxx
index 2c48308344b02b27744c3c362a07603ceb348c47..9a0741d46cbc81ed060d9d8a06d3dad85a32a6c9 100644
--- a/Modules/Applications/AppClassification/app/otbSampleExtraction.cxx
+++ b/Modules/Applications/AppClassification/app/otbSampleExtraction.cxx
@@ -140,7 +140,7 @@ private:
         
         OGRFieldType fieldType = feature.ogr().GetFieldDefnRef(iField)->GetType();
         
-        if(fieldType == OFTString || fieldType == OFTInteger || ogr::version_proxy::IsOFTInteger64(fieldType))
+        if(fieldType == OFTString || fieldType == OFTInteger || fieldType == OFTInteger64)
           {
           std::string tmpKey="field."+key.substr(0, end - key.begin());
           AddChoice(tmpKey,item);
diff --git a/Modules/Applications/AppClassification/app/otbSampleSelection.cxx b/Modules/Applications/AppClassification/app/otbSampleSelection.cxx
index 531203f01ad2bb64c651c860831728e496193bdd..823a95d70eba2ba067437e777bafe420eaefa946 100644
--- a/Modules/Applications/AppClassification/app/otbSampleSelection.cxx
+++ b/Modules/Applications/AppClassification/app/otbSampleSelection.cxx
@@ -248,7 +248,7 @@ private:
         
         OGRFieldType fieldType = feature.ogr().GetFieldDefnRef(iField)->GetType();
         
-        if(fieldType == OFTString || fieldType == OFTInteger || ogr::version_proxy::IsOFTInteger64(fieldType))
+        if(fieldType == OFTString || fieldType == OFTInteger || fieldType == OFTInteger64)
           {
           std::string tmpKey="field."+key.substr(0, end - key.begin());
           AddChoice(tmpKey,item);
diff --git a/Modules/Applications/AppClassification/app/otbVectorClassifier.cxx b/Modules/Applications/AppClassification/app/otbVectorClassifier.cxx
index 286b6b0dd7d6cf89f55e9c942d73df988dbe7114..d101d983de3410bb1d347e9f03888ff30fe995dd 100644
--- a/Modules/Applications/AppClassification/app/otbVectorClassifier.cxx
+++ b/Modules/Applications/AppClassification/app/otbVectorClassifier.cxx
@@ -183,7 +183,7 @@ private:
         std::transform(key.begin(), key.end(), key.begin(), tolower);
 
         OGRFieldType fieldType = layerDefn.GetFieldDefn(iField)->GetType();
-        if(fieldType == OFTInteger ||  ogr::version_proxy::IsOFTInteger64(fieldType) || fieldType == OFTReal)
+        if(fieldType == OFTInteger ||  fieldType == OFTInteger64 || fieldType == OFTReal)
           {
           std::string tmpKey="feat."+key;
           AddChoice(tmpKey,item);
diff --git a/Modules/Applications/AppClassification/include/otbTrainVectorBase.hxx b/Modules/Applications/AppClassification/include/otbTrainVectorBase.hxx
index 588e07ae8a51d609aedd7f9834ca10ff029c26a5..3b4fcd115491e0ffd231e0f809cc624cbea949c7 100644
--- a/Modules/Applications/AppClassification/include/otbTrainVectorBase.hxx
+++ b/Modules/Applications/AppClassification/include/otbTrainVectorBase.hxx
@@ -131,12 +131,12 @@ void TrainVectorBase::DoUpdateParameters()
 
       OGRFieldType fieldType = feature.ogr().GetFieldDefnRef( iField )->GetType();
 
-      if( fieldType == OFTInteger || ogr::version_proxy::IsOFTInteger64( fieldType ) || fieldType == OFTReal )
+      if( fieldType == OFTInteger || fieldType == OFTInteger64 || fieldType == OFTReal )
         {
         std::string tmpKey = "feat." + key.substr( 0, static_cast<unsigned long>( end - key.begin() ) );
         AddChoice( tmpKey, item );
         }
-      if( fieldType == OFTString || fieldType == OFTInteger || ogr::version_proxy::IsOFTInteger64( fieldType ) )
+      if( fieldType == OFTString || fieldType == OFTInteger || fieldType == OFTInteger64 )
         {
         std::string tmpKey = "cfield." + key.substr( 0, static_cast<unsigned long>( end - key.begin() ) );
         AddChoice( tmpKey, item );
diff --git a/Modules/Applications/AppClassification/test/CMakeLists.txt b/Modules/Applications/AppClassification/test/CMakeLists.txt
index 46f4e82dcf3142883cd94d7508458647dd02c47a..13db483c00d9fe033a0b7b7f531abdb1df5a6fe7 100644
--- a/Modules/Applications/AppClassification/test/CMakeLists.txt
+++ b/Modules/Applications/AppClassification/test/CMakeLists.txt
@@ -115,6 +115,7 @@ set(sharkkm_parameters "")
 set(ascii_comparison --compare-ascii ${EPSILON_6})
 set(raster_comparison --compare-image ${NOTOL})
 set(raster_comparison_two --compare-n-images ${NOTOL} 2)
+set(raster_comparison_three --compare-n-images ${NOTOL} 3)
 
 # Reference ffiles depending on modes
 set(ascii_ref_path ${OTBAPP_BASELINE_FILES})
@@ -136,6 +137,7 @@ if(OTB_USE_SHARK)
 endif()
 
 set(classifier_with_confmap "LIBSVM" "BOOST" "KNN" "ANN" "RF")
+set(classifier_with_probamap "SHARKRF")
 
 # This is a black list for classifier that can not have a baseline
 # because they are using randomness and seed can not be set
@@ -156,6 +158,7 @@ foreach(classifier ${classifierList})
 
   set(OUTRASTER cl${classifier}LabeledImageQB1${raster_output_format})
   set(OUTCONFMAP cl${classifier}ConfidenceMapQB1${raster_output_format})
+  set(OUTPROBAMAP cl${classifier}ProbabilityMapQB1${raster_output_format})
 
   list(FIND classifier_without_baseline ${classifier} _classifier_has_baseline)
   if(${_classifier_has_baseline} EQUAL -1)
@@ -198,6 +201,7 @@ foreach(classifier ${classifierList})
   set_tests_properties(apTvClTrainMethod${classifier}ImagesClassifierQB1_InXML1 PROPERTIES DEPENDS apTvClTrainMethod${classifier}ImagesClassifierQB1)
 
   list(FIND classifier_with_confmap ${classifier} _classifier_has_confmap)
+  list(FIND classifier_with_probamap ${classifier} _classifier_has_probamap)
   if(${_classifier_has_confmap} EQUAL -1)
     otb_test_application(
       NAME     apTvClMethod${classifier}ImageClassifierQB1
@@ -212,21 +216,44 @@ foreach(classifier ${classifierList})
       ${TEMP}/${OUTRASTER}
     )
   else()
-    otb_test_application(
-      NAME     apTvClMethod${classifier}ImageClassifierQB1
-      APP      ImageClassifier
-      OPTIONS  -in ${INPUTDATA}/Classification/QB_1_ortho${raster_input_format}
-      -model ${INPUTDATA}/Classification/${OUTMODELFILE}
-      -imstat ${INPUTDATA}/Classification/clImageStatisticsQB1${stat_input_format}
-      -out ${TEMP}/${OUTRASTER} ${raster_output_option}
-      -confmap ${TEMP}/${OUTCONFMAP}
-
-      VALID    ${raster_comparison_two}
-      ${raster_ref_path}/${OUTRASTER}
-      ${TEMP}/${OUTRASTER}
-      ${raster_ref_path}/${OUTCONFMAP}
-      ${TEMP}/${OUTCONFMAP}
-    )
+    if(${_classifier_has_probamap} EQUAL -1)
+      otb_test_application(
+        NAME     apTvClMethod${classifier}ImageClassifierQB1
+        APP      ImageClassifier
+        OPTIONS  -in ${INPUTDATA}/Classification/QB_1_ortho${raster_input_format}
+        -model ${INPUTDATA}/Classification/${OUTMODELFILE}
+        -imstat ${INPUTDATA}/Classification/clImageStatisticsQB1${stat_input_format}
+        -out ${TEMP}/${OUTRASTER} ${raster_output_option}
+        -confmap ${TEMP}/${OUTCONFMAP}
+
+        VALID    ${raster_comparison_two}
+        ${raster_ref_path}/${OUTRASTER}
+        ${TEMP}/${OUTRASTER}
+        ${raster_ref_path}/${OUTCONFMAP}
+        ${TEMP}/${OUTCONFMAP}
+        )
+    else()
+      message(${classifier})
+      otb_test_application(
+        NAME     apTvClMethod${classifier}ImageClassifierQB1
+        APP      ImageClassifier
+        OPTIONS  -in ${INPUTDATA}/Classification/QB_1_ortho${raster_input_format}
+        -model ${INPUTDATA}/Classification/${OUTMODELFILE}
+        -imstat ${INPUTDATA}/Classification/clImageStatisticsQB1${stat_input_format}
+        -out ${TEMP}/${OUTRASTER} ${raster_output_option}
+        -confmap ${TEMP}/${OUTCONFMAP}
+        -nbclasses 4
+        -probamap ${TEMP}/${OUTPROBAMAP}
+
+        VALID    ${raster_comparison_three}
+        ${raster_ref_path}/${OUTRASTER}
+        ${TEMP}/${OUTRASTER}
+        ${raster_ref_path}/${OUTCONFMAP}
+        ${TEMP}/${OUTCONFMAP}
+        ${raster_ref_path}/${OUTPROBAMAP}
+        ${TEMP}/${OUTPROBAMAP}
+        )
+    endif()
   endif()
 
 endforeach()
diff --git a/Modules/Applications/AppFusion/app/otbPansharpening.cxx b/Modules/Applications/AppFusion/app/otbPansharpening.cxx
index fda0827b4f9b2e1ce06b91c22de6607540572aed..8e6cf20f0cd8cf8f2325ec2c9169caaf7bdaf25f 100644
--- a/Modules/Applications/AppFusion/app/otbPansharpening.cxx
+++ b/Modules/Applications/AppFusion/app/otbPansharpening.cxx
@@ -53,8 +53,6 @@ public:
   typedef itk::SmartPointer<Self>       Pointer;
   typedef itk::SmartPointer<const Self> ConstPointer;
 
-  typedef itk::ImageToImageFilter<FloatVectorImageType, FloatVectorImageType> FusionFilterType;
-
   typedef otb::SimpleRcsPanSharpeningFusionImageFilter<FloatImageType, FloatVectorImageType, FloatVectorImageType> SimpleRCSFilterType;
 
   typedef otb::LmvmPanSharpeningFusionImageFilter
@@ -176,7 +174,9 @@ private:
 
       filter->UpdateOutputInformation();
       otbAppLogINFO( << "Simple RCS algorithm" );
-      m_FusionFilter = filter;
+      m_Ref.push_back(filter.GetPointer());
+      SetParameterOutputImage("out", filter->GetOutput());
+
       break;
       }
       case 1:
@@ -203,8 +203,9 @@ private:
       filter->UpdateOutputInformation();
 
       otbAppLogINFO( << "Lmvm algorithm" );
+      m_Ref.push_back(filter.GetPointer());
+      SetParameterOutputImage("out", filter->GetOutput());
 
-      m_FusionFilter = filter;
       break;
       }
       case 2:
@@ -224,7 +225,9 @@ private:
 
       filter->UpdateOutputInformation();
       otbAppLogINFO( << "Bayesian fusion algorithm" );
-      m_FusionFilter = filter;
+
+      m_Ref.push_back(filter.GetPointer());
+      SetParameterOutputImage("out", filter->GetOutput());
 
       break;
       }
@@ -236,12 +239,9 @@ private:
       }
       return;
       }
-
-    SetParameterOutputImage("out", m_FusionFilter->GetOutput());
   }
 
   std::vector<itk::ProcessObject::Pointer> m_Ref;
-  FusionFilterType::Pointer m_FusionFilter;
 };
 }
 }
diff --git a/Modules/Applications/AppMorphology/app/otbMorphologicalProfilesAnalysis.cxx b/Modules/Applications/AppMorphology/app/otbMorphologicalProfilesAnalysis.cxx
index ae3c31abac736608f76fd892662613504159dfb8..6946103d3c926b7d564994f494691714575e7032 100644
--- a/Modules/Applications/AppMorphology/app/otbMorphologicalProfilesAnalysis.cxx
+++ b/Modules/Applications/AppMorphology/app/otbMorphologicalProfilesAnalysis.cxx
@@ -270,12 +270,13 @@ private:
       }
 
     classificationFilter = MultiScaleClassificationFilterType::New();
-    classificationFilter->SetOpeningProfileDerivativeMaxima( omsCharFilter->GetOutput() );
-    classificationFilter->SetOpeningProfileCharacteristics( omsCharFilter->GetOutputCharacteristics() );
-    classificationFilter->SetClosingProfileDerivativeMaxima( cmsCharFilter->GetOutput() );
-    classificationFilter->SetClosingProfileCharacteristics( cmsCharFilter->GetOutputCharacteristics() );
-    classificationFilter->SetSigma( sigma );
-    classificationFilter->SetLabelSeparator( static_cast<unsigned short>(initValue + profileSize * step) );
+    using namespace Functor::MultiScaleConvexOrConcaveDecisionRule_tags;
+    classificationFilter->SetVariadicNamedInput<max_opening_profile_derivative>( omsCharFilter->GetOutput() );
+    classificationFilter->SetVariadicNamedInput<opening_profile_characteristics>( omsCharFilter->GetOutputCharacteristics() );
+    classificationFilter->SetVariadicNamedInput<max_closing_profile_derivative>( cmsCharFilter->GetOutput() );
+    classificationFilter->SetVariadicNamedInput<closing_profile_characteristics>( cmsCharFilter->GetOutputCharacteristics() );
+    classificationFilter->GetModifiableFunctor().SetSigma( sigma );
+    classificationFilter->GetModifiableFunctor().SetLabelSeparator( static_cast<unsigned short>(initValue + profileSize * step) );
     AddProcess(classificationFilter, "Classification");
     classificationFilter->Update();
     SetParameterOutputImage( "out", classificationFilter->GetOutput() );
diff --git a/Modules/Applications/AppSARCalibration/app/CMakeLists.txt b/Modules/Applications/AppSARCalibration/app/CMakeLists.txt
index 4360104d2a87f0b4995f15c2a36fde004f786096..5e518e169a3da8497098a5a68716b8746f7d0312 100644
--- a/Modules/Applications/AppSARCalibration/app/CMakeLists.txt
+++ b/Modules/Applications/AppSARCalibration/app/CMakeLists.txt
@@ -27,3 +27,13 @@ otb_create_application(
   NAME           SARDeburst
   SOURCES        otbSARDeburst.cxx
   LINK_LIBRARIES ${${otb-module}_LIBRARIES})
+
+otb_create_application(
+  NAME           SARBurstExtraction
+  SOURCES        otbSARBurstExtraction.cxx
+  LINK_LIBRARIES ${${otb-module}_LIBRARIES})
+
+otb_create_application(
+  NAME           SARConcatenateBursts
+  SOURCES        otbSARConcatenateBursts.cxx
+  LINK_LIBRARIES ${${otb-module}_LIBRARIES})
diff --git a/Modules/Applications/AppSARCalibration/app/otbSARBurstExtraction.cxx b/Modules/Applications/AppSARCalibration/app/otbSARBurstExtraction.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..36082b796fe59fa58e353cc0ad057c2280f99fb1
--- /dev/null
+++ b/Modules/Applications/AppSARCalibration/app/otbSARBurstExtraction.cxx
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "otbWrapperApplication.h"
+#include "otbWrapperApplicationFactory.h"
+
+#include "otbSarBurstExtractionImageFilter.h"
+
+namespace otb
+{
+namespace Wrapper
+{
+class SARBurstExtraction : public Application
+{
+public:
+  /** Standard class typedefs. */
+  typedef SARBurstExtraction     Self;
+  typedef Application                   Superclass;
+  typedef itk::SmartPointer<Self>       Pointer;
+  typedef itk::SmartPointer<const Self> ConstPointer;
+
+  /** Standard macro */
+  itkNewMacro(Self);
+
+  itkTypeMacro(SARBurstExtraction, otb::Application);
+
+  typedef otb::SarBurstExtractionImageFilter<FloatVectorImageType>     BurstExtractionFilterType;
+
+private:
+  void DoInit() override
+  {
+    SetName("SARBurstExtraction");
+    SetDescription("This application performs a burst extraction by keeping only lines and samples of a required burst.");
+
+    // Documentation
+    SetDocName("SAR Burst Extraction");
+    SetDocLongDescription("Sentinel1 IW SLC products are composed of several burst overlapping in"
+                          " azimuth time for each subswath, separated by black lines [1]. The burst"
+                          " extraction consist in extracting a single burst, by selecting only lines" 
+			  " and samples of the wanted burst.\n\n"
+                          
+                          "Note that the output sensor model is updated accordingly. This burst"
+                          " extraction is the perfect preprocessing step for S1 IW SLC"
+                          " product with OTB without suffering from artifacts caused by"
+                          " bursts separation\n."
+			  
+			   "Two modes are available for the output image : with all pixels and"
+			  "with only valid pixels ");
+    
+    SetDocLimitations("Only Sentinel1 IW SLC products are supported for now. Processing of"
+                      " other Sentinel1 modes or TerrasarX images will result in no changes in"
+                      " the image and metadata. Images from other sensors will lead to an"
+                      " error."
+		      " Burst extraction needs as inputs a image composed of several Bursts. A burst has to "
+		      " contain all its lines in order to have a correct extraction. "
+		      " ie : Careful with ROI.");
+    
+    SetDocAuthors("OTB-Team");
+    SetDocSeeAlso("[1] Sentinel1 User Handbook, p. 52: https://sentinel.esa.int/documents/247904/685163/Sentinel-1_User_Handbook\n");
+
+    AddDocTag(Tags::SAR);
+    AddDocTag(Tags::Calibration);
+
+    AddParameter(ParameterType_InputImage,  "in", "Input Sentinel1 IW SLC Image");
+    SetParameterDescription("in", "Raw Sentinel1 IW SLC image, or any extract of such made by OTB (geom file needed)");
+
+    AddParameter(ParameterType_Int,  "burstindex", "Index of Burst");
+    SetParameterDescription("burstindex", "Index for the required Burst (By default -1). If this parameter remains at -1, all bursts will be extracted");
+    MandatoryOff("burstindex");
+    SetDefaultParameterInt("burstindex", -1);
+
+    AddParameter(ParameterType_OutputImage,  "out", "Output Image");
+    SetParameterDescription("out", "The output filename will be used to get the prefix "
+			    "and the extension of thise output written's image. For example with outimage.tif as"
+			    "output filename, the generated images will had an indice (corresponding at each "
+			    "burst) between the prefix and the extension, such as: outimage_Burst0.tif and "
+			    "outimage_Burst1.tif (if 2 bursts).");
+
+    AddParameter(ParameterType_Bool, "allpixels", "Select the modes for output image");
+    SetParameterDescription("allpixels", "If true, all pixels of the current burst are selected.");
+
+    AddRAMParameter();
+
+    SetDocExampleParameterValue("in","s1_iw_slc.tif");
+    SetDocExampleParameterValue("out","s1_iw_slc_burst0.tif");
+
+    SetOfficialDocLink();
+  }
+
+  void DoUpdateParameters() override
+  {}
+
+  void DoExecute() override
+  {
+    // Get the input complex image
+    FloatVectorImageType*  in = GetParameterImage("in");
+
+    // Get the Burst index 
+    int burst_index = GetParameterInt("burstindex"); // If -1 or > nb_Bursts => all bursts will be extracted
+    
+
+    // Get the path/fileWithoutextension/extension of the output images filename
+    std::string ofname = GetParameterString("out");
+
+    // Get the extension and the prefix of the filename
+    const std::string path  = itksys::SystemTools::GetFilenamePath(ofname);
+    const std::string fname = itksys::SystemTools::GetFilenameWithoutExtension(ofname);
+    const std::string ext   = itksys::SystemTools::GetFilenameExtension(ofname);
+
+    // Set the filer input
+    m_BurstExtractionFilter = BurstExtractionFilterType::New();
+    m_BurstExtractionFilter->SetInput(in);
+
+    if (IsParameterEnabled("allpixels"))
+      {
+	m_BurstExtractionFilter->SetAllPixels(true);
+      }
+
+    // Get the number of Bursts
+    unsigned int nbBursts = 1;
+    try
+      {
+	nbBursts = std::stoi(in->GetImageKeywordlist().GetMetadataByKey("support_data.geom.bursts.number"));
+      }
+    catch( ... )
+      {
+	// Throw an execption
+	otbAppLogFATAL(<<"Failed to retrieve bursts.number value from .geom file.");
+      }
+      
+    const bool extractAll = burst_index <= -1 || burst_index >= static_cast<int>(nbBursts);
+    
+    // Extract burst index only
+    if (! extractAll)
+      {
+	// Set the burst index
+	m_BurstExtractionFilter->SetBurstIndex(burst_index);
+	
+	SetParameterOutputImage("out", m_BurstExtractionFilter->GetOutput());
+	
+      }
+    // Extract all bursts
+    else
+      {	
+	for (unsigned int i = 0; i < nbBursts; ++i)
+	  {
+	    // Set the burst index
+	    m_BurstExtractionFilter->SetBurstIndex(i);
+
+	    // Build the current output filename
+	    std::ostringstream oss;
+	    if (!path.empty())
+	      {
+		oss <<path<<"/";
+	      }
+	    oss <<fname<<"_burst"<<i<<ext;
+
+	    // Create an output parameter to write the current output image
+	    OutputImageParameter::Pointer paramOut = OutputImageParameter::New();
+
+	    // Writer label
+	    std::ostringstream osswriter;
+	    osswriter<< "writer (Burst : "<< i<<")";
+
+	    // Set the filename of the current output image
+	    paramOut->SetFileName(oss.str());
+	    otbAppLogINFO(<< "File: "<<paramOut->GetFileName() << " will be written.");
+	    paramOut->SetValue(m_BurstExtractionFilter->GetOutput());
+	    paramOut->SetPixelType(this->GetParameterOutputImagePixelType("out"));
+	    // Add the current level to be written
+	    paramOut->InitializeWriters();
+	    AddProcess(paramOut->GetWriter(), osswriter.str());
+	    paramOut->Write();
+	  }
+
+	// Disable the output Image parameter to avoid writing
+	// the last image (Application::ExecuteAndWriteOutput method)
+	DisableParameter("out");
+      }
+    RegisterPipeline();
+  }
+
+  BurstExtractionFilterType::Pointer   m_BurstExtractionFilter;
+
+};
+}
+}
+
+OTB_APPLICATION_EXPORT(otb::Wrapper::SARBurstExtraction)
diff --git a/Modules/Applications/AppSARCalibration/app/otbSARConcatenateBursts.cxx b/Modules/Applications/AppSARCalibration/app/otbSARConcatenateBursts.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..580311fb41493b401c76c68c7a2f8e2157a128c4
--- /dev/null
+++ b/Modules/Applications/AppSARCalibration/app/otbSARConcatenateBursts.cxx
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "otbWrapperApplication.h"
+#include "otbWrapperApplicationFactory.h"
+
+#include "otbMultiChannelExtractROI.h"
+#include "otbImageList.h"
+
+#include "otbSarConcatenateBurstsImageFilter.h"
+
+namespace otb
+{
+namespace Wrapper
+{
+class SARConcatenateBursts : public Application
+{
+public:
+  /** Standard class typedefs. */
+  typedef SARConcatenateBursts     Self;
+  typedef Application                   Superclass;
+  typedef itk::SmartPointer<Self>       Pointer;
+  typedef itk::SmartPointer<const Self> ConstPointer;
+
+  /** Standard macro */
+  itkNewMacro(Self);
+
+  itkTypeMacro(SARConcatenateBursts, otb::Application);
+
+  typedef otb::ImageList<FloatVectorImageType>  ImageListType;
+  typedef MultiChannelExtractROI<FloatVectorImageType::InternalPixelType,
+				 FloatVectorImageType::InternalPixelType>       ExtractROIFilterType;
+  typedef ObjectList<ExtractROIFilterType>                                      ExtractROIFilterListType;
+ 
+  typedef otb::SarConcatenateBurstsImageFilter<FloatVectorImageType> BurstFusionFilterType;
+
+private:
+  void DoInit() override
+  {
+    SetName("SARConcatenateBursts");
+    SetDescription("Concatenate a list of Bursts to provide a whole SAR Deburst Image.");
+
+    // Documentation
+    SetDocName("SAR Concatenate Bursts");
+    SetDocLongDescription("This application performs a burst concatenation and provides a SAR Deburst Image. "
+			  "It reads the input image list (single bursts) "
+			  "and generates a whole SAR image with deburst operations.");
+    SetDocLimitations("Only Sentinel1 IW SLC products are supported for now. In order to concatenate several" 
+		      " bursts, all valid lines of each burst are required as inputs." 
+		      "ie : Careful with ROI extraction inside a Burst.");
+    SetDocAuthors("OTB-Team");
+
+    AddDocTag(Tags::SAR);
+    AddDocTag(Tags::Calibration);
+    
+    AddParameter(ParameterType_InputImageList,  "il",   "Input bursts list");
+    SetParameterDescription("il", "The list of bursts to concatenate.");
+
+    AddParameter(ParameterType_InputImage,  "insar",   "Input Sentinel1 IW SLC Image (only metadata used)");
+    SetParameterDescription("insar", "Raw Sentinel1 IW SLC image, or any extract of such made by OTB (geom file needed).");
+
+    AddParameter(ParameterType_OutputImage, "out",  "Output Image");
+    SetParameterDescription("out", "The concatenated and debursted output image.");
+
+    AddRAMParameter();
+
+    // Doc example parameter settings
+    SetDocExampleParameterValue("in","s1_iw_slc.tif");
+    SetDocExampleParameterValue("il", "Burst0.png Burst1.png");
+    SetDocExampleParameterValue("out", "otbConcatenateBursts.tif");
+
+    SetOfficialDocLink();
+  }
+
+  void DoUpdateParameters() override
+  {}
+
+  void DoExecute() override
+  {
+    // Instanciate filters
+    ExtractROIFilterListType::Pointer m_ExtractorList = ExtractROIFilterListType::New();
+    ImageListType::Pointer m_ImageList = ImageListType::New();
+    BurstFusionFilterType::Pointer fusionFilter = BurstFusionFilterType::New();
+    
+    // Get the input complex image list
+    FloatVectorImageListType*  inList = GetParameterImageList("il");
+    // Get the input complex image
+    FloatVectorImageType*  in = GetParameterImage("insar");
+    in->UpdateOutputInformation();
+
+    std::vector<std::pair<unsigned long,unsigned long> > lines;
+    std::vector<std::pair<unsigned long,unsigned long> > samples;
+
+    // Check number of inputs with number of bursts into SLC image (must be the same)
+    unsigned int nbBursts = 1;
+    try
+      {
+	nbBursts = std::stoi(in->GetImageKeywordlist().GetMetadataByKey("support_data.geom.bursts.number"));
+      }
+    catch( ... )
+      {
+	// Throw an execption
+	throw std::runtime_error("Failed to retrieve bursts.number value from .geom file.");
+      }
+
+    nbBursts = inList->Size();
+    
+    /*if (inList->Size() != nbBursts)
+      {
+	throw std::runtime_error("Failed to concatenate bursts. Some bursts are missing.");
+	}*/ 
+
+    // Coniguration for fusion filter
+    fusionFilter->SetSLCImageKeyWorList(in->GetImageKeywordlist());
+    fusionFilter->getDeburstLinesAndSamples(lines, samples);
+       
+    // Split each input burst to keep only interested region
+    for( unsigned int i=0; i<inList->Size(); i++ )
+      {
+	FloatVectorImageType::Pointer vectIm = inList->GetNthElement(i);
+	vectIm->UpdateOutputInformation();
+
+	unsigned long originOffset_samples = static_cast<long>(vectIm->GetOrigin()[0]-0.5);
+	unsigned long originOffset_lines = static_cast<long>(vectIm->GetOrigin()[1]-0.5);
+
+	// Retrieve start and size for each burst
+	std::pair<unsigned long,unsigned long> line = lines[i];
+	std::pair<unsigned long,unsigned long> sample = samples[i];
+
+	unsigned long minSamples = std::min(sample.second, static_cast<unsigned long>(vectIm->GetLargestPossibleRegion().GetSize()[0]-1));
+	unsigned long minLines = std::min(line.second, static_cast<unsigned long>(vectIm->GetLargestPossibleRegion().GetSize()[1]-1));
+
+	unsigned long startL = line.first - originOffset_lines;
+	unsigned long sizeL = minLines - line.first + 1;
+	unsigned long startS = sample.first - originOffset_samples;
+	unsigned long sizeS = minSamples - sample.first + 1;
+	// Readjust if origin is superior to the first selected line/sample for the current burst
+	if (line.first < originOffset_lines) 
+	  {
+	    startL = 0;
+	    sizeL =  minLines - line.first - originOffset_lines + 1;
+	  }
+	if (sample.first < originOffset_samples) 
+	  {
+	    startS = 0;
+	    sizeS =  minSamples - sample.first - originOffset_samples + 1;
+	  }
+
+	ExtractROIFilterType::Pointer extractor = ExtractROIFilterType::New();
+	extractor->SetInput(vectIm);
+	extractor->SetStartX(startS);
+	extractor->SetStartY(startL);
+	extractor->SetSizeX(sizeS);
+	extractor->SetSizeY(sizeL);
+	extractor->UpdateOutputInformation();
+
+	m_ExtractorList->PushBack( extractor );
+	m_ImageList->PushBack( extractor->GetOutput() );
+	
+      }
+
+    BurstFusionFilterType::SizeType layout;
+    layout[0] = 1;
+    layout[1] = nbBursts;
+    fusionFilter->SetLayout(layout);
+
+    for (unsigned int i=0; i<(layout[0]*layout[1]); i++)
+      {
+	fusionFilter->SetInput(i,m_ImageList->GetNthElement(i));
+      }
+
+    SetParameterOutputImage("out", fusionFilter->GetOutput());
+
+    RegisterPipeline();
+  }
+
+
+};
+}
+}
+
+OTB_APPLICATION_EXPORT(otb::Wrapper::SARConcatenateBursts)
diff --git a/Modules/Applications/AppSARCalibration/app/otbSARDeburst.cxx b/Modules/Applications/AppSARCalibration/app/otbSARDeburst.cxx
index 0858e7e7146997530a067cb32929850e749e06f9..849f91de97313dabacb4533fcd18354c23c7e567 100644
--- a/Modules/Applications/AppSARCalibration/app/otbSARDeburst.cxx
+++ b/Modules/Applications/AppSARCalibration/app/otbSARDeburst.cxx
@@ -60,7 +60,10 @@ private:
                           "Note that the output sensor model is updated accordingly. This deburst"
                           " operation is the perfect preprocessing step to orthorectify S1 IW SLC"
                           " product with OTB [2] without suffering from artifacts caused by"
-                          " bursts separation.");
+                          " bursts separation.\n"
+
+			   "Two modes are available for the output image : with all samples and"
+			  "with only valid samples ");
     
     SetDocLimitations("Only Sentinel1 IW SLC products are supported for now. Processing of"
                       " other Sentinel1 modes or TerrasarX images will result in no changes in"
@@ -80,6 +83,9 @@ private:
     AddParameter(ParameterType_OutputImage,  "out", "Output Image");
     SetParameterDescription("out", "Deburst image, with updated geom file that can be further used by Orthorectification application. If the input image is a raw Sentinel1 product, uint16 output type should be used (encoding of S1 product). Otherwise, output type should match type of input image.");
 
+    AddParameter(ParameterType_Bool, "onlyvalidsamples", "Select the modes for output image");
+    SetParameterDescription("onlyvalidsamples", "If true, the selected mode is with only valid samples.");
+
     AddRAMParameter();
 
     SetDocExampleParameterValue("in","s1_iw_slc.tif");
@@ -100,6 +106,12 @@ private:
     m_DeburstFilter = DeburstFilterType::New();
     m_DeburstFilter->SetInput(in);
 
+    if (IsParameterEnabled("onlyvalidsamples"))
+      {
+	m_DeburstFilter->SetOnlyValidSample(true);
+      }
+     
+
     // Set the output image
     SetParameterOutputImage("out", m_DeburstFilter->GetOutput());
   }
diff --git a/Modules/Applications/AppSARCalibration/test/CMakeLists.txt b/Modules/Applications/AppSARCalibration/test/CMakeLists.txt
index 1ca0afb569f058654d1df161432d920c8eb66df2..eabd2ace9d092b6dea7faf1551f371b78fe67e8d 100644
--- a/Modules/Applications/AppSARCalibration/test/CMakeLists.txt
+++ b/Modules/Applications/AppSARCalibration/test/CMakeLists.txt
@@ -54,3 +54,23 @@ otb_test_application(NAME apTvRaSarDeburst_SENTINEL1
   # Same baseline as filter test
   ${BASELINE}/saTvSarDeburstImageFilterTestOutput.tif
   ${TEMP}/apTvRaSarDeburst_SENTINEL1_output.tif)
+
+otb_test_application(NAME apTvRaSarBurstExtraction_SENTINEL1
+  APP  SARBurstExtraction
+  OPTIONS -in ${INPUTDATA}/s1a-iw1-slc-vv-20170111_Burst01_amp.tiff
+  -out ${TEMP}/apTvRaSarBurstExtraction_SENTINEL1_output.tif uint16
+  -burstindex 0
+  VALID --compare-image ${NOTOL}
+  # Same baseline as filter test
+  ${BASELINE}/apTvRaSarBurstExtraction_SENTINEL1_output.tif
+  ${TEMP}/apTvRaSarBurstExtraction_SENTINEL1_output.tif)
+
+otb_test_application(NAME apTvRaSarConcatenateBursts_SENTINEL1
+  APP  SARConcatenateBursts
+  OPTIONS -il ${INPUTDATA}/s1a-iw1-slc-vv-20170111_Burst0_amp.tif ${INPUTDATA}/s1a-iw1-slc-vv-20170111_Burst1_amp.tif
+  -insar ${INPUTDATA}/s1a-iw1-slc-vv-20170111_Burst01_amp.tiff
+  -out ${TEMP}/apTvRaSarConcatenateBursts_SENTINEL1_output.tif uint16
+  VALID --compare-image ${NOTOL}
+  # Same baseline as filter test
+  ${BASELINE}/apTvRaSarConcatenateBursts_SENTINEL1_output.tif
+  ${TEMP}/apTvRaSarConcatenateBursts_SENTINEL1_output.tif)
diff --git a/Modules/Applications/AppSegmentation/app/otbSegmentation.cxx b/Modules/Applications/AppSegmentation/app/otbSegmentation.cxx
index cbb87ed79d6194b36da369c69a8d7f7548088026..b49467c19ba962aa1c5d97730bd75600084cbf91 100644
--- a/Modules/Applications/AppSegmentation/app/otbSegmentation.cxx
+++ b/Modules/Applications/AppSegmentation/app/otbSegmentation.cxx
@@ -689,7 +689,7 @@ private:
         //Note : the GetDriver() Method has not been encapsulated in otb::ogr::DataSource,
         //so we must access the OGR pointer by using .ogr()
 
-        std::string driverName(otb::ogr::version_proxy::GetDriverNameFromDataSource(&ogrDS->ogr()));
+        std::string driverName(ogrDS->ogr().GetDriverName());
         if ( driverName.find("ESRI Shapefile") != std::string::npos)
           {
           otbAppLogINFO(<<"REPACK the Shapefile ..."<<std::endl);
diff --git a/Modules/Core/Common/otb-module.cmake b/Modules/Core/Common/otb-module.cmake
index b3276d69422b566872290eba6a5d817cb2b45be1..7f1468126675bea77c61e159711239a1a7be2f2d 100644
--- a/Modules/Core/Common/otb-module.cmake
+++ b/Modules/Core/Common/otb-module.cmake
@@ -25,7 +25,6 @@ ENABLE_SHARED
   DEPENDS
     OTBBoost
     OTBITK
-    #Add dependency to OTBGDAL as GDAL module need to set OTB_USE_GDAL_20 before configuring otbConfigure.h
     OTBGDAL
     #Add dependency for extended filename helper class
     OTBBoostAdapters
diff --git a/Modules/Core/Common/src/otbConfigure.h.in b/Modules/Core/Common/src/otbConfigure.h.in
index 2146cf15bffa6fdb90e30c766a9f3f483263944e..f93fa266c56946791f42aa09e7d8bb63a14fe62a 100644
--- a/Modules/Core/Common/src/otbConfigure.h.in
+++ b/Modules/Core/Common/src/otbConfigure.h.in
@@ -27,8 +27,6 @@
 
 #cmakedefine OTB_BUILD_SHARED_LIBS
 
-#cmakedefine OTB_USE_GDAL_20
-
 #cmakedefine OTB_USE_OPENMP
 
 #cmakedefine OTB_USE_SSE_FLAGS
diff --git a/Modules/Core/ComplexImage/otb-module.cmake b/Modules/Core/ComplexImage/otb-module.cmake
index e80b01956289abbc6985352d0443a940be8f02eb..6b31ea5c698119698c90a82ed83688f24c432a2c 100644
--- a/Modules/Core/ComplexImage/otb-module.cmake
+++ b/Modules/Core/ComplexImage/otb-module.cmake
@@ -27,6 +27,7 @@ otb_module(OTBComplexImage
 
   TEST_DEPENDS
     OTBITK
+    OTBFunctor
     OTBImageBase
     OTBImageIO
     OTBTestKernel
diff --git a/Modules/Core/ComplexImage/test/otbAmplitudePhaseToRGBFunctor.cxx b/Modules/Core/ComplexImage/test/otbAmplitudePhaseToRGBFunctor.cxx
index 4861e5ec1665fd46bd06b8929aae92090178e512..ddfe7bf1e79474f75d77152f3db895839b00d8f4 100644
--- a/Modules/Core/ComplexImage/test/otbAmplitudePhaseToRGBFunctor.cxx
+++ b/Modules/Core/ComplexImage/test/otbAmplitudePhaseToRGBFunctor.cxx
@@ -24,9 +24,8 @@
 #include "otbImage.h"
 #include "otbImageFileReader.h"
 #include "otbImageFileWriter.h"
-#include "itkUnaryFunctorImageFilter.h"
-#include "itkTernaryFunctorImageFilter.h"
 #include "otbAmplitudePhaseToRGBFunctor.h"
+#include "otbFunctorImageFilter.h"
 #include "itkComplexToModulusImageFilter.h"
 #include "itkComplexToPhaseImageFilter.h"
 #include "itkShiftScaleImageFilter.h"
@@ -65,11 +64,10 @@ int otbAmplitudePhaseToRGBFunctor(int itkNotUsed(argc), char * argv[])
 
   typedef otb::Functor::AmplitudePhaseToRGBFunctor
   <PixelType, PixelType, PixelType, RGBPixelType> ColorMapFunctorType;
-  typedef itk::TernaryFunctorImageFilter
-  <ImageType, ImageType, ImageType, RGBImageType, ColorMapFunctorType> ColorMapFilterType;
+  typedef otb::FunctorImageFilter<ColorMapFunctorType> ColorMapFilterType;
   ColorMapFilterType::Pointer colormapper = ColorMapFilterType::New();
-  colormapper->GetFunctor().SetMaximum(4000);
-  colormapper->GetFunctor().SetMinimum(0);
+  colormapper->GetModifiableFunctor().SetMaximum(4000);
+  colormapper->GetModifiableFunctor().SetMinimum(0);
 
   colormapper->SetInput1(modulusFilter->GetOutput());
   colormapper->SetInput2(constFilter->GetOutput());
diff --git a/Modules/Core/Functor/include/otbFunctorImageFilter.hxx b/Modules/Core/Functor/include/otbFunctorImageFilter.hxx
index add3fadcc4e18acef2bd4acb837fa2c93b3567e1..cda6bb6c63c8d47a6653b9bbaffe7ad05b53bb33 100644
--- a/Modules/Core/Functor/include/otbFunctorImageFilter.hxx
+++ b/Modules/Core/Functor/include/otbFunctorImageFilter.hxx
@@ -26,6 +26,7 @@
 #include "itkConstNeighborhoodIterator.h"
 #include "itkImageRegionConstIterator.h"
 #include "itkImageScanlineIterator.h"
+#include <array>
 
 namespace otb
 {
diff --git a/Modules/Core/VectorDataBase/src/otbVectorDataKeywordlist.cxx b/Modules/Core/VectorDataBase/src/otbVectorDataKeywordlist.cxx
index 39c3623e1a122bb187ab1f8b7c198af3d8098610..c14f3dda5a992d70dc68e4bfa6a62a56103cdf88 100644
--- a/Modules/Core/VectorDataBase/src/otbVectorDataKeywordlist.cxx
+++ b/Modules/Core/VectorDataBase/src/otbVectorDataKeywordlist.cxx
@@ -106,14 +106,12 @@ VectorDataKeywordlist
         ss << std::setprecision(15) << m_FieldList[i].second.Integer;
         return ss.str();
         }
-#ifdef OTB_USE_GDAL_20
         case OFTInteger64:
         {
         std::ostringstream ss;
         ss << std::setprecision(15) << m_FieldList[i].second.Integer64;
         return ss.str();
         }
-#endif     
         case OFTReal:
         {
         std::ostringstream ss;
@@ -183,7 +181,6 @@ VectorDataKeywordlist
           {
         return (int)(m_FieldList[i].second.Integer);
         }
-#ifdef OTB_USE_GDAL_20
         // Some fields that were OFTInteger with gdal 1.x are now
         // exposed as OFTInteger64. So as to make the old code still
         // work with the same data, here we downcast to Integer (if
@@ -197,7 +194,6 @@ VectorDataKeywordlist
           
           return static_cast<int>(m_FieldList[i].second.Integer64);
           }
-#endif    
         case OFTReal:
           {
           return (int)(m_FieldList[i].second.Real);
@@ -483,13 +479,11 @@ VectorDataKeywordlist
              << field.second.Date.Hour << field.second.Date.Minute << field.second.Date.Second;
       break;
       }
-#ifdef OTB_USE_GDAL_20
     case OFTInteger64:
     {
     output << std::setprecision(15)<<field.second.Integer64;
     break;
     }
-#endif     
     default:
       output << "Type not handled for printing";
       break;
@@ -511,13 +505,11 @@ VectorDataKeywordlist
       outField.second.Integer = field.second.Integer;
       break;
       }
-#ifdef OTB_USE_GDAL_20
     case OFTInteger64:
     {
     outField.second.Integer64 = field.second.Integer64;
     break;
     }
-#endif     
     case OFTReal:
       {
       outField.second.Real = field.second.Real;
diff --git a/Modules/Fusion/PanSharpening/include/otbBayesianFusionFilter.h b/Modules/Fusion/PanSharpening/include/otbBayesianFusionFilter.h
index eb0b4a6389f69aaf1cb06cf9b94c534897cd7863..b8389e8463389e18c0dce4ff7ee6b90ac472c733 100644
--- a/Modules/Fusion/PanSharpening/include/otbBayesianFusionFilter.h
+++ b/Modules/Fusion/PanSharpening/include/otbBayesianFusionFilter.h
@@ -24,7 +24,7 @@
 #include "itkImageToImageFilter.h"
 #include "otbVectorImage.h"
 #include "otbStreamingStatisticsVectorImageFilter.h"
-#include "otbFusionImageBase.h"
+#include "otbFunctorImageFilter.h"
 #include "otbStreamingMatrixTransposeMatrixImageFilter.h"
 #include "otbImageToVectorImageCastFilter.h"
 
@@ -100,12 +100,11 @@ public:
     return m_Vcondopt;
   }
 
-  inline TOutput operator ()(const TInputMultiSpectral& itkNotUsed(ms),
-                             const TInputMultiSpectralInterp& msi,
-                             const TInputPanchro& p)
+  void operator ()(TOutput & obs,
+                   const TInputMultiSpectral& itkNotUsed(ms),
+                   const TInputMultiSpectralInterp& msi,
+                   const TInputPanchro& p)
   {
-    TOutput obs;
-    obs.SetSize(msi.GetSize());
     MatrixType obsMat, msiVect;
     obsMat.SetSize(1, obs.GetSize());
     msiVect.SetSize(1, msi.GetSize());
@@ -145,7 +144,11 @@ public:
       {
       obs[i] = static_cast<typename TOutput::ValueType>(obsMat(0U, i));
       }
-    return obs;
+  }
+
+  constexpr size_t OutputSize(const std::array<size_t, 3> inputsNbBands) const
+  {
+    return inputsNbBands[1];
   }
 
 private:
@@ -193,14 +196,10 @@ template <class TInputMultiSpectralImage,
     class TInputPanchroImage,
     class TOutputImage>
 class ITK_EXPORT BayesianFusionFilter
-  :  public FusionImageBase<TInputMultiSpectralImage,
-      TInputMultiSpectralInterpImage,
-      TInputPanchroImage,
-      TOutputImage,
-      Functor::BayesianFunctor<typename TInputMultiSpectralImage::PixelType,
-          typename TInputMultiSpectralInterpImage::PixelType,
-          typename TInputPanchroImage::PixelType,
-          typename TOutputImage::PixelType> >
+  :  public FunctorImageFilter<Functor::BayesianFunctor<typename TInputMultiSpectralImage::PixelType,
+                                                        typename TInputMultiSpectralInterpImage::PixelType,
+                                                        typename TInputPanchroImage::PixelType,
+                                                        typename TOutputImage::PixelType> >
 {
 public:
   /**   Extract input and output images dimensions.*/
@@ -215,14 +214,11 @@ public:
 
   /** "typedef" for standard classes. */
   typedef BayesianFusionFilter Self;
-  typedef FusionImageBase<InputMultiSpectralImageType,
-      InputMultiSpectralInterpImageType,
-      InputPanchroImageType,
-      OutputImageType,
-      Functor::BayesianFunctor<typename InputMultiSpectralImageType::PixelType,
-          typename InputMultiSpectralInterpImageType::PixelType,
-          typename InputPanchroImageType::PixelType,
-          typename OutputImageType::PixelType> > Superclass;
+  using BayesianFunctorType = Functor::BayesianFunctor<typename TInputMultiSpectralImage::PixelType,
+                                                       typename TInputMultiSpectralInterpImage::PixelType,
+                                                       typename TInputPanchroImage::PixelType,
+                                                       typename TOutputImage::PixelType>; 
+  typedef FunctorImageFilter<BayesianFunctorType>  Superclass;
   typedef itk::SmartPointer<Self>       Pointer;
   typedef itk::SmartPointer<const Self> ConstPointer;
 
@@ -230,7 +226,7 @@ public:
   itkNewMacro(Self);
 
   /** return class name. */
-  itkTypeMacro(BayesianFusionFilter, FusionImageBase);
+  itkTypeMacro(BayesianFusionFilter, FunctorImageFilter);
 
   /** Supported images definition. */
   typedef typename InputMultiSpectralImageType::PixelType               InputMultiSpectralPixelType;
@@ -266,6 +262,36 @@ public:
   typedef ImageToVectorImageCastFilter<InputPanchroImageType,
       InputMultiSpectralImageType>              CasterType;
 
+  void SetMultiSpect(const InputMultiSpectralImageType *multiSpect)
+  {
+    this->template SetVariadicInput<0>(multiSpect);
+  }
+
+  void SetMultiSpectInterp(const InputMultiSpectralInterpImageType *multiSpectInterp)
+  {
+    this->template SetVariadicInput<1>(multiSpectInterp);
+  }
+
+  void SetPanchro(const InputPanchroImageType *panchro)
+  {
+    this->template SetVariadicInput<2>(panchro);
+  }
+
+  const InputMultiSpectralImageType* GetMultiSpect()
+  {
+    return this->template GetVariadicInput<0>();
+  }
+
+  const InputMultiSpectralInterpImageType* GetMultiSpectInterp()
+  {
+    return this->template GetVariadicInput<1>();
+  }
+
+  const InputPanchroImageType* GetPanchro()
+  {
+    return this->template GetVariadicInput<2>();
+  }
+
   /** Set the ponderation value. */
   itkSetMacro(Lambda, float);
   /** Give the ponderation value. */
@@ -297,8 +323,14 @@ public:
   itkGetConstReferenceMacro(S, float);
 
 protected:
-  BayesianFusionFilter();
-  ~BayesianFusionFilter() override;
+  BayesianFusionFilter() : Superclass(BayesianFunctorType{},{{0,0}})
+    {
+    m_Lambda = 0.9999;
+    m_S = 1;
+    m_StatisticsHaveBeenGenerated = false;
+    };
+
+  ~BayesianFusionFilter() override {};
   /** Check if internal statistics need to be computed, and do so */
   void BeforeThreadedGenerateData() override;
   /** Compute internal statistics required for fusion */
diff --git a/Modules/Fusion/PanSharpening/include/otbBayesianFusionFilter.hxx b/Modules/Fusion/PanSharpening/include/otbBayesianFusionFilter.hxx
index ca718c967e6c973c0c6b8944171991eddc8ab44e..0fe25b3875632b9d3694cb74b54999b18d94d6f5 100644
--- a/Modules/Fusion/PanSharpening/include/otbBayesianFusionFilter.hxx
+++ b/Modules/Fusion/PanSharpening/include/otbBayesianFusionFilter.hxx
@@ -27,33 +27,6 @@
 namespace otb
 {
 
-template <class TInputMultiSpectralImage,
-    class TInputMultiSpectralInterpImage,
-    class TInputPanchroImage,
-    class TOutputImage>
-BayesianFusionFilter<TInputMultiSpectralImage,
-    TInputMultiSpectralInterpImage,
-    TInputPanchroImage,
-    TOutputImage>
-::BayesianFusionFilter()
-{
-  m_Lambda = 0.9999;
-  m_S = 1;
-  m_StatisticsHaveBeenGenerated = false;
-}
-
-template <class TInputMultiSpectralImage,
-    class TInputMultiSpectralInterpImage,
-    class TInputPanchroImage,
-    class TOutputImage>
-BayesianFusionFilter<TInputMultiSpectralImage,
-    TInputMultiSpectralInterpImage,
-    TInputPanchroImage,
-    TOutputImage>
-::~BayesianFusionFilter()
-{
-
-}
 template <class TInputMultiSpectralImage,
     class TInputMultiSpectralInterpImage,
     class TInputPanchroImage,
@@ -302,12 +275,12 @@ BayesianFusionFilter<TInputMultiSpectralImage,
   //**** END TODO ****/
   m_Vcondopt = m_Vcondopt.GetInverse();
   // Functor initialization
-  this->GetFunctor().SetVcondopt(m_Vcondopt);
-  this->GetFunctor().SetBeta(cutBeta);
-  this->GetFunctor().SetAlpha(m_Beta(0, 0));
-  this->GetFunctor().SetCovarianceInvMatrix(m_CovarianceInvMatrix);
-  this->GetFunctor().SetLambda(m_Lambda);
-  this->GetFunctor().SetS(m_S);
+  this->GetModifiableFunctor().SetVcondopt(m_Vcondopt);
+  this->GetModifiableFunctor().SetBeta(cutBeta);
+  this->GetModifiableFunctor().SetAlpha(m_Beta(0, 0));
+  this->GetModifiableFunctor().SetCovarianceInvMatrix(m_CovarianceInvMatrix);
+  this->GetModifiableFunctor().SetLambda(m_Lambda);
+  this->GetModifiableFunctor().SetS(m_S);
 
   // Restore the previous buffered data
   multiSpecInterp->SetRequestedRegion(msiRequestedRegion);
diff --git a/Modules/Fusion/PanSharpening/include/otbFusionImageBase.h b/Modules/Fusion/PanSharpening/include/otbFusionImageBase.h
deleted file mode 100644
index 2e7429281c3bec78addc71aaa18d1cc0ac2685bf..0000000000000000000000000000000000000000
--- a/Modules/Fusion/PanSharpening/include/otbFusionImageBase.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
- *
- * This file is part of Orfeo Toolbox
- *
- *     https://www.orfeo-toolbox.org/
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef otbFusionImageBase_h
-#define otbFusionImageBase_h
-
-#include "itkTernaryFunctorImageFilter.h"
-#include "itkNumericTraits.h"
-
-namespace otb
-{
-/** \class FusionImageBase
- * Basic class for every Fusion classes.
- * \sa TernaryFunctorImageFilter
- *
- * \ingroup OTBPanSharpening
- */
-template <class TInputMultiSpectralImage, class TInputMultiSpectralInterpImage, class TInputPanchroImage,
-    class TOutputImage, class TFunctor>
-class ITK_EXPORT FusionImageBase :  public itk::TernaryFunctorImageFilter<TInputMultiSpectralImage,
-      TInputMultiSpectralInterpImage,
-      TInputPanchroImage, TOutputImage, TFunctor>
-{
-public:
-  /**   Extract input and output images dimensions.*/
-  itkStaticConstMacro(InputImageDimension, unsigned int, TInputMultiSpectralImage::ImageDimension);
-  itkStaticConstMacro(OutputImageDimension, unsigned int, TOutputImage::ImageDimension);
-
-  /** "typedef" to simplify the variables definition and the declaration. */
-  typedef TInputMultiSpectralImage       InputMultiSpectralImageType;
-  typedef TInputMultiSpectralInterpImage InputMultiSpectralInterpImageType;
-  typedef TInputPanchroImage             InputPanchroImageType;
-  typedef TOutputImage                   OutputImageType;
-  typedef TFunctor                       FunctorType;
-
-  /** "typedef" for standard classes. */
-  typedef FusionImageBase Self;
-  typedef itk::TernaryFunctorImageFilter<InputMultiSpectralImageType,
-      InputMultiSpectralInterpImageType,
-      InputPanchroImageType,
-      OutputImageType,
-      FunctorType> Superclass;
-  typedef itk::SmartPointer<Self>       Pointer;
-  typedef itk::SmartPointer<const Self> ConstPointer;
-
-  /** object factory method. */
-  itkNewMacro(Self);
-
-  /** return class name. */
-  itkTypeMacro(FusionImageBase, TernaryFunctorImageFilter);
-
-  /** Supported images definition. */
-  typedef typename InputMultiSpectralImageType::PixelType       InputMultiSpectralPixelType;
-  typedef typename InputMultiSpectralInterpImageType::PixelType InputMultiSpectralInterpPixelType;
-  typedef typename InputPanchroImageType::PixelType             InputPanchroPixelType;
-  typedef typename OutputImageType::PixelType                   OutputPixelType;
-  /** Real class typedef definition. */
-  typedef typename itk::NumericTraits<InputMultiSpectralPixelType>::RealType       InputMultiSpectralRealType;
-  typedef typename itk::NumericTraits<InputMultiSpectralInterpPixelType>::RealType InputMultiSpectralInterpRealType;
-  typedef typename itk::NumericTraits<InputPanchroPixelType>::RealType             InputPanchroRealType;
-  typedef typename InputMultiSpectralImageType::RegionType                         InputMultiSpectralImageRegionType;
-  typedef typename InputMultiSpectralInterpImageType::RegionType
-  InputMultiSpectralInterpImageRegionType;
-  typedef typename InputPanchroImageType::RegionType InputPanchroImageRegionType;
-  typedef typename OutputImageType::RegionType       OutputImageRegionType;
-
-  /** Image size "typedef" definition. */
-  typedef typename InputMultiSpectralImageType::SizeType SizeType;
-
-  void SetMultiSpect(const InputMultiSpectralImageType *multiSpect)
-  {
-    this->SetInput1(multiSpect);
-  }
-  void SetMultiSpectInterp(const InputMultiSpectralInterpImageType *multiSpectInterp)
-  {
-    this->SetInput2(multiSpectInterp);
-  }
-  void SetPanchro(const InputPanchroImageType *panchro)
-  {
-    this->SetInput3(panchro);
-  }
-
-  const InputMultiSpectralImageType* GetMultiSpect()
-  {
-    if (this->GetNumberOfInputs() < 1)
-      {
-      return nullptr;
-      }
-    else return (static_cast<const InputMultiSpectralImageType *>(this->itk::ProcessObject::GetInput(0)));
-  }
-
-  const InputMultiSpectralInterpImageType* GetMultiSpectInterp()
-  {
-    if (this->GetNumberOfInputs() < 2)
-      {
-      return nullptr;
-      }
-    else return (static_cast<const InputMultiSpectralInterpImageType *>(this->itk::ProcessObject::GetInput(1)));
-  }
-
-  const InputPanchroImageType* GetPanchro()
-  {
-    if (this->GetNumberOfInputs() < 3)
-      {
-      return nullptr;
-      }
-    else return (static_cast<const InputPanchroImageType *>(this->itk::ProcessObject::GetInput(2)));
-  }
-
-};
-
-} // end namespace otb
-
-#endif
diff --git a/Modules/Fusion/PanSharpening/include/otbLmvmPanSharpeningFusionImageFilter.h b/Modules/Fusion/PanSharpening/include/otbLmvmPanSharpeningFusionImageFilter.h
index 74d85336699d1def707944156b84873e772c68f2..345a7bcb959c97b7177b5b87451d0b7a3480517c 100644
--- a/Modules/Fusion/PanSharpening/include/otbLmvmPanSharpeningFusionImageFilter.h
+++ b/Modules/Fusion/PanSharpening/include/otbLmvmPanSharpeningFusionImageFilter.h
@@ -23,8 +23,7 @@
 #define otbLmvmPanSharpeningFusionImageFilter_h
 
 #include "otbConvolutionImageFilter.h"
-#include "itkUnaryFunctorImageFilter.h"
-#include "itkTernaryFunctorImageFilter.h"
+#include "otbFunctorImageFilter.h"
 #include "otbPerBandVectorImageFilter.h"
 #include "itkNoiseImageFilter.h"
 #include "otbVectorImage.h"
@@ -132,36 +131,34 @@ private:
   {
   public:
     // Implement the fusion as a six arguments operator
-    typename TOutputImageType::PixelType operator()(
-      const typename InternalVectorImageType::PixelType& stdXsPixel,
-      const TInternalPrecision& smoothPanchroPixel,
-      const typename TPanImageType::PixelType& sharpPanchroPixel) const
+    void operator()(typename TOutputImageType::PixelType& output,
+                    const typename InternalVectorImageType::PixelType& stdXsPixel,
+                    const TInternalPrecision& smoothPanchroPixel,
+                    const typename TPanImageType::PixelType& sharpPanchroPixel) const
     {
-      // Build output pixel
-      typename TOutputImageType::PixelType output(stdXsPixel.Size());
-
       // Perform fusion for each band with appropriate casting
       for(unsigned int i = 0; i < stdXsPixel.Size(); ++i)
         {
         output[i] = static_cast<typename TOutputImageType::InternalPixelType>(
           ((sharpPanchroPixel - smoothPanchroPixel) * stdXsPixel[i]));
         }
-      // Returns the output pixel
-      return output;
     }
+    constexpr size_t OutputSize(const std::array<size_t, 3> inputsNbBands) const
+    {
+      return inputsNbBands[0];
+    }
+
   };
 
   class FusionFunctor2
   {
   public:
     // Implement the fusion as a six arguments operator
-    typename TOutputImageType::PixelType operator()(const typename TOutputImageType::PixelType& functor1Pixel,
-                                                    const typename InternalVectorImageType::PixelType& smoothXsPixel,
-                                              const TInternalPrecision& stdPanchroPixel) const
+    void operator()(typename TOutputImageType::PixelType & output,
+                    const typename TOutputImageType::PixelType& functor1Pixel,
+                    const typename InternalVectorImageType::PixelType& smoothXsPixel,
+                    const TInternalPrecision& stdPanchroPixel) const
     {
-      // Build output pixel
-      typename TOutputImageType::PixelType output(smoothXsPixel.Size());
-
       TInternalPrecision scale = 1.;
 
       if(std::abs(stdPanchroPixel) > 1e-10)
@@ -175,8 +172,11 @@ private:
         output[i] = static_cast<typename TOutputImageType::InternalPixelType>(
           ((functor1Pixel[i] * scale) + smoothXsPixel[i]));
         }
-      // Returns the output pixel
-      return output;
+    }
+
+    constexpr size_t OutputSize(const std::array<size_t, 3> inputsNbBands) const
+    {
+      return inputsNbBands[0];
     }
   };
 
@@ -184,24 +184,16 @@ private:
    *  Typedef of the TernaryFunctorImageFilter applying the fusion functor to
    *  p, p_smooth, p_std, xs_smooth, xs_std and xs.
    */
-  typedef itk::TernaryFunctorImageFilter<InternalVectorImageType,
-                                         InternalImageType,
-                                         TPanImageType,
-                                         TOutputImageType,
-                                         FusionFunctor1>     FusionStep1FilterType;
+  typedef FunctorImageFilter<FusionFunctor1> FusionStep1FilterType;
 
   /** Pointer to the fusion filter */
-  typename FusionStep1FilterType::Pointer      m_FusionStep1Filter;
+  typename FusionStep1FilterType::Pointer m_FusionStep1Filter;
 
 
-  typedef itk::TernaryFunctorImageFilter<TOutputImageType,
-                                         InternalVectorImageType,
-                                    InternalImageType,
-                                    TOutputImageType,
-                                         FusionFunctor2>     FusionStep2FilterType;
+  typedef FunctorImageFilter<FusionFunctor2> FusionStep2FilterType;
 
   /** Pointer to the fusion filter */
-  typename FusionStep2FilterType::Pointer      m_FusionStep2Filter;
+  typename FusionStep2FilterType::Pointer m_FusionStep2Filter;
 
 
   /** Typedef of the convolution filter performing Pan smoothing */
diff --git a/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.h b/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.h
index ab0d4de8ca5d2dfaa1bf53787176a67367be2aff..2fe474c54361b798153c37c4564a5420a3f7dae7 100644
--- a/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.h
+++ b/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.h
@@ -24,7 +24,7 @@
 
 #include "otbConvolutionImageFilter.h"
 #include "otbImage.h"
-#include "itkTernaryFunctorImageFilter.h"
+#include "otbFunctorImageFilter.h"
 
 #include "itkProgressAccumulator.h"
 
@@ -118,13 +118,11 @@ private:
   {
   public:
     // Implement the fusion as a three arguments operator
-    typename TOutputImageType::PixelType operator()(const typename TXsImageType::PixelType& xsPixel,
+    void operator()(typename TOutputImageType::PixelType & output,
+                                                    const typename TXsImageType::PixelType& xsPixel,
                                                     const TInternalPrecision& smoothPanchroPixel,
                                                     const typename TPanImageType::PixelType& sharpPanchroPixel) const
     {
-      // Build output pixel
-      typename TOutputImageType::PixelType output(xsPixel.Size());
-
       TInternalPrecision scale = 1.;
 
       if(std::abs(smoothPanchroPixel) > 1e-10)
@@ -138,8 +136,11 @@ private:
         output[i] = static_cast<typename TOutputImageType::InternalPixelType>(
           xsPixel[i] * scale);
         }
-      // Returns the output pixel
-      return output;
+    }
+
+    constexpr size_t OutputSize(const std::array<size_t, 3> & inputsNbBands) const
+    {
+      return inputsNbBands[0];
     }
   };
 
@@ -155,13 +156,11 @@ private:
   {
   public:
     // Implement the fusion as a three arguments operator
-    typename TOutputImageType::PixelType operator()(const typename TXsImageType::PixelType& xsPixel,
-                                                    const TInternalPrecision& smoothPanchroPixel,
-                                                    const typename TPanImageType::PixelType& sharpPanchroPixel) const
+    void operator()(typename TOutputImageType::PixelType & output,
+                    const typename TXsImageType::PixelType& xsPixel,
+                    const TInternalPrecision& smoothPanchroPixel,
+                    const typename TPanImageType::PixelType& sharpPanchroPixel) const
     {
-      // Build output pixel
-      typename TOutputImageType::PixelType output(xsPixel.Size());
-
       // Check for no data Pan value
       if( m_NoDataValuePanAvailable && sharpPanchroPixel == m_NoDataValuePan )
         {
@@ -169,7 +168,7 @@ private:
           {
           output[i] = static_cast<typename TOutputImageType::InternalPixelType>( m_NoDataValuesXs[i] );
           }
-        return output;
+        return;
         }
 
       TInternalPrecision scale = 1.;
@@ -186,8 +185,6 @@ private:
                     static_cast<typename TOutputImageType::InternalPixelType>( xsPixel[i] ) :
                     static_cast<typename TOutputImageType::InternalPixelType>( xsPixel[i] * scale );
         }
-      // Returns the output pixel
-      return output;
     }
 
     void SetNoDataValuePanAvailable(bool noDataAvailable) {
@@ -206,6 +203,12 @@ private:
       m_NoDataValuesXs = noDataValues;
     }
 
+    constexpr size_t OutputSize(const std::array<size_t, 3> inputsNbBands) const
+    {
+      return inputsNbBands[0];
+    }
+
+    NoDataFusionFunctor() : m_NoDataValuePanAvailable(false), m_NoDataValuePan(0),m_NoDataValuesXsAvailable(false), m_NoDataValuesXs() {}
 
   private:
     /** No data flags and values for APN image */
@@ -221,24 +224,16 @@ private:
 
 
   /**
-   *  Typedef of the TernaryFunctorImageFilter applying the fusion functor to
+   *  Typedef of the FunctorImageFilter applying the fusion functor to
    *  p, p_smooth and xs.
    */
-  typedef itk::TernaryFunctorImageFilter<TXsImageType,
-                                         InternalImageType,
-                                         TPanImageType,
-                                         TOutputImageType,
-                                         FusionFunctor>     FusionFilterType;
+  typedef FunctorImageFilter<FusionFunctor> FusionFilterType;
 
   /**
-   *  Typedef of the TernaryFunctorImageFilter applying the no data fusion functor to
+   *  Typedef of the FunctorImageFilter applying the no data fusion functor to
    *  p, p_smooth and xs.
    */
-  typedef itk::TernaryFunctorImageFilter<TXsImageType,
-                                         InternalImageType,
-                                         TPanImageType,
-                                         TOutputImageType,
-                                         NoDataFusionFunctor>     NoDataFusionFilterType;
+  typedef FunctorImageFilter<NoDataFusionFunctor> NoDataFusionFilterType;
 
   /** Typedef of the convolution filter performing smoothing */
   typedef otb::ConvolutionImageFilter
diff --git a/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.hxx b/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.hxx
index e8a5c642fe8e9c9e557a0cde4f68a7f788fbeff4..eb7624829796ae1879897845c9e2472c7d16f295 100644
--- a/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.hxx
+++ b/Modules/Fusion/PanSharpening/include/otbSimpleRcsPanSharpeningFusionImageFilter.hxx
@@ -174,10 +174,10 @@ SimpleRcsPanSharpeningFusionImageFilter
     m_ProgressAccumulator->RegisterInternalFilter( m_NoDataFusionFilter, 0.1 );
 
     m_NoDataFusionFilter->SetInput2( m_ConvolutionFilter->GetOutput() );
-    m_NoDataFusionFilter->GetFunctor().SetNoDataValuesXsAvailable( noDataValuesXsAvailable );
-    m_NoDataFusionFilter->GetFunctor().SetNoDataValuePanAvailable( noDataValuePanAvailable );
-    m_NoDataFusionFilter->GetFunctor().SetNoDataValuePan( noDataValuePan );
-    m_NoDataFusionFilter->GetFunctor().SetNoDataValuesXs( noDataValuesXs );
+    m_NoDataFusionFilter->GetModifiableFunctor().SetNoDataValuesXsAvailable( noDataValuesXsAvailable );
+    m_NoDataFusionFilter->GetModifiableFunctor().SetNoDataValuePanAvailable( noDataValuePanAvailable );
+    m_NoDataFusionFilter->GetModifiableFunctor().SetNoDataValuePan( noDataValuePan );
+    m_NoDataFusionFilter->GetModifiableFunctor().SetNoDataValuesXs( noDataValuesXs );
 
     m_NoDataFusionFilter->SetInput1( this->GetXsInput() );
     m_NoDataFusionFilter->SetInput2( m_ConvolutionFilter->GetOutput() );
diff --git a/Modules/Fusion/PanSharpening/otb-module.cmake b/Modules/Fusion/PanSharpening/otb-module.cmake
index d53c37af34f75ea5120980b48308194ac24682c1..e8444f8661dd66783286cdc19e1200fad32ea07f 100644
--- a/Modules/Fusion/PanSharpening/otb-module.cmake
+++ b/Modules/Fusion/PanSharpening/otb-module.cmake
@@ -32,7 +32,7 @@ otb_module(OTBPanSharpening
     OTBITK
     OTBConvolution
     OTBImageManipulation
-
+    OTBFunctor
   TEST_DEPENDS
     OTBTestKernel
     OTBImageIO
diff --git a/Modules/IO/IOGDAL/include/otbOGRIOHelper.h b/Modules/IO/IOGDAL/include/otbOGRIOHelper.h
index 67b5e19778378afc4ed1a95e26a809f13c84358a..5427f030c6cbd786a3cd283635852e176dbed1fa 100644
--- a/Modules/IO/IOGDAL/include/otbOGRIOHelper.h
+++ b/Modules/IO/IOGDAL/include/otbOGRIOHelper.h
@@ -24,7 +24,6 @@
 #include <vector>
 
 #include "otbVectorData.h"
-#include "otbOGRVersionProxy.h"
 
 #include "OTBIOGDALExport.h"
 
@@ -74,14 +73,14 @@ public:
 
 
   unsigned int ProcessNodeWrite(InternalTreeNodeType * source,
-                                ogr::version_proxy::GDALDatasetType * m_DataSource,
+                                GDALDataset * m_DataSource,
                                 OGRGeometryCollection * ogrCollection,
                                 OGRLayer * ogrCurrentLayer,
                                 OGRSpatialReference * oSRS);
 
   /** Return a list of OGRLayer * */
   std::vector<OGRLayer*> ConvertDataTreeNodeToOGRLayers(InternalTreeNodeType * source,
-                                                        ogr::version_proxy::GDALDatasetType * dummyDatasource,
+                                                        GDALDataset * dummyDatasource,
                                                         OGRLayer* ogrCurrentLayer,
                                                         OGRSpatialReference * oSRS);
 
diff --git a/Modules/IO/IOGDAL/include/otbOGRVectorDataIO.h b/Modules/IO/IOGDAL/include/otbOGRVectorDataIO.h
index dbff89e1b3dd6448dd2d7ad57950c2e9e2f190ca..d743bfa2b5e3b0736edcfaac8ae9b70b1801f786 100644
--- a/Modules/IO/IOGDAL/include/otbOGRVectorDataIO.h
+++ b/Modules/IO/IOGDAL/include/otbOGRVectorDataIO.h
@@ -26,7 +26,6 @@
 
 #include "otbVectorDataIOBase.h"
 #include "otbVectorData.h"
-#include "otbOGRVersionProxy.h"
 
 #include "OTBIOGDALExport.h"
 
@@ -123,7 +122,7 @@ private:
 
   void CloseInternalDataSource();
 
-  ogr::version_proxy::GDALDatasetType * m_DataSource;
+  GDALDataset * m_DataSource;
 
 };
 
diff --git a/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx b/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx
index 22cdc92cd695dbba7937858a4d994bc9ea0ceba5..5a8f62ce70387bd3b372b02747aca18c056663d0 100644
--- a/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx
+++ b/Modules/IO/IOGDAL/src/otbGDALImageIO.cxx
@@ -1508,7 +1508,6 @@ void GDALImageIO::InternalWriteImageInformation(const void* buffer)
     /* -------------------------------------------------------------------- */
     /* Set the RPC coeffs if no projection available (since GDAL 1.10.0)    */
     /* -------------------------------------------------------------------- */
-#if GDAL_VERSION_NUM >= 1100000
     ImageKeywordlist otb_kwl;
     itk::ExposeMetaData<ImageKeywordlist>(dict,
                                           MetaDataKey::OSSIMKeywordlistKey,
@@ -1523,7 +1522,6 @@ void GDALImageIO::InternalWriteImageInformation(const void* buffer)
         CSLDestroy( rpcMetadata );
         }
       }
-#endif
     }
 
   /* -------------------------------------------------------------------- */
diff --git a/Modules/IO/IOGDAL/src/otbOGRIOHelper.cxx b/Modules/IO/IOGDAL/src/otbOGRIOHelper.cxx
index c27c1525025ef3f118cfac387e636e60ad55d584..0bf6f0644d9536a302cc54d191e4de4bf27d90fa 100644
--- a/Modules/IO/IOGDAL/src/otbOGRIOHelper.cxx
+++ b/Modules/IO/IOGDAL/src/otbOGRIOHelper.cxx
@@ -209,7 +209,7 @@ void OGRIOHelper
     otb::VectorDataKeywordlist kwl;
     for (int fieldNum = 0; fieldNum < feature->GetFieldCount(); ++fieldNum)
       {
-      if (ogr::version_proxy::IsFieldSetAndNotNull(feature, fieldNum))
+      if (ogr::IsFieldSetAndNotNull(feature, fieldNum))
         {
         kwl.AddField(feature->GetFieldDefnRef(fieldNum), feature->GetRawFieldRef(fieldNum));
         }
@@ -651,7 +651,7 @@ void OGRIOHelper
 
 unsigned int OGRIOHelper
 ::ProcessNodeWrite(InternalTreeNodeType * source,
-                   ogr::version_proxy::GDALDatasetType * m_DataSource,
+                   GDALDataset * m_DataSource,
                    OGRGeometryCollection * ogrCollection,
                    OGRLayer * ogrCurrentLayer,
                    OGRSpatialReference * oSRS)
@@ -1027,7 +1027,7 @@ unsigned int OGRIOHelper
  **/
 std::vector<OGRLayer*> OGRIOHelper
 ::ConvertDataTreeNodeToOGRLayers(InternalTreeNodeType * source,
-                                 ogr::version_proxy::GDALDatasetType * inMemoryDataSource,
+                                 GDALDataset * inMemoryDataSource,
                                  OGRLayer* ogrCurrentLayer,
                                  OGRSpatialReference * oSRS)
 {
@@ -1036,8 +1036,13 @@ std::vector<OGRLayer*> OGRIOHelper
   if (inMemoryDataSource == nullptr)
     {
     const char * driverName = "Memory";
-    ogr::version_proxy::GDALDriverType * ogrDriver = ogr::version_proxy::GetDriverByName(driverName);
-    inMemoryDataSource = ogr::version_proxy::Create(ogrDriver,"tempDataSource");
+    GDALDriver * ogrDriver = GetGDALDriverManager()->GetDriverByName(driverName);
+    inMemoryDataSource = ogrDriver->Create( "tempDataSource",
+                    0,
+                    0,
+                    0,
+                    GDT_Unknown,
+                    0);
     }
 
   std::vector<OGRLayer*>  ogrLayerVector;
diff --git a/Modules/IO/IOGDAL/src/otbOGRVectorDataIO.cxx b/Modules/IO/IOGDAL/src/otbOGRVectorDataIO.cxx
index f47b192d7ea916632d00f880722f7d7304f1a1b4..2d280b1af1d253995429407f559406cac20e142c 100644
--- a/Modules/IO/IOGDAL/src/otbOGRVectorDataIO.cxx
+++ b/Modules/IO/IOGDAL/src/otbOGRVectorDataIO.cxx
@@ -54,15 +54,19 @@ OGRVectorDataIO::~OGRVectorDataIO()
 bool
 OGRVectorDataIO::CanReadFile(const char* filename) const
 {
-  otb::ogr::version_proxy::GDALDatasetType * poDS = ogr::version_proxy::Open(filename, true);
-
+  GDALDataset * poDS = (GDALDataset *)GDALOpenEx(
+      filename, 
+      GDAL_OF_READONLY | GDAL_OF_VECTOR,
+      NULL,
+      NULL,
+      NULL);
   if (poDS == nullptr)
     {
     std::cerr<<"Can not read file "<<filename<<" with GDALOpen"<<std::endl;
     return false;
     }
 //     std::cout << poDS->GetDriver()->GetName() << std::endl;
-  ogr::version_proxy::Close(poDS);
+  GDALClose(poDS);
   return true;
 }
 
@@ -93,8 +97,12 @@ OGRVectorDataIO
     this->CloseInternalDataSource();
     }
 
-  m_DataSource = ogr::version_proxy::Open(this->m_FileName.c_str(),true);
-
+  m_DataSource = (GDALDataset *)GDALOpenEx(
+      this->m_FileName.c_str(), 
+      GDAL_OF_READONLY | GDAL_OF_VECTOR,
+      NULL,
+      NULL,
+      NULL);
   if (m_DataSource == nullptr)
     {
     itkExceptionMacro(<< "Failed to open data file " << this->m_FileName);
@@ -184,7 +192,7 @@ OGRVectorDataIO
 void OGRVectorDataIO::CloseInternalDataSource()
 {
   assert(m_DataSource != NULL && "m_DataSource cannot be NULL");
-  ogr::version_proxy::Close(m_DataSource);
+  GDALClose(m_DataSource);
   m_DataSource = nullptr;
 }
 
@@ -215,8 +223,8 @@ void OGRVectorDataIO::Write(const itk::DataObject* datag, char ** /** unused */)
 
 
   //Find first the OGR driver
-  ogr::version_proxy::GDALDriverType * ogrDriver =
-    ogr::version_proxy::GetDriverByName(this->GetOGRDriverName(this->m_FileName).data());
+  GDALDriver * ogrDriver =
+    GetGDALDriverManager()->GetDriverByName(this->GetOGRDriverName(this->m_FileName).data());
 
   if (ogrDriver == nullptr)
     {
@@ -226,15 +234,34 @@ void OGRVectorDataIO::Write(const itk::DataObject* datag, char ** /** unused */)
   // free an existing previous data source, if any
   if (m_DataSource != nullptr)
     {
-    ogr::version_proxy::Close(m_DataSource);
+    GDALClose(m_DataSource);
     }
 
   // Erase the dataSource if already exist
-  ogr::version_proxy::Delete(this->m_FileName.c_str());
-
-  // m_DataSource = OGRSFDriverRegistrar::Open(this->m_FileName.c_str(), TRUE);
-  m_DataSource = ogr::version_proxy::Create(ogrDriver,this->m_FileName.c_str());
+  GDALDataset * poDS = (GDALDataset *)GDALOpenEx(
+      this->m_FileName.c_str(), 
+       GDAL_OF_UPDATE | GDAL_OF_VECTOR,
+      NULL,
+      NULL,
+      NULL);
+
+  GDALDriver * poDriver = NULL;
+  if(poDS)
+    {
+    poDriver = poDS->GetDriver();
+    GDALClose(poDS);
+    }
+  if(poDriver)
+    {
+    poDriver->Delete(this->m_FileName.c_str());
+    }
 
+  m_DataSource = ogrDriver->Create( this->m_FileName.c_str(),
+                    0,
+                    0,
+                    0,
+                    GDT_Unknown,
+                    0);
   // check the created data source
   if (m_DataSource == nullptr)
     {
@@ -288,7 +315,7 @@ void OGRVectorDataIO::Write(const itk::DataObject* datag, char ** /** unused */)
   otbMsgDevMacro( << "layerKept " << layerKept );
   (void)layerKept; // keep compiler happy
 
-  otb::ogr::version_proxy::Close(m_DataSource);
+  GDALClose(m_DataSource);
   m_DataSource = nullptr;
 
   if (oSRS != nullptr)
diff --git a/Modules/IO/TestKernel/src/otbTestHelper.cxx b/Modules/IO/TestKernel/src/otbTestHelper.cxx
index fae2a40dfe64a70447af91c8ade41eb539f20fb5..e849b0129510644ac3d9c856d570f7931b5cbb04 100644
--- a/Modules/IO/TestKernel/src/otbTestHelper.cxx
+++ b/Modules/IO/TestKernel/src/otbTestHelper.cxx
@@ -48,7 +48,7 @@
 #include "otbDifferenceImageFilter.h"
 #include "otbPrintableImageFilter.h"
 #include "otbStreamingShrinkImageFilter.h"
-#include "otbOGRVersionProxy.h"
+#include "otbOGRHelpers.h"
 
 #include "otbConfigure.h"
 
@@ -1727,28 +1727,48 @@ int TestHelper::RegressionTestOgrFile(const char *testOgrFilename, const char *b
   /* -------------------------------------------------------------------- */
   /*      Open data source.                                               */
   /* -------------------------------------------------------------------- */
-  otb::ogr::version_proxy::GDALDatasetType *ref_poDS = nullptr;
-  otb::ogr::version_proxy::GDALDriverType *  ref_poDriver = nullptr;
+  GDALDataset *ref_poDS = nullptr;
+  GDALDriver *  ref_poDriver = nullptr;
   //OGRGeometry *  ref_poSpatialFilter = NULL;
-  otb::ogr::version_proxy::GDALDatasetType *test_poDS = nullptr;
-  otb::ogr::version_proxy::GDALDriverType *  test_poDriver = nullptr;
+  GDALDataset *test_poDS = nullptr;
+  GDALDriver *  test_poDriver = nullptr;
   //OGRGeometry *  test_poSpatialFilter = NULL;
 
-  ref_poDS = otb::ogr::version_proxy::Open(ref_pszDataSource, false);
+  ref_poDS = (GDALDataset *)GDALOpenEx(
+      ref_pszDataSource, 
+       GDAL_OF_UPDATE | GDAL_OF_VECTOR,
+      NULL,
+      NULL,
+      NULL);
+
   if (ref_poDS == nullptr && !bReadOnly)
     {
-    ref_poDS = otb::ogr::version_proxy::Open(ref_pszDataSource, true);
+    ref_poDS = (GDALDataset *)GDALOpenEx(
+      ref_pszDataSource, 
+       GDAL_OF_READONLY | GDAL_OF_VECTOR,
+      NULL,
+      NULL,
+      NULL);
     bReadOnly = TRUE;
     if (ref_poDS != nullptr && m_ReportErrors)
       {
       std::cout << "Had to open REF data source read-only."<<std::endl;
       }
     }
-  test_poDS = otb::ogr::version_proxy::Open(ref_pszDataSource, bReadOnly);
+  test_poDS = (GDALDataset *)GDALOpenEx(
+      ref_pszDataSource, 
+      (bReadOnly? GDAL_OF_READONLY : GDAL_OF_UPDATE) | GDAL_OF_VECTOR,
+      NULL,
+      NULL,
+      NULL);
   if (test_poDS == nullptr && !bReadOnly)
     {
-    test_poDS = otb::ogr::version_proxy::Open(ref_pszDataSource, bReadOnly);
-
+    test_poDS = (GDALDataset *)GDALOpenEx(
+      ref_pszDataSource, 
+      (bReadOnly? GDAL_OF_READONLY : GDAL_OF_UPDATE) | GDAL_OF_VECTOR,
+      NULL,
+      NULL,
+      NULL);
     bReadOnly = TRUE;
 
     if (test_poDS != nullptr && m_ReportErrors)
@@ -1766,7 +1786,7 @@ int TestHelper::RegressionTestOgrFile(const char *testOgrFilename, const char *b
       {
       std::cout << "FAILURE:\n" "Unable to open REF datasource `" << ref_pszDataSource << "' with the following drivers." << std::endl;
 
-      std::vector<std::string> drivers = ogr::version_proxy::GetAvailableDriversAsStringVector();
+      std::vector<std::string> drivers = ogr::GetAvailableDriversAsStringVector();
 
       for (std::vector<std::string>::const_iterator it = drivers.begin();it!=drivers.end();++it)
         {
@@ -1784,7 +1804,7 @@ int TestHelper::RegressionTestOgrFile(const char *testOgrFilename, const char *b
       {
       std::cout << "FAILURE:\n""Unable to open TEST datasource `" << test_pszDataSource << "' with the following drivers." << std::endl;
 
-      std::vector<std::string> drivers = ogr::version_proxy::GetAvailableDriversAsStringVector();
+      std::vector<std::string> drivers = ogr::GetAvailableDriversAsStringVector();
 
       for (std::vector<std::string>::const_iterator it = drivers.begin();it!=drivers.end();++it)
         {
@@ -1803,8 +1823,8 @@ int TestHelper::RegressionTestOgrFile(const char *testOgrFilename, const char *b
 
   // TODO: Improve this check as it will stop as soon as one of the
   // list ends (i.e. it does not guarantee that all files are present)
-  std::vector<std::string> refFileList = otb::ogr::version_proxy::GetFileListAsStringVector(ref_poDS);
-  std::vector<std::string> testFileList = otb::ogr::version_proxy::GetFileListAsStringVector(test_poDS);
+  std::vector<std::string> refFileList = otb::ogr::GetFileListAsStringVector(ref_poDS);
+  std::vector<std::string> testFileList = otb::ogr::GetFileListAsStringVector(test_poDS);
 
   unsigned int fileId = 0;
 
@@ -1941,7 +1961,7 @@ void TestHelper::DumpOGRFeature(FILE* fpOut, OGRFeature* feature, char** papszOp
               poFDefn->GetNameRef(),
               OGRFieldDefn::GetFieldTypeName(poFDefn->GetType()));
 
-      if (ogr::version_proxy::IsFieldSetAndNotNull(feature, iField)) fprintf(fpOut, "%s\n", feature->GetFieldAsString(iField));
+      if (ogr::IsFieldSetAndNotNull(feature, iField)) fprintf(fpOut, "%s\n", feature->GetFieldAsString(iField));
       else fprintf(fpOut, "(null)\n");
 
       }
diff --git a/Modules/Learning/DimensionalityReductionLearning/include/otbAutoencoderModel.h b/Modules/Learning/DimensionalityReductionLearning/include/otbAutoencoderModel.h
index 71ed7482073a8090e7ef854436707cca60a88528..1c133864de36de022b2b1a1104cdb22cef7de949 100644
--- a/Modules/Learning/DimensionalityReductionLearning/include/otbAutoencoderModel.h
+++ b/Modules/Learning/DimensionalityReductionLearning/include/otbAutoencoderModel.h
@@ -84,6 +84,8 @@ public:
   typedef typename Superclass::ConfidenceSampleType         ConfidenceSampleType;
   typedef typename Superclass::ConfidenceListSampleType         ConfidenceListSampleType;
 
+  typedef typename Superclass::ProbaSampleType       ProbaSampleType;
+  typedef typename Superclass::ProbaListSampleType   ProbaListSampleType;
   /// Neural network related typedefs
   typedef shark::ConcatenatedModel<shark::RealVector> ModelType;
   typedef shark::LinearModel<shark::RealVector,NeuronType> LayerType;
@@ -162,14 +164,16 @@ protected:
 
   virtual TargetSampleType DoPredict(
     const InputSampleType& input,
-    ConfidenceValueType * quality = nullptr) const override;
+    ConfidenceValueType * quality = nullptr, 
+    ProbaSampleType * proba = nullptr) const override;
 
   virtual void DoPredictBatch(
     const InputListSampleType *,
     const unsigned int & startIndex,
     const unsigned int & size,
     TargetListSampleType *,
-    ConfidenceListSampleType * quality = nullptr) const override;
+    ConfidenceListSampleType * quality = nullptr,
+    ProbaListSampleType * proba = nullptr) const override;
 
 private:
   /** Internal Network */
diff --git a/Modules/Learning/DimensionalityReductionLearning/include/otbAutoencoderModel.hxx b/Modules/Learning/DimensionalityReductionLearning/include/otbAutoencoderModel.hxx
index 636f62cfd22ec339da109a2a7a7fea75832481bf..695f7e29e97502d96bd5a8cee8440913941fb1cb 100644
--- a/Modules/Learning/DimensionalityReductionLearning/include/otbAutoencoderModel.hxx
+++ b/Modules/Learning/DimensionalityReductionLearning/include/otbAutoencoderModel.hxx
@@ -375,7 +375,7 @@ AutoencoderModel<TInputValue,NeuronType>
 template <class TInputValue, class NeuronType>
 typename AutoencoderModel<TInputValue,NeuronType>::TargetSampleType
 AutoencoderModel<TInputValue,NeuronType>
-::DoPredict(const InputSampleType & value, ConfidenceValueType * /*quality*/) const
+::DoPredict(const InputSampleType & value, ConfidenceValueType * /*quality*/, ProbaSampleType * /*proba*/) const
 {  
   shark::RealVector samples(value.Size());
   for(size_t i = 0; i < value.Size();i++)
@@ -408,7 +408,8 @@ AutoencoderModel<TInputValue,NeuronType>
   const unsigned int & startIndex,
   const unsigned int & size,
   TargetListSampleType * targets,
-  ConfidenceListSampleType * /*quality*/) const
+  ConfidenceListSampleType * /*quality*/,
+  ProbaListSampleType * /*proba*/) const
 {
   std::vector<shark::RealVector> features;
   Shark::ListSampleRangeToSharkVector(input, features,startIndex,size);
diff --git a/Modules/Learning/DimensionalityReductionLearning/include/otbPCAModel.h b/Modules/Learning/DimensionalityReductionLearning/include/otbPCAModel.h
index c1aa97b938b350824da50b0d2886537fed3828f4..cc3971fe001e6cda8f8c84158e2b82ecad546394 100644
--- a/Modules/Learning/DimensionalityReductionLearning/include/otbPCAModel.h
+++ b/Modules/Learning/DimensionalityReductionLearning/include/otbPCAModel.h
@@ -79,6 +79,9 @@ public:
   typedef typename Superclass::ConfidenceSampleType      ConfidenceSampleType;
   typedef typename Superclass::ConfidenceListSampleType  ConfidenceListSampleType;
 
+  typedef typename Superclass::ProbaSampleType       ProbaSampleType;
+  typedef typename Superclass::ProbaListSampleType   ProbaListSampleType;
+
   itkNewMacro(Self);
   itkTypeMacro(PCAModel, DimensionalityReductionModel);
 
@@ -101,14 +104,16 @@ protected:
  
   virtual TargetSampleType DoPredict(
     const InputSampleType& input,
-    ConfidenceValueType * quality = nullptr) const override;
+    ConfidenceValueType * quality = nullptr,
+    ProbaSampleType * proba = nullptr) const override;
 
   virtual void DoPredictBatch(
     const InputListSampleType *,
     const unsigned int & startIndex,
     const unsigned int & size,
     TargetListSampleType *,
-    ConfidenceListSampleType * quality = nullptr) const override;
+    ConfidenceListSampleType * quality = nullptr,
+    ProbaListSampleType* proba = nullptr) const override;
 
 private:
   shark::LinearModel<> m_Encoder;
diff --git a/Modules/Learning/DimensionalityReductionLearning/include/otbPCAModel.hxx b/Modules/Learning/DimensionalityReductionLearning/include/otbPCAModel.hxx
index 85601662729a23d931b2b5d841494b7633b8728a..9c6973367242ec77ecad2240a215dabaee36369f 100644
--- a/Modules/Learning/DimensionalityReductionLearning/include/otbPCAModel.hxx
+++ b/Modules/Learning/DimensionalityReductionLearning/include/otbPCAModel.hxx
@@ -148,7 +148,7 @@ PCAModel<TInputValue>::Load(const std::string & filename, const std::string & /*
 
 template <class TInputValue>
 typename PCAModel<TInputValue>::TargetSampleType
-PCAModel<TInputValue>::DoPredict(const InputSampleType & value, ConfidenceValueType * /*quality*/) const
+PCAModel<TInputValue>::DoPredict(const InputSampleType & value, ConfidenceValueType * /*quality*/, ProbaSampleType * /*proba*/) const
 {  
   shark::RealVector samples(value.Size());
   for(size_t i = 0; i < value.Size();i++)
@@ -173,7 +173,7 @@ PCAModel<TInputValue>::DoPredict(const InputSampleType & value, ConfidenceValueT
 
 template <class TInputValue>
 void PCAModel<TInputValue>
-::DoPredictBatch(const InputListSampleType *input, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType * targets, ConfidenceListSampleType * /*quality*/) const
+::DoPredictBatch(const InputListSampleType *input, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType * targets, ConfidenceListSampleType * /*quality*/,ProbaListSampleType * /*proba*/) const
 {
   std::vector<shark::RealVector> features;
   Shark::ListSampleRangeToSharkVector(input, features,startIndex,size);
diff --git a/Modules/Learning/DimensionalityReductionLearning/include/otbSOMModel.h b/Modules/Learning/DimensionalityReductionLearning/include/otbSOMModel.h
index 11c5fe592a7b56ca04a6ca81c55edfdfb4ec0f7e..304fdac23d293d8e7d3275ab9f76e9e921875955 100644
--- a/Modules/Learning/DimensionalityReductionLearning/include/otbSOMModel.h
+++ b/Modules/Learning/DimensionalityReductionLearning/include/otbSOMModel.h
@@ -64,7 +64,8 @@ public:
   typedef typename Superclass::ConfidenceValueType       ConfidenceValueType;
   typedef typename Superclass::ConfidenceSampleType      ConfidenceSampleType;
   typedef typename Superclass::ConfidenceListSampleType  ConfidenceListSampleType;
-
+  typedef typename Superclass::ProbaSampleType       ProbaSampleType;
+  typedef typename Superclass::ProbaListSampleType   ProbaListSampleType;
   typedef SOMMap<
     itk::VariableLengthVector<TInputValue>,
     itk::Statistics::EuclideanDistanceMetric<
@@ -118,7 +119,8 @@ private:
 
   virtual TargetSampleType DoPredict(
     const InputSampleType& input,
-    ConfidenceValueType * quality = nullptr) const override;
+    ConfidenceValueType * quality = nullptr,
+    ProbaSampleType * proba = nullptr) const override;
 
   /** Map size (width, height) */
   SizeType m_MapSize;
diff --git a/Modules/Learning/DimensionalityReductionLearning/include/otbSOMModel.hxx b/Modules/Learning/DimensionalityReductionLearning/include/otbSOMModel.hxx
index 2c2abca261bb0533745eaf55fad822f9d9397f03..a2f93184f4ae05f42fe8205355ec0863121a9ab7 100644
--- a/Modules/Learning/DimensionalityReductionLearning/include/otbSOMModel.hxx
+++ b/Modules/Learning/DimensionalityReductionLearning/include/otbSOMModel.hxx
@@ -212,7 +212,8 @@ template <class TInputValue, unsigned int MapDimension>
 typename SOMModel<TInputValue, MapDimension>::TargetSampleType
 SOMModel<TInputValue, MapDimension>::DoPredict(
   const InputSampleType & value,
-  ConfidenceValueType * /*quality*/) const
+  ConfidenceValueType * /*quality*/,
+  ProbaSampleType * /*proba*/) const
 {
   TargetSampleType target;
   target.SetSize(this->m_Dimension);
diff --git a/Modules/Learning/LearningBase/include/otbImageClassificationFilter.h b/Modules/Learning/LearningBase/include/otbImageClassificationFilter.h
index 4609ce047de79e67fcb7a5e09a1174579ba172a0..2ff458e7d4ff5935631b676d00d4142a2756d76b 100644
--- a/Modules/Learning/LearningBase/include/otbImageClassificationFilter.h
+++ b/Modules/Learning/LearningBase/include/otbImageClassificationFilter.h
@@ -24,6 +24,7 @@
 #include "itkImageToImageFilter.h"
 #include "otbMachineLearningModel.h"
 #include "otbImage.h"
+#include "otbVectorImage.h"
 
 namespace otb
 {
@@ -75,6 +76,11 @@ public:
   typedef otb::Image<double>                    ConfidenceImageType;
   typedef typename ConfidenceImageType::Pointer ConfidenceImagePointerType;
 
+  /**Output type for Proba */
+  typedef otb::VectorImage<double>              ProbaImageType;
+
+  typedef typename ProbaImageType::Pointer      ProbaImagePointerType;
+  typedef itk::VariableLengthVector<double>     ProbaSampleType;
   /** Set/Get the model */
   itkSetObjectMacro(Model, ModelType);
   itkGetObjectMacro(Model, ModelType);
@@ -87,10 +93,16 @@ public:
   itkSetMacro(UseConfidenceMap, bool);
   itkGetMacro(UseConfidenceMap, bool);
 
+  /** Set/Get the proba map flag */
+  itkSetMacro(UseProbaMap, bool);
+  itkGetMacro(UseProbaMap, bool);
+  
   itkSetMacro(BatchMode, bool);
   itkGetMacro(BatchMode, bool);
   itkBooleanMacro(BatchMode);
 
+  itkSetMacro(NumberOfClasses, unsigned int);
+  itkGetMacro(NumberOfClasses, unsigned int);
   /**
    * If set, only pixels within the mask will be classified.
    * All pixels with a value greater than 0 in the mask, will be classified.
@@ -108,7 +120,7 @@ public:
    * Get the output confidence map
    */
   ConfidenceImageType * GetOutputConfidence(void);
-
+  ProbaImageType * GetOutputProba(void);
 protected:
   /** Constructor */
   ImageClassificationFilter();
@@ -124,6 +136,12 @@ protected:
   /**PrintSelf method */
   void PrintSelf(std::ostream& os, itk::Indent indent) const override;
 
+  void GenerateOutputInformation() override
+  {
+    Superclass::GenerateOutputInformation();
+    // Define the number of output bands
+    this->GetOutputProba()->SetNumberOfComponentsPerPixel(m_NumberOfClasses);
+  }
 private:
   ImageClassificationFilter(const Self &) = delete;
   void operator =(const Self&) = delete;
@@ -134,7 +152,9 @@ private:
   LabelType m_DefaultLabel;
   /** Flag to produce the confidence map (if the model supports it) */
   bool m_UseConfidenceMap;
+  bool m_UseProbaMap;
   bool m_BatchMode;
+  unsigned int m_NumberOfClasses;
 };
 } // End namespace otb
 #ifndef OTB_MANUAL_INSTANTIATION
diff --git a/Modules/Learning/LearningBase/include/otbImageClassificationFilter.hxx b/Modules/Learning/LearningBase/include/otbImageClassificationFilter.hxx
index fda4ab00349481e59c459257999737dd6b744b27..4aea60a2dade1cfa0a281d19573e8a6084da0918 100644
--- a/Modules/Learning/LearningBase/include/otbImageClassificationFilter.hxx
+++ b/Modules/Learning/LearningBase/include/otbImageClassificationFilter.hxx
@@ -38,11 +38,14 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
   this->SetNumberOfRequiredInputs(1);
   m_DefaultLabel = itk::NumericTraits<LabelType>::ZeroValue();
 
-  this->SetNumberOfRequiredOutputs(2);
+  this->SetNumberOfRequiredOutputs(3);
   this->SetNthOutput(0,TOutputImage::New());
   this->SetNthOutput(1,ConfidenceImageType::New());
+  this->SetNthOutput(2,ProbaImageType::New());
   m_UseConfidenceMap = false;
+  m_UseProbaMap = false;
   m_BatchMode = true;
+  m_NumberOfClasses = 1;
 }
 
 template <class TInputImage, class TOutputImage, class TMaskImage>
@@ -79,6 +82,19 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
   return static_cast<ConfidenceImageType *>(this->itk::ProcessObject::GetOutput(1));
 }
 
+template <class TInputImage, class TOutputImage, class TMaskImage>
+typename ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
+::ProbaImageType *
+ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
+::GetOutputProba()
+{
+  if (this->GetNumberOfOutputs() < 2)
+    {
+    return nullptr;
+    }
+  return static_cast<ProbaImageType *>(this->itk::ProcessObject::GetOutput(2));
+}
+
 template <class TInputImage, class TOutputImage, class TMaskImage>
 void
 ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
@@ -100,22 +116,25 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
 template <class TInputImage, class TOutputImage, class TMaskImage>
 void
 ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
-::ClassicThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId)
+::ClassicThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
+                              itk::ThreadIdType threadId)
 {
   // Get the input pointers
   InputImageConstPointerType inputPtr     = this->GetInput();
   MaskImageConstPointerType  inputMaskPtr  = this->GetInputMask();
   OutputImagePointerType     outputPtr    = this->GetOutput();
   ConfidenceImagePointerType confidencePtr = this->GetOutputConfidence();
-
+  ProbaImagePointerType      probaPtr      = this->GetOutputProba();
   // Progress reporting
-  itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
+  itk::ProgressReporter progress(this, threadId,
+                                 outputRegionForThread.GetNumberOfPixels());
 
   // Define iterators
   typedef itk::ImageRegionConstIterator<InputImageType> InputIteratorType;
   typedef itk::ImageRegionConstIterator<MaskImageType>  MaskIteratorType;
   typedef itk::ImageRegionIterator<OutputImageType>     OutputIteratorType;
   typedef itk::ImageRegionIterator<ConfidenceImageType> ConfidenceMapIteratorType;
+  typedef itk::ImageRegionIterator<ProbaImageType>      ProbaMapIteratorType;
 
   InputIteratorType inIt(inputPtr, outputRegionForThread);
   OutputIteratorType outIt(outputPtr, outputRegionForThread);
@@ -129,7 +148,8 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
     }
 
   // setup iterator for confidence map
-  bool computeConfidenceMap(m_UseConfidenceMap && m_Model->HasConfidenceIndex() && !m_Model->GetRegressionMode());
+  bool computeConfidenceMap(m_UseConfidenceMap && m_Model->HasConfidenceIndex() &&
+                            !m_Model->GetRegressionMode());
   ConfidenceMapIteratorType confidenceIt;
   if (computeConfidenceMap)
     {
@@ -137,11 +157,25 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
     confidenceIt.GoToBegin();
     }
 
+  // setup iterator for proba map
+  bool computeProbaMap(m_UseProbaMap &&  m_Model->HasProbaIndex() &&
+                       !m_Model->GetRegressionMode());
+
+  ProbaMapIteratorType probaIt;
+
+  if(computeProbaMap)
+    {
+      probaIt = ProbaMapIteratorType(probaPtr,outputRegionForThread);
+      probaIt.GoToBegin();
+    }
+
   bool validPoint = true;
   double confidenceIndex = 0.0;
-
+  ProbaSampleType probaVector{m_NumberOfClasses};
+  probaVector.Fill(0);
   // Walk the part of the image
-  for (inIt.GoToBegin(), outIt.GoToBegin(); !inIt.IsAtEnd() && !outIt.IsAtEnd(); ++inIt, ++outIt)
+  for (inIt.GoToBegin(), outIt.GoToBegin(); !inIt.IsAtEnd() && !outIt.IsAtEnd();
+       ++inIt, ++outIt)
     {
     // Check pixel validity
     if (inputMaskPtr)
@@ -151,17 +185,22 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
       }
     // If point is valid
     if (validPoint)
-      {
+    {
       // Classifify
-      if (computeConfidenceMap)
-        {
+      if (computeProbaMap)
+      {
+        outIt.Set(m_Model->Predict(inIt.Get(),&confidenceIndex,
+                                   &probaVector)[0]);
+      }
+      else if (computeConfidenceMap)
+      {
         outIt.Set(m_Model->Predict(inIt.Get(),&confidenceIndex)[0]);
-        }
+      }
       else
-        {
+      {
         outIt.Set(m_Model->Predict(inIt.Get())[0]);
-        }
       }
+    }
     else
       {
       // else, set default value
@@ -173,6 +212,11 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
       confidenceIt.Set(confidenceIndex);
       ++confidenceIt;
       }
+    if (computeProbaMap)
+    {
+      probaIt.Set(probaVector);
+      ++probaIt;
+    }
     progress.CompletedPixel();
     }
 
@@ -181,24 +225,31 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
 template <class TInputImage, class TOutputImage, class TMaskImage>
 void
 ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
-::BatchThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId)
+::BatchThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
+                            itk::ThreadIdType threadId)
 {
-  bool computeConfidenceMap(m_UseConfidenceMap && m_Model->HasConfidenceIndex() 
+  bool computeConfidenceMap(m_UseConfidenceMap && m_Model->HasConfidenceIndex()
                             && !m_Model->GetRegressionMode());
+
+  bool computeProbaMap(m_UseProbaMap && m_Model->HasProbaIndex()
+                       && !m_Model->GetRegressionMode());
   // Get the input pointers
   InputImageConstPointerType inputPtr     = this->GetInput();
   MaskImageConstPointerType  inputMaskPtr  = this->GetInputMask();
   OutputImagePointerType     outputPtr    = this->GetOutput();
   ConfidenceImagePointerType confidencePtr = this->GetOutputConfidence();
-    
+  ProbaImagePointerType      probaPtr      = this->GetOutputProba();
+
   // Progress reporting
-  itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
+  itk::ProgressReporter progress(this, threadId,
+                                 outputRegionForThread.GetNumberOfPixels());
 
   // Define iterators
   typedef itk::ImageRegionConstIterator<InputImageType> InputIteratorType;
   typedef itk::ImageRegionConstIterator<MaskImageType>  MaskIteratorType;
   typedef itk::ImageRegionIterator<OutputImageType>     OutputIteratorType;
   typedef itk::ImageRegionIterator<ConfidenceImageType> ConfidenceMapIteratorType;
+  typedef itk::ImageRegionIterator<ProbaImageType>      ProbaMapIteratorType;
 
   InputIteratorType inIt(inputPtr, outputRegionForThread);
   OutputIteratorType outIt(outputPtr, outputRegionForThread);
@@ -210,16 +261,12 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
     maskIt.GoToBegin();
     }
 
-  // typedef typename ModelType::InputValueType       InputValueType;
   typedef typename ModelType::InputSampleType      InputSampleType;
   typedef typename ModelType::InputListSampleType  InputListSampleType;
   typedef typename ModelType::TargetValueType      TargetValueType;
-  // typedef typename ModelType::TargetSampleType     TargetSampleType;
   typedef typename ModelType::TargetListSampleType TargetListSampleType;
-  // typedef typename ModelType::ConfidenceValueType      ConfidenceValueType;
-  // typedef typename ModelType::ConfidenceSampleType     ConfidenceSampleType;
   typedef typename ModelType::ConfidenceListSampleType ConfidenceListSampleType;
-
+  typedef typename ModelType::ProbaListSampleType ProbaListSampleType;
   typename InputListSampleType::Pointer samples = InputListSampleType::New();
   unsigned int num_features = inputPtr->GetNumberOfComponentsPerPixel();
   samples->SetMeasurementVectorSize(num_features);
@@ -247,11 +294,14 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
   //Make the batch prediction
   typename TargetListSampleType::Pointer labels;
   typename ConfidenceListSampleType::Pointer confidences;
+  typename ProbaListSampleType::Pointer probas;
   if(computeConfidenceMap)
     confidences = ConfidenceListSampleType::New();
 
+  if(computeProbaMap)
+    probas = ProbaListSampleType::New();
   // This call is threadsafe
-  labels = m_Model->PredictBatch(samples,confidences);
+  labels = m_Model->PredictBatch(samples,confidences,probas);
 
   // Set the output values
   ConfidenceMapIteratorType confidenceIt;
@@ -261,12 +311,19 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
     confidenceIt.GoToBegin();
     }
 
+  ProbaMapIteratorType probaIt;
+  if (computeProbaMap)
+    {
+      probaIt = ProbaMapIteratorType(probaPtr,outputRegionForThread);
+      probaIt.GoToBegin();
+    }
   typename TargetListSampleType::ConstIterator labIt = labels->Begin();
   maskIt.GoToBegin();
   for (outIt.GoToBegin(); !outIt.IsAtEnd(); ++outIt)
     {
     double confidenceIndex = 0.0;
     TargetValueType labelValue(m_DefaultLabel);
+    ProbaSampleType probaValues{m_NumberOfClasses};
     if (inputMaskPtr)
       {
       validPoint = maskIt.Get() > 0;
@@ -278,16 +335,26 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
 
        if(computeConfidenceMap)
         {
-        confidenceIndex = confidences->GetMeasurementVector(labIt.GetInstanceIdentifier())[0];
+        confidenceIndex =
+          confidences->GetMeasurementVector(labIt.GetInstanceIdentifier())[0];
         }
-       
-      ++labIt;    
+       if(computeProbaMap)
+       {
+         //The probas may have different size than the m_NumberOfClasses set by the user
+         auto tempProbaValues = probas->GetMeasurementVector(labIt.GetInstanceIdentifier());
+         for(unsigned int i=0; i<m_NumberOfClasses; ++i)
+         {
+           if(i<tempProbaValues.Size()) probaValues[i] = tempProbaValues[i];
+           else probaValues[i] = 0;
+         }
+       }
+      ++labIt;
       }
     else
       {
       labelValue = m_DefaultLabel;
       }
-    
+
     outIt.Set(labelValue);
 
     if(computeConfidenceMap)
@@ -295,14 +362,20 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
       confidenceIt.Set(confidenceIndex);
       ++confidenceIt;
       }
-    
+    if(computeProbaMap)
+    {
+      probaIt.Set(probaValues);
+      ++probaIt;
+    }
     progress.CompletedPixel();
     }
 }
 template <class TInputImage, class TOutputImage, class TMaskImage>
 void
-ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
-::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId)
+ImageClassificationFilter<TInputImage, TOutputImage,
+                          TMaskImage>::ThreadedGenerateData(
+                            const OutputImageRegionType& outputRegionForThread,
+                            itk::ThreadIdType threadId)
 {
   if(m_BatchMode)
     {
diff --git a/Modules/Learning/LearningBase/include/otbMachineLearningModel.h b/Modules/Learning/LearningBase/include/otbMachineLearningModel.h
index 01f522a4feccf6afbc246c7f61f5b14aa0e0cea5..9eb583e08477c14b30d7348256e578cff6aa4643 100644
--- a/Modules/Learning/LearningBase/include/otbMachineLearningModel.h
+++ b/Modules/Learning/LearningBase/include/otbMachineLearningModel.h
@@ -99,6 +99,9 @@ public:
   typedef typename MLMTargetTraits<TConfidenceValue>::SampleType ConfidenceSampleType;
   typedef itk::Statistics::ListSample<ConfidenceSampleType>      ConfidenceListSampleType;
 
+  
+  typedef itk::VariableLengthVector<double>      ProbaSampleType;
+  typedef itk::Statistics::ListSample<ProbaSampleType> ProbaListSampleType;
   /**\name Standard macros */
   //@{
   /** Run-time type information (and related methods). */
@@ -114,7 +117,7 @@ public:
     * quality value, or NULL
     * \return The predicted label
      */
-  TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality = nullptr) const;
+  TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality = nullptr, ProbaSampleType *proba = nullptr) const;
 
   /**\name Set and get the dimension of the model for dimensionality reduction models */
   //@{
@@ -130,7 +133,7 @@ public:
     * Note that this method will be multi-threaded if OTB is built
     * with OpenMP.
      */
-  typename TargetListSampleType::Pointer PredictBatch(const InputListSampleType * input, ConfidenceListSampleType * quality = nullptr) const;
+  typename TargetListSampleType::Pointer PredictBatch(const InputListSampleType * input, ConfidenceListSampleType * quality = nullptr, ProbaListSampleType * proba = nullptr) const;
   
 /**\name Classification model file manipulation */
 //@{
@@ -152,6 +155,8 @@ public:
 
 /** Query capacity to produce a confidence index */
   bool HasConfidenceIndex() const {return m_ConfidenceIndex;}
+  /** Query capacity to produce probability values */
+  bool HasProbaIndex() const {return m_ProbaIndex;}
 
 /**\name Input list of samples accessors */
 //@{
@@ -208,6 +213,9 @@ protected:
   /** flag that tells if the model support confidence index output */
   bool m_ConfidenceIndex;
 
+  /** flag that tells if the model support probability output */
+  bool m_ProbaIndex;
+  
   /** Is DoPredictBatch multi-threaded ? */
   bool m_IsDoPredictBatchMultiThreaded;
   
@@ -230,7 +238,7 @@ private:
     * Also set m_IsDoPredictBatchMultiThreaded to true if internal
     * implementation allows for parallel batch prediction.
     */
-  virtual void DoPredictBatch(const InputListSampleType * input, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType * target, ConfidenceListSampleType * quality = nullptr) const;
+  virtual void DoPredictBatch(const InputListSampleType * input, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType * target, ConfidenceListSampleType * quality = nullptr, ProbaListSampleType * proba = nullptr) const;
 
   /** Actual implementation of single sample prediction
    *  \param input sample to predict
@@ -238,7 +246,7 @@ private:
    *  or NULL
    *  \return The predicted label
    */ 
-  virtual TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType * quality= nullptr) const = 0;  
+  virtual TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType * quality= nullptr, ProbaSampleType *proba=nullptr) const = 0;  
  
   MachineLearningModel(const Self &) = delete;
   void operator =(const Self&) = delete;
diff --git a/Modules/Learning/LearningBase/include/otbMachineLearningModel.hxx b/Modules/Learning/LearningBase/include/otbMachineLearningModel.hxx
index a2c353a89a90865d2510eeafba9a75de2c18ee3d..c2956a76627b21c21540bdb45259e50efcbd9182 100644
--- a/Modules/Learning/LearningBase/include/otbMachineLearningModel.hxx
+++ b/Modules/Learning/LearningBase/include/otbMachineLearningModel.hxx
@@ -38,6 +38,7 @@ MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue>
   m_RegressionMode(false),
   m_IsRegressionSupported(false),
   m_ConfidenceIndex(false),
+  m_ProbaIndex(false),
   m_IsDoPredictBatchMultiThreaded(false),
   m_Dimension(0)
 {}
@@ -68,10 +69,10 @@ template <class TInputValue, class TOutputValue, class TConfidenceValue>
 typename MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue>
 ::TargetSampleType
 MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue>
-::Predict(const InputSampleType& input, ConfidenceValueType *quality) const
+::Predict(const InputSampleType& input, ConfidenceValueType *quality, ProbaSampleType *proba) const
 {
   // Call protected specialization entry point
-  return this->DoPredict(input,quality);
+  return this->DoPredict(input,quality,proba);
 }
 
 
@@ -79,8 +80,9 @@ template <class TInputValue, class TOutputValue, class TConfidenceValue>
 typename MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue>
 ::TargetListSampleType::Pointer
 MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue>
-::PredictBatch(const InputListSampleType * input, ConfidenceListSampleType * quality) const
+::PredictBatch(const InputListSampleType * input, ConfidenceListSampleType * quality, ProbaListSampleType *proba) const
 {
+  //std::cout << "Enter batch predict" << std::endl;
   typename TargetListSampleType::Pointer targets = TargetListSampleType::New();
   targets->Resize(input->Size());
   
@@ -89,16 +91,19 @@ MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue>
     quality->Clear();
     quality->Resize(input->Size());
     }
-  
+  if(proba!=ITK_NULLPTR)
+    {
+      proba->Clear();
+      proba->Resize(input->Size());
+    }
   if(m_IsDoPredictBatchMultiThreaded)
     {
     // Simply calls DoPredictBatch
-    this->DoPredictBatch(input,0,input->Size(),targets,quality);
-    return targets;
+      this->DoPredictBatch(input,0,input->Size(),targets,quality,proba);
+      return targets;
     }
   else
     {
-    
 #ifdef _OPENMP
     // OpenMP threading here
     unsigned int nb_threads(0), threadId(0), nb_batches(0);
@@ -120,11 +125,11 @@ MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue>
         batch_size+=input->Size()%nb_batches;
         }
     
-      this->DoPredictBatch(input,batch_start,batch_size,targets,quality);
+      this->DoPredictBatch(input,batch_start,batch_size,targets,quality,proba);
       }
     }
 #else
-    this->DoPredictBatch(input,0,input->Size(),targets,quality);
+    this->DoPredictBatch(input,0,input->Size(),targets,quality,proba);
 #endif
     return targets;
     }
@@ -135,29 +140,42 @@ MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue>
 template <class TInputValue, class TOutputValue, class TConfidenceValue>
 void
 MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue>
-::DoPredictBatch(const InputListSampleType * input, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType * targets, ConfidenceListSampleType * quality) const
+  ::DoPredictBatch(const InputListSampleType * input, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType * targets, ConfidenceListSampleType * quality, ProbaListSampleType * proba) const
 {
   assert(input != nullptr);
   assert(targets != nullptr);
   
   assert(input->Size()==targets->Size()&&"Input sample list and target label list do not have the same size.");
   assert(((quality==nullptr)||(quality->Size()==input->Size()))&&"Quality samples list is not null and does not have the same size as input samples list");
+  assert((proba==nullptr)||(input->Size()==proba->Size())&&"Proba sample list and target label list do not have the same size.");
 
   if(startIndex+size>input->Size())
     {
     itkExceptionMacro(<<"requested range ["<<startIndex<<", "<<startIndex+size<<"[ partially outside input sample list range.[0,"<<input->Size()<<"[");
     }
 
-  if(quality != nullptr)
+  if (proba != nullptr)
     {
     for(unsigned int id = startIndex;id<startIndex+size;++id)
       {
+      ProbaSampleType prob;
       ConfidenceValueType confidence = 0;
-      const TargetSampleType target = this->DoPredict(input->GetMeasurementVector(id),&confidence);
+      const TargetSampleType target = this->DoPredict(input->GetMeasurementVector(id),&confidence, &prob);
       quality->SetMeasurementVector(id,confidence);
+      proba->SetMeasurementVector(id,prob);
       targets->SetMeasurementVector(id,target);
       }
     }
+  else if(quality != ITK_NULLPTR)
+    {
+    for(unsigned int id = startIndex;id<startIndex+size;++id)
+      {
+      ConfidenceValueType confidence = 0;
+      const TargetSampleType target = this->DoPredict(input->GetMeasurementVector(id),&confidence);
+      quality->SetMeasurementVector(id,confidence);
+      targets->SetMeasurementVector(id,target);
+      }
+    }    
   else
     {
     for(unsigned int id = startIndex;id<startIndex+size;++id)
@@ -176,6 +194,6 @@ void
     // Call superclass implementation
     Superclass::PrintSelf(os,indent);
     }
-    }
+}
 
 #endif
diff --git a/Modules/Learning/Sampling/src/otbSampleAugmentationFilter.cxx b/Modules/Learning/Sampling/src/otbSampleAugmentationFilter.cxx
index 5778de0d9324b7a022cab8569c3b25a48260cfc8..1ff5bb8043539fa4f45dc7c90f0f52535e86f1c3 100644
--- a/Modules/Learning/Sampling/src/otbSampleAugmentationFilter.cxx
+++ b/Modules/Learning/Sampling/src/otbSampleAugmentationFilter.cxx
@@ -247,7 +247,7 @@ SampleAugmentationFilter
 {
   OGRFieldType fieldType = feature.ogr().GetFieldDefnRef(idx)->GetType();
   return (fieldType == OFTInteger 
-          || ogr::version_proxy::IsOFTInteger64( fieldType ) 
+          || fieldType == OFTInteger64
           || fieldType == OFTReal);
 }
 
diff --git a/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.h b/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.h
index 6b61f1f03201d12caf6e0ba557129017de0fc32f..93fa4da45cd239d9a9f7deae5bbf942e40f53461 100644
--- a/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.h
+++ b/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.h
@@ -53,7 +53,7 @@ public:
   typedef typename Superclass::TargetSampleType           TargetSampleType;
   typedef typename Superclass::TargetListSampleType       TargetListSampleType;
   typedef typename Superclass::ConfidenceValueType        ConfidenceValueType;
-
+  typedef typename Superclass::ProbaSampleType            ProbaSampleType;
   /** Run-time type information (and related methods). */
   itkNewMacro(Self);
   itkTypeMacro(BoostMachineLearningModel, MachineLearningModel);
@@ -124,8 +124,7 @@ protected:
   ~BoostMachineLearningModel() override;
 
   /** Predict values using the model */
-  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr) const override;
-
+  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr, ProbaSampleType *proba=nullptr) const override;
   
   /** PrintSelf method */
   void PrintSelf(std::ostream& os, itk::Indent indent) const override;
diff --git a/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.hxx b/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.hxx
index 8112d51d6f338bb376d892507274cb1cc4ff847d..86421b3b4b01bc1fc2313d55d8a01b1debb27f21 100644
--- a/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.hxx
+++ b/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.hxx
@@ -104,7 +104,7 @@ template <class TInputValue, class TOutputValue>
 typename BoostMachineLearningModel<TInputValue,TOutputValue>
 ::TargetSampleType
 BoostMachineLearningModel<TInputValue,TOutputValue>
-::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const
+::DoPredict(const InputSampleType & input, ConfidenceValueType *quality, ProbaSampleType *proba) const
 {
   TargetSampleType target;
 
@@ -132,6 +132,8 @@ BoostMachineLearningModel<TInputValue,TOutputValue>
 #endif
       );
     }
+ if (proba != nullptr && !this->m_ProbaIndex)
+   itkExceptionMacro("Probability per class not available for this classifier !");
 
   target[0] = static_cast<TOutputValue>(result);
   return target;
diff --git a/Modules/Learning/Supervised/include/otbCvRTreesWrapper.h b/Modules/Learning/Supervised/include/otbCvRTreesWrapper.h
index 97d881371c0768bc1fb5b1584de8c79fe75d95f7..7d8c4ad6cb60570da4ff07759daa5b0112aacd27 100644
--- a/Modules/Learning/Supervised/include/otbCvRTreesWrapper.h
+++ b/Modules/Learning/Supervised/include/otbCvRTreesWrapper.h
@@ -65,7 +65,7 @@ public:
   float predict_margin(const cv::Mat& sample,
                           const cv::Mat& missing =
                           cv::Mat()) const;
-
+  
 #ifdef OTB_OPENCV_3
 
 #define OTB_CV_WRAP_PROPERTY(type,name) \
diff --git a/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.h b/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.h
index b0940ce737a6ff649319537508f6d7b7334b1888..b90982f2b98ab0ae5d16d7c1976c7f2e93a7ef9d 100644
--- a/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.h
+++ b/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.h
@@ -53,7 +53,7 @@ public:
   typedef typename Superclass::TargetSampleType           TargetSampleType;
   typedef typename Superclass::TargetListSampleType       TargetListSampleType;
   typedef typename Superclass::ConfidenceValueType        ConfidenceValueType;
-
+  typedef typename Superclass::ProbaSampleType            ProbaSampleType;
   /** Run-time type information (and related methods). */
   itkNewMacro(Self);
   itkTypeMacro(DecisionTreeMachineLearningModel, MachineLearningModel);
@@ -179,7 +179,7 @@ protected:
   ~DecisionTreeMachineLearningModel() override;
 
   /** Predict values using the model */
-  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr) const override;
+  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr, ProbaSampleType *proba=nullptr) const override;
 
   /** PrintSelf method */
   void PrintSelf(std::ostream& os, itk::Indent indent) const override;
diff --git a/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.hxx b/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.hxx
index 52255ac51e365c359177e5d8be2c4ebed4fef38c..b5a7b618eb6ebad88010dc642196bbb18e2835e2 100644
--- a/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.hxx
+++ b/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.hxx
@@ -117,7 +117,7 @@ template <class TInputValue, class TOutputValue>
 typename DecisionTreeMachineLearningModel<TInputValue,TOutputValue>
 ::TargetSampleType
 DecisionTreeMachineLearningModel<TInputValue,TOutputValue>
-::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const
+::DoPredict(const InputSampleType & input, ConfidenceValueType *quality, ProbaSampleType *proba) const
 {
   TargetSampleType target;
 
@@ -140,8 +140,10 @@ DecisionTreeMachineLearningModel<TInputValue,TOutputValue>
       itkExceptionMacro("Confidence index not available for this classifier !");
       }
     }
+  if (proba != nullptr && !this->m_ProbaIndex)
+    itkExceptionMacro("Probability per class not available for this classifier !");
 
-  return target;
+return target;
 }
 
 template <class TInputValue, class TOutputValue>
diff --git a/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.h b/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.h
index 3249ef81a9e2e22a8139db8b419c349c968b2155..15a8df438697b6bf5031eb73e1f3e4852f57af4d 100644
--- a/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.h
+++ b/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.h
@@ -51,7 +51,7 @@ public:
   typedef typename Superclass::TargetSampleType           TargetSampleType;
   typedef typename Superclass::TargetListSampleType       TargetListSampleType;
   typedef typename Superclass::ConfidenceValueType        ConfidenceValueType;
-
+  typedef typename Superclass::ProbaSampleType            ProbaSampleType;
   /** Run-time type information (and related methods). */
   itkNewMacro(Self);
   itkTypeMacro(GradientBoostedTreeMachineLearningModel, MachineLearningModel);
@@ -130,8 +130,7 @@ protected:
   ~GradientBoostedTreeMachineLearningModel() override;
 
     /** Predict values using the model */
-  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr) const override;
-
+  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr, ProbaSampleType *proba=nullptr) const override;
   
   /** PrintSelf method */
   void PrintSelf(std::ostream& os, itk::Indent indent) const override;
diff --git a/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.hxx b/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.hxx
index b40394593bddb97d055b420b311f0cd34fd1dda6..132dd7bc3d12530260a2cc8f0ec2328775a94cbf 100644
--- a/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.hxx
+++ b/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.hxx
@@ -83,7 +83,7 @@ template <class TInputValue, class TOutputValue>
 typename GradientBoostedTreeMachineLearningModel<TInputValue,TOutputValue>
 ::TargetSampleType
 GradientBoostedTreeMachineLearningModel<TInputValue,TOutputValue>
-::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const
+::DoPredict(const InputSampleType & input, ConfidenceValueType *quality, ProbaSampleType *proba) const
 {
   //convert listsample to Mat
   cv::Mat sample;
@@ -103,6 +103,8 @@ GradientBoostedTreeMachineLearningModel<TInputValue,TOutputValue>
       itkExceptionMacro("Confidence index not available for this classifier !");
       }
     }
+  if (proba != nullptr && !this->m_ProbaIndex)
+    itkExceptionMacro("Probability per class not available for this classifier !");
 
   return target;
 }
diff --git a/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.h b/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.h
index fff1dd22567ed636752218d94d9c70cf992184ab..b9bceffb1c5c9f6a876a7047ce1d0dadec22f64d 100644
--- a/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.h
+++ b/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.h
@@ -53,7 +53,7 @@ public:
   typedef typename Superclass::TargetSampleType           TargetSampleType;
   typedef typename Superclass::TargetListSampleType       TargetListSampleType;
   typedef typename Superclass::ConfidenceValueType        ConfidenceValueType;
-
+  typedef typename Superclass::ProbaSampleType            ProbaSampleType;
   /** Run-time type information (and related methods). */
   itkNewMacro(Self);
   itkTypeMacro(KNearestNeighborsMachineLearningModel, MachineLearningModel);
@@ -104,8 +104,7 @@ protected:
   ~KNearestNeighborsMachineLearningModel() override;
 
   /** Predict values using the model */
-  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr) const override;
-
+  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr, ProbaSampleType *proba=nullptr) const override;
   
   /** PrintSelf method */
   void PrintSelf(std::ostream& os, itk::Indent indent) const override;
diff --git a/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.hxx b/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.hxx
index 230bd44357d3e52dd82a6598dd1893a3abd901ac..2d12cceb360808be01a6a2579b7b6ed58422d0bd 100644
--- a/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.hxx
+++ b/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.hxx
@@ -106,7 +106,7 @@ template <class TInputValue, class TTargetValue>
 typename KNearestNeighborsMachineLearningModel<TInputValue,TTargetValue>
 ::TargetSampleType
 KNearestNeighborsMachineLearningModel<TInputValue,TTargetValue>
-::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const
+::DoPredict(const InputSampleType & input, ConfidenceValueType *quality, ProbaSampleType *proba) const
 {
   TargetSampleType target;
 
@@ -135,6 +135,8 @@ KNearestNeighborsMachineLearningModel<TInputValue,TTargetValue>
       }
     (*quality) = static_cast<ConfidenceValueType>(accuracy);
     }
+  if (proba != nullptr && !this->m_ProbaIndex)
+      itkExceptionMacro("Probability per class not available for this classifier !");
 
   // Decision rule :
   //  VOTING is OpenCV default behaviour for classification
diff --git a/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.h b/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.h
index 1600b022bc545ace4446d523d865e2b376f79b19..da96ae0f47dc71c7648be456f39358ff119377e4 100644
--- a/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.h
+++ b/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.h
@@ -47,7 +47,7 @@ public:
   typedef typename Superclass::TargetSampleType           TargetSampleType;
   typedef typename Superclass::TargetListSampleType       TargetListSampleType;
   typedef typename Superclass::ConfidenceValueType        ConfidenceValueType;
-
+  typedef typename Superclass::ProbaSampleType            ProbaSampleType;
   /** enum to choose the way confidence is computed
    *   CM_INDEX : compute the difference between highest and second highest probability
    *   CM_PROBA : returns probabilities for all classes
@@ -272,7 +272,7 @@ protected:
   ~LibSVMMachineLearningModel() override;
 
   /** Predict values using the model */
-  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr) const override;
+  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr, ProbaSampleType *proba=nullptr) const override;
 
   /** PrintSelf method */
   void PrintSelf(std::ostream& os, itk::Indent indent) const override;
diff --git a/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.hxx b/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.hxx
index 5588ccbe7aa87ea58510da4a4dcbd423a1fd1f77..8435fecce363c43093cf3f37f9c3a1eaf48e80dc 100644
--- a/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.hxx
+++ b/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.hxx
@@ -107,7 +107,7 @@ template <class TInputValue, class TOutputValue>
 typename LibSVMMachineLearningModel<TInputValue,TOutputValue>
 ::TargetSampleType
 LibSVMMachineLearningModel<TInputValue,TOutputValue>
-::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const
+::DoPredict(const InputSampleType & input, ConfidenceValueType *quality, ProbaSampleType *proba) const
 {
   TargetSampleType target;
   target.Fill(0);
@@ -129,6 +129,8 @@ LibSVMMachineLearningModel<TInputValue,TOutputValue>
   // terminate node
   x[input.Size()].index = -1;
   x[input.Size()].value = 0;
+  if (proba != nullptr && !this->m_ProbaIndex)
+    itkExceptionMacro("Probability per class not available for this classifier !");
 
   if (quality != nullptr)
     {
diff --git a/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.h b/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.h
index 283b5ce015c53c3c9ac4e8d6c9d91d3c8668e2a0..f461a9e7d4d5f941706c0c234349cdf8881714ec 100644
--- a/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.h
+++ b/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.h
@@ -48,7 +48,7 @@ public:
   typedef typename Superclass::TargetSampleType           TargetSampleType;
   typedef typename Superclass::TargetListSampleType       TargetListSampleType;
   typedef typename Superclass::ConfidenceValueType        ConfidenceValueType;
-
+  typedef typename Superclass::ProbaSampleType            ProbaSampleType;
   typedef std::map<TargetValueType, unsigned int>         MapOfLabelsType;
 
   /** Run-time type information (and related methods). */
@@ -178,7 +178,7 @@ protected:
   ~NeuralNetworkMachineLearningModel() override;
 
   /** Predict values using the model */
-  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr) const override;
+  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr, ProbaSampleType *proba=nullptr) const override;
   
   void LabelsToMat(const TargetListSampleType * listSample, cv::Mat & output);
 
diff --git a/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.hxx b/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.hxx
index 2f807898aa660c52e88ac366808badeb12f6e667..1a54679b29e30bf567b37174120aebb294d76dd8 100644
--- a/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.hxx
+++ b/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.hxx
@@ -234,7 +234,7 @@ void NeuralNetworkMachineLearningModel<TInputValue, TOutputValue>::Train()
 
 template<class TInputValue, class TOutputValue>
 typename NeuralNetworkMachineLearningModel<TInputValue, TOutputValue>::TargetSampleType NeuralNetworkMachineLearningModel<
-  TInputValue, TOutputValue>::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const
+  TInputValue, TOutputValue>::DoPredict(const InputSampleType & input, ConfidenceValueType *quality, ProbaSampleType *proba) const
 {
   TargetSampleType target;
   //convert listsample to Mat
@@ -282,6 +282,9 @@ typename NeuralNetworkMachineLearningModel<TInputValue, TOutputValue>::TargetSam
     {
     (*quality) = static_cast<ConfidenceValueType>(maxResponse) - static_cast<ConfidenceValueType>(secondResponse);
     }
+  if (proba != nullptr && !this->m_ProbaIndex)
+    itkExceptionMacro("Probability per class not available for this classifier !");
+
   return target;
 }
 
diff --git a/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.h b/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.h
index cb3da6e3025e279b47794c8ba48dca748c832e4d..6589f6c4c174f8afe16dce22194ecb0e23280a11 100644
--- a/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.h
+++ b/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.h
@@ -53,7 +53,7 @@ public:
   typedef typename Superclass::TargetSampleType           TargetSampleType;
   typedef typename Superclass::TargetListSampleType       TargetListSampleType;
   typedef typename Superclass::ConfidenceValueType        ConfidenceValueType;
-
+  typedef typename Superclass::ProbaSampleType            ProbaSampleType;
   /** Run-time type information (and related methods). */
   itkNewMacro(Self);
   itkTypeMacro(NormalBayesMachineLearningModel, MachineLearningModel);
@@ -84,8 +84,7 @@ protected:
   ~NormalBayesMachineLearningModel() override;
 
   /** Predict values using the model */
-  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr) const override;
-
+  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr, ProbaSampleType *proba=nullptr) const override;
   
   /** PrintSelf method */
   void PrintSelf(std::ostream& os, itk::Indent indent) const override;
diff --git a/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.hxx b/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.hxx
index 9e0ca05c8bec54e4a80765eea447ed37ba9a8768..1285d211e1c0a906c68d1a38acf1184fe91d8c0f 100644
--- a/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.hxx
+++ b/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.hxx
@@ -85,7 +85,7 @@ template <class TInputValue, class TOutputValue>
 typename NormalBayesMachineLearningModel<TInputValue,TOutputValue>
 ::TargetSampleType
 NormalBayesMachineLearningModel<TInputValue,TOutputValue>
-::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const
+::DoPredict(const InputSampleType & input, ConfidenceValueType *quality, ProbaSampleType *proba) const
 {
   TargetSampleType target;
 
@@ -107,6 +107,9 @@ NormalBayesMachineLearningModel<TInputValue,TOutputValue>
       itkExceptionMacro("Confidence index not available for this classifier !");
       }
     }
+  if (proba != nullptr && !this->m_ProbaIndex)
+    itkExceptionMacro("Probability per class not available for this classifier !");
+
   return target;
 }
 
diff --git a/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.h b/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.h
index 276e9ca3492d21db03d2872b38e4c80cc44002b9..adbade7db5d62c6d3aea1faf809461a01c5e751b 100644
--- a/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.h
+++ b/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.h
@@ -50,7 +50,7 @@ public:
   typedef typename Superclass::TargetSampleType           TargetSampleType;
   typedef typename Superclass::TargetListSampleType       TargetListSampleType;
   typedef typename Superclass::ConfidenceValueType        ConfidenceValueType;
-  
+  typedef typename Superclass::ProbaSampleType            ProbaSampleType;
   // Other
   typedef itk::VariableSizeMatrix<float>                VariableImportanceMatrixType;
 
@@ -137,8 +137,7 @@ protected:
   ~RandomForestsMachineLearningModel() override;
 
   /** Predict values using the model */
-  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr) const override;
-
+  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr, ProbaSampleType *proba=nullptr) const override;
   
   /** PrintSelf method */
   void PrintSelf(std::ostream& os, itk::Indent indent) const override;
diff --git a/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.hxx b/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.hxx
index 10508ead57bb89d90b76cc5675731ce864e7786b..a78f668fcbff653f4016f5cdb7a98fa28760951d 100644
--- a/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.hxx
+++ b/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.hxx
@@ -50,6 +50,7 @@ RandomForestsMachineLearningModel<TInputValue,TOutputValue>
   m_ComputeMargin(false)
 {
   this->m_ConfidenceIndex = true;
+  this->m_ProbaIndex = false;
   this->m_IsRegressionSupported = true;
 }
 
@@ -171,8 +172,9 @@ template <class TInputValue, class TOutputValue>
 typename RandomForestsMachineLearningModel<TInputValue,TOutputValue>
 ::TargetSampleType
 RandomForestsMachineLearningModel<TInputValue,TOutputValue>
-::DoPredict(const InputSampleType & value, ConfidenceValueType *quality) const
+::DoPredict(const InputSampleType & value, ConfidenceValueType *quality, ProbaSampleType *proba) const
 {
+  //std::cout << "Enter predict" << std::endl;
   TargetSampleType target;
   //convert listsample to Mat
   cv::Mat sample;
@@ -190,6 +192,10 @@ RandomForestsMachineLearningModel<TInputValue,TOutputValue>
     else
       (*quality) = m_RFModel->predict_confidence(sample);
     }
+
+  if (proba != nullptr && !this->m_ProbaIndex)
+    itkExceptionMacro("Probability per class not available for this classifier !");
+
   return target[0];
 }
 
diff --git a/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.h b/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.h
index dca029a2c8cf2b2a09cea9eb3162a100e7cbbe64..6fcc923971388bcd04c13f21ee89560296d023f4 100644
--- a/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.h
+++ b/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.h
@@ -60,7 +60,7 @@ public:
   typedef typename Superclass::TargetSampleType           TargetSampleType;
   typedef typename Superclass::TargetListSampleType       TargetListSampleType;
   typedef typename Superclass::ConfidenceValueType        ConfidenceValueType;
-
+  typedef typename Superclass::ProbaSampleType            ProbaSampleType;
   /** Run-time type information (and related methods). */
   itkNewMacro(Self);
   itkTypeMacro(SVMMachineLearningModel, MachineLearningModel);
@@ -141,8 +141,7 @@ protected:
   ~SVMMachineLearningModel() override;
 
   /** Predict values using the model */
-  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr) const override;
-
+  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr, ProbaSampleType *proba=nullptr) const override;
   
   /** PrintSelf method */
   void PrintSelf(std::ostream& os, itk::Indent indent) const override;
diff --git a/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.hxx b/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.hxx
index a52163ddee88a537e23fb2be5bb1244f34cee585..dc8d55dcddc2d04981b55fac4eabfc05418b0559 100644
--- a/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.hxx
+++ b/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.hxx
@@ -174,7 +174,7 @@ template <class TInputValue, class TOutputValue>
 typename SVMMachineLearningModel<TInputValue,TOutputValue>
 ::TargetSampleType
 SVMMachineLearningModel<TInputValue,TOutputValue>
-::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const
+::DoPredict(const InputSampleType & input, ConfidenceValueType *quality, ProbaSampleType *proba) const
 {
   TargetSampleType target;
   //convert listsample to Mat
@@ -198,7 +198,10 @@ SVMMachineLearningModel<TInputValue,TOutputValue>
     (*quality) = m_SVMModel->predict(sample,true);
 #endif
     }
-  return target;
+  if (proba != nullptr && !this->m_ProbaIndex)
+    itkExceptionMacro("Probability per class not available for this classifier !");
+
+return target;
 }
 
 template <class TInputValue, class TOutputValue>
diff --git a/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.h b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.h
index 836afb8411431d4633d2c0b997391ac477866c37..b80fc244f0448ca0729cfcd0ed491ab0c107b9cb 100644
--- a/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.h
+++ b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.h
@@ -86,7 +86,8 @@ public:
   typedef typename Superclass::ConfidenceValueType        ConfidenceValueType;
   typedef typename Superclass::ConfidenceSampleType       ConfidenceSampleType;
   typedef typename Superclass::ConfidenceListSampleType   ConfidenceListSampleType;
-  
+  typedef typename Superclass::ProbaSampleType             ProbaSampleType;
+  typedef typename Superclass::ProbaListSampleType        ProbaListSampleType;
   /** Run-time type information (and related methods). */
   itkNewMacro(Self);
   itkTypeMacro(SharkRandomForestsMachineLearningModel, MachineLearningModel);
@@ -155,10 +156,9 @@ protected:
   virtual ~SharkRandomForestsMachineLearningModel();
 
   /** Predict values using the model */
-  virtual TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr) const override;
-
+  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=nullptr, ProbaSampleType *proba=nullptr) const override;
   
-  virtual void DoPredictBatch(const InputListSampleType *, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType *, ConfidenceListSampleType * = nullptr) const override;
+  void DoPredictBatch(const InputListSampleType *, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType *, ConfidenceListSampleType * = nullptr, ProbaListSampleType * = nullptr) const override;
   
   /** PrintSelf method */
   void PrintSelf(std::ostream& os, itk::Indent indent) const override;
diff --git a/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.hxx b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.hxx
index 35dd418ed62b4f6efc5564c4fc69497dd73d000a..5f7726938e1993bfc1e9beaf007a133f34430082 100644
--- a/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.hxx
+++ b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.hxx
@@ -49,6 +49,7 @@ SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue>
 ::SharkRandomForestsMachineLearningModel()
 {
   this->m_ConfidenceIndex = true;
+  this->m_ProbaIndex = true;
   this->m_IsRegressionSupported = false;
   this->m_IsDoPredictBatchMultiThreaded = true;
   this->m_NormalizeClassLabels = true;
@@ -120,20 +121,32 @@ template <class TInputValue, class TOutputValue>
 typename SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue>
 ::TargetSampleType
 SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue>
-::DoPredict(const InputSampleType & value, ConfidenceValueType *quality) const
+::DoPredict(const InputSampleType & value, ConfidenceValueType *quality, ProbaSampleType *proba) const
 {
   shark::RealVector samples(value.Size());
   for(size_t i = 0; i < value.Size();i++)
     {
     samples.push_back(value[i]);
     }
-  if (quality != nullptr)
-    {
+  if (quality != nullptr || proba != nullptr)
+  {
     shark::RealVector probas = m_RFModel.decisionFunction()(samples);
-    (*quality) = ComputeConfidence(probas, m_ComputeMargin);
+    if (quality != nullptr)
+    {
+      (*quality) = ComputeConfidence(probas, m_ComputeMargin);
+    }
+    if (proba != nullptr)
+    {
+      for(size_t i =0; i< probas.size();i++)
+      {
+        //probas contain the N class probability indexed between 0 and N-1
+        (*proba)[i] = static_cast<unsigned int>(probas[i]*1000);
+      }
     }
+  }
   unsigned int res{0};
   m_RFModel.eval(samples, res);
+
   TargetSampleType target;
   if(m_NormalizeClassLabels)
     {
@@ -149,14 +162,15 @@ SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue>
 template <class TInputValue, class TOutputValue>
 void
 SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue>
-::DoPredictBatch(const InputListSampleType *input, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType * targets, ConfidenceListSampleType * quality) const
+::DoPredictBatch(const InputListSampleType *input, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType * targets, ConfidenceListSampleType * quality, ProbaListSampleType * proba) const
 {
   assert(input != nullptr);
   assert(targets != nullptr);
 
   assert(input->Size()==targets->Size()&&"Input sample list and target label list do not have the same size.");
   assert(((quality==nullptr)||(quality->Size()==input->Size()))&&"Quality samples list is not null and does not have the same size as input samples list");
-  
+  assert((proba==nullptr)||(input->Size()==proba->Size())&&"Proba sample list and target label list do not have the same size.");
+
   if(startIndex+size>input->Size())
     {
     itkExceptionMacro(<<"requested range ["<<startIndex<<", "<<startIndex+size<<"[ partially outside input sample list range.[0,"<<input->Size()<<"[");
@@ -168,11 +182,27 @@ SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue>
 
 #ifdef _OPENMP
   omp_set_num_threads(itk::MultiThreader::GetGlobalDefaultNumberOfThreads());
-#endif
-  
+
+  #endif
+  if( proba !=nullptr || quality != nullptr)
+  {
+    shark::Data<shark::RealVector> probas = m_RFModel.decisionFunction()(inputSamples);
+  if( proba !=nullptr)
+  {
+    unsigned int id = startIndex;
+    for(shark::RealVector && p : probas.elements())
+    {
+      ProbaSampleType prob{(unsigned int)p.size()};
+      for(size_t i =0; i< p.size();i++)
+      {
+        prob[i] =p[i]*1000;
+      }
+      proba->SetMeasurementVector(id,prob);
+      ++id;
+    }
+  }
   if(quality != nullptr)
     {
-    shark::Data<shark::RealVector> probas = m_RFModel.decisionFunction()(inputSamples);
     unsigned int id = startIndex;
     for(shark::RealVector && p : probas.elements())
       {
@@ -183,7 +213,8 @@ SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue>
       ++id;
       }
     }
-    
+  }
+
   auto prediction = m_RFModel(inputSamples);
   unsigned int id = startIndex;
   for(const auto& p : prediction.elements())
diff --git a/Modules/Learning/Supervised/src/otbCvRTreesWrapper.cxx b/Modules/Learning/Supervised/src/otbCvRTreesWrapper.cxx
index ddc3a821d8f3bb1b9aae69c2559f9b8af543dad1..7c62782107bd4b82a064e3bafc47e1bbcecad97a 100644
--- a/Modules/Learning/Supervised/src/otbCvRTreesWrapper.cxx
+++ b/Modules/Learning/Supervised/src/otbCvRTreesWrapper.cxx
@@ -140,7 +140,7 @@ float CvRTreesWrapper::predict_confidence(const cv::Mat& sample,
   float confidence = static_cast<float>(max_votes)/ntrees;
   return confidence;
 }
-
+  
 #ifdef OTB_OPENCV_3
 #define OTB_CV_WRAP_IMPL(type,name) \
 type CvRTreesWrapper::get##name() const \
diff --git a/Modules/Learning/Supervised/test/otbSharkImageClassificationFilter.cxx b/Modules/Learning/Supervised/test/otbSharkImageClassificationFilter.cxx
index 1753b05b36bcb3e96393a485707a7068e7725ee1..010781f1d25ec99c14e4f3468075344f57406057 100644
--- a/Modules/Learning/Supervised/test/otbSharkImageClassificationFilter.cxx
+++ b/Modules/Learning/Supervised/test/otbSharkImageClassificationFilter.cxx
@@ -100,16 +100,18 @@ void buildModel(unsigned int num_classes, unsigned int num_samples,
 
 int otbSharkImageClassificationFilter(int argc, char * argv[])
 {
-  if(argc<5 || argc>7)
+  if(argc<6 || argc>8)
     {
-    std::cout << "Usage: input_image output_image output_confidence batchmode [in_model_name] [mask_name]\n";
+    std::cout << "Usage: input_image output_image output_confidence output_proba batchmode [in_model_name] [mask_name]\n";
     }
   std::string imfname = argv[1];
   std::string outfname = argv[2];
   std::string conffname = argv[3]; 
-  bool batch = (std::string(argv[4])=="1");
+  std::string probafname = argv[4]; 
+  bool batch = (std::string(argv[5])=="1");
   std::string modelfname = "/tmp/rf_model.txt";
   std::string maskfname{};
+  int num_classes = 3;
 
   MaskReaderType::Pointer mask_reader = MaskReaderType::New();
   ReaderType::Pointer reader = ReaderType::New();
@@ -120,13 +122,15 @@ int otbSharkImageClassificationFilter(int argc, char * argv[])
 
   std::cout << "Image has " << num_features << " bands\n";
     
-  if(argc>5)
+  if(argc>6)
     {
-    modelfname = argv[5];
+    modelfname = argv[6];
+    // We don't know the number of classes, so we set it to a high number
+    num_classes = 10;
     }
   else
     {
-    buildModel(3, 1000, num_features, modelfname);
+    buildModel(num_classes, 1000, num_features, modelfname);
     }
 
   ClassificationFilterType::Pointer filter = ClassificationFilterType::New();
@@ -135,9 +139,10 @@ int otbSharkImageClassificationFilter(int argc, char * argv[])
   model->Load(modelfname);
   filter->SetModel(model);
   filter->SetInput(reader->GetOutput());
-  if(argc==7)
+  filter->SetNumberOfClasses(num_classes);
+  if(argc==8)
     {
-    maskfname = argv[6];
+    maskfname = argv[7];
     mask_reader->SetFileName(maskfname);
     filter->SetInputMask(mask_reader->GetOutput());
     }
@@ -148,6 +153,7 @@ int otbSharkImageClassificationFilter(int argc, char * argv[])
   std::cout << "Classification\n";
   filter->SetBatchMode(batch);
   filter->SetUseConfidenceMap(true);
+  filter->SetUseProbaMap(true);
   using TimeT = std::chrono::milliseconds;
   auto start = std::chrono::system_clock::now();
   writer->Update();
@@ -161,5 +167,35 @@ int otbSharkImageClassificationFilter(int argc, char * argv[])
   confWriter->SetFileName(conffname);
   confWriter->Update();
 
+  auto probaWriter = otb::ImageFileWriter<ClassificationFilterType::ProbaImageType>::New();
+  probaWriter->SetInput(filter->GetOutputProba());
+  probaWriter->SetFileName(probafname);
+  probaWriter->Update();
+
+  // Check that the chosen labels correspond to the max proba
+
+  itk::ImageRegionConstIterator<LabeledImageType> labIt(filter->GetOutput(), 
+                                                        filter->GetOutput()->GetLargestPossibleRegion());
+  itk::ImageRegionConstIterator<ClassificationFilterType::ProbaImageType> probIt(filter->GetOutputProba(), 
+                                                        filter->GetOutputProba()->GetLargestPossibleRegion());
+
+  for (labIt.GoToBegin(), probIt.GoToBegin(); !labIt.IsAtEnd();
+       ++labIt, ++probIt)
+    {
+      if(labIt.Get()>0) //Pixel is not masked
+      {
+      auto first = probIt.Get().GetDataPointer();
+      auto last = probIt.Get().GetDataPointer();
+      std::advance(last, num_classes);
+      auto max_proba = std::distance(first, std::max_element(first, last)) + 1;
+      if(labIt.Get() != max_proba)
+      {
+        std::cout << "Chosen label " << labIt.Get() << " and max proba position "
+                  << max_proba << " from " << probIt.Get() << " don't match\n";
+        return EXIT_FAILURE;
+      }
+      }
+    }
+
   return EXIT_SUCCESS;
 }
diff --git a/Modules/Learning/Supervised/test/tests-shark.cmake b/Modules/Learning/Supervised/test/tests-shark.cmake
index 87fbcbfc48077ea8fcbf0f07a6ea25b9da195e81..9c44f9eb23f428c88043aeb2cf8951373c33075b 100644
--- a/Modules/Learning/Supervised/test/tests-shark.cmake
+++ b/Modules/Learning/Supervised/test/tests-shark.cmake
@@ -46,6 +46,7 @@ otb_add_test(NAME leTvImageClassificationFilterSharkFast COMMAND  otbSupervisedT
   ${INPUTDATA}/Classification/QB_1_ortho.tif
   ${TEMP}/leSharkImageClassificationFilterOutput.tif
   ${TEMP}/leSharkImageClassificationFilterConfidence.tif
+  ${TEMP}/leSharkImageClassificationFilterProba.tif
   1
   ${INPUTDATA}/Classification/otbSharkImageClassificationFilter_RFmodel.txt
   )
@@ -72,6 +73,7 @@ otb_add_test(NAME leTvImageClassificationFilterSharkFastMask COMMAND  otbSupervi
   ${INPUTDATA}/Classification/QB_1_ortho.tif
   ${TEMP}/leSharkImageClassificationFilterWithMaskOutput.tif
   ${TEMP}/leSharkImageClassificationFilterWithMaskConfidence.tif
+  ${TEMP}/leSharkImageClassificationFilterWithMaskProba.tif
   1
   ${INPUTDATA}/Classification/otbSharkImageClassificationFilter_RFmodel.txt
   ${INPUTDATA}/Classification/QB_1_ortho_mask.tif
diff --git a/Modules/Learning/Unsupervised/include/otbSharkKMeansMachineLearningModel.h b/Modules/Learning/Unsupervised/include/otbSharkKMeansMachineLearningModel.h
index 05a408cd35b3c66fbdac66eefdc039b49ffe3d9e..873bb5e3578b2bdc4d1b0bc3c29a88563b9ef135 100644
--- a/Modules/Learning/Unsupervised/include/otbSharkKMeansMachineLearningModel.h
+++ b/Modules/Learning/Unsupervised/include/otbSharkKMeansMachineLearningModel.h
@@ -87,8 +87,8 @@ public:
   typedef typename Superclass::ConfidenceValueType        ConfidenceValueType;
   typedef typename Superclass::ConfidenceSampleType       ConfidenceSampleType;
   typedef typename Superclass::ConfidenceListSampleType   ConfidenceListSampleType;
-
-
+  typedef typename Superclass::ProbaSampleType             ProbaSampleType;
+  typedef typename Superclass::ProbaListSampleType        ProbaListSampleType;
   typedef shark::HardClusteringModel<shark::RealVector>   ClusteringModelType;
   typedef ClusteringModelType::OutputType                 ClusteringOutputType;
 
@@ -137,11 +137,10 @@ protected:
 
   /** Predict values using the model */
   virtual TargetSampleType
-  DoPredict(const InputSampleType &input, ConfidenceValueType *quality = nullptr) const override;
-
+  DoPredict(const InputSampleType &input, ConfidenceValueType *quality = nullptr, ProbaSampleType *proba=nullptr) const override;
 
   virtual void DoPredictBatch(const InputListSampleType *, const unsigned int &startIndex, const unsigned int &size,
-                              TargetListSampleType *, ConfidenceListSampleType * = nullptr) const override;
+                              TargetListSampleType *, ConfidenceListSampleType * = nullptr, ProbaListSampleType * = nullptr) const override;
 
   template<typename DataType>
   DataType NormalizeData(const DataType &data) const;
diff --git a/Modules/Learning/Unsupervised/include/otbSharkKMeansMachineLearningModel.hxx b/Modules/Learning/Unsupervised/include/otbSharkKMeansMachineLearningModel.hxx
index 1cd01e13c47a7d1187251e46dbf4d83ac109a5b5..82f16e23d7d75b924623ca67753f37038ee98dce 100644
--- a/Modules/Learning/Unsupervised/include/otbSharkKMeansMachineLearningModel.hxx
+++ b/Modules/Learning/Unsupervised/include/otbSharkKMeansMachineLearningModel.hxx
@@ -102,7 +102,7 @@ template<class TInputValue, class TOutputValue>
 typename SharkKMeansMachineLearningModel<TInputValue, TOutputValue>
 ::TargetSampleType
 SharkKMeansMachineLearningModel<TInputValue, TOutputValue>
-::DoPredict(const InputSampleType &value, ConfidenceValueType *quality) const
+::DoPredict(const InputSampleType &value, ConfidenceValueType *quality, ProbaSampleType *proba) const
 {
   shark::RealVector data( value.Size());
   for( size_t i = 0; i < value.Size(); i++ )
@@ -117,6 +117,13 @@ SharkKMeansMachineLearningModel<TInputValue, TOutputValue>
     ( *quality ) = ConfidenceValueType( 1.);
     }
 
+  if (proba != nullptr)
+    {
+    if (!this->m_ProbaIndex)
+      {
+      itkExceptionMacro("Probability per class not available for this classifier !");
+      }
+    }
   TargetSampleType target;
   ClusteringOutputType predictedValue = (*m_ClusteringModel)( data );
   target[0] = static_cast<TOutputValue>(predictedValue);
@@ -130,7 +137,8 @@ SharkKMeansMachineLearningModel<TInputValue, TOutputValue>
                  const unsigned int &startIndex,
                  const unsigned int &size,
                  TargetListSampleType *targets,
-                 ConfidenceListSampleType *quality) const
+                 ConfidenceListSampleType *quality,
+		 ProbaListSampleType * proba) const
 {
 
   // Perform check on input values
@@ -180,6 +188,10 @@ SharkKMeansMachineLearningModel<TInputValue, TOutputValue>
       quality->SetMeasurementVector( qid, static_cast<ConfidenceValueType>(1.) );
       }
     }
+  if (proba !=nullptr && !this->m_ProbaIndex)
+    {
+      itkExceptionMacro("Probability per class not available for this classifier !");
+    }
 }
 
 
diff --git a/Modules/Radiometry/SARCalibration/include/otbSarBurstExtractionImageFilter.h b/Modules/Radiometry/SARCalibration/include/otbSarBurstExtractionImageFilter.h
new file mode 100644
index 0000000000000000000000000000000000000000..420870e469a40ad3516fb25131ce9f4c902abc9c
--- /dev/null
+++ b/Modules/Radiometry/SARCalibration/include/otbSarBurstExtractionImageFilter.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef otbSarBurstExtractionImageFilter_h
+#define otbSarBurstExtractionImageFilter_h
+
+#include "itkImageToImageFilter.h"
+#include "itkSmartPointer.h"
+
+namespace otb
+{
+/** \class SarBurstExtractionImageFilter 
+ * \brief Performs a burst extraction by keeping only lines and samples
+ * of a required Burst
+ * 
+ * This filter performs a burst extraction by keeping only lines and samples
+ * of a required burst. This operation is useful when dealing with
+ * Sentinel1 IW SLC products, where each subswath is composed of
+ * several overlapping burst separated by black lines. The aim is to separate
+ * bursts to be able to process each burst independently.
+ * The output image represents only one burst and is smaller in azimuth and range 
+ * direction than the input line. This filter is the perfect preprocessing step
+ * to process each burst of S1 IW SLC product with OTB without suffering from
+ * artifacts caused by bursts separation.
+ * 
+ * Note that currently only Sentinel1 IW SLC products are supported.
+ * 
+ * \ingroup OTBSARCalibration
+ */
+
+template <class TImage> class ITK_EXPORT SarBurstExtractionImageFilter :
+    public itk::ImageToImageFilter<TImage,TImage>
+{
+public:
+  // Standard class typedefs
+  typedef SarBurstExtractionImageFilter                  Self;
+  typedef itk::ImageToImageFilter<TImage,TImage> Superclass;
+  typedef itk::SmartPointer<Self>                Pointer;
+  typedef itk::SmartPointer<const Self>          ConstPointer;
+
+  itkNewMacro(Self);
+  itkTypeMacro(SarBurstExtractionImageFilter,ImageToImageFilter);
+
+  typedef TImage                                 ImageType;
+  typedef typename ImageType::RegionType         RegionType;
+  typedef typename ImageType::PointType          PointType;
+
+  typedef std::pair<unsigned long, unsigned long> RecordType;
+  typedef std::vector<RecordType>            LinesRecordVectorType;
+
+  // Setter
+  itkSetMacro(BurstIndex, unsigned int);
+  itkSetMacro(AllPixels, bool);
+
+protected:
+  // Constructor
+  SarBurstExtractionImageFilter();
+
+  // Destructor
+  ~SarBurstExtractionImageFilter() override = default;
+
+  // Needs to be re-implemented since size of output is modified
+  virtual void GenerateOutputInformation() override;
+
+  // Needs to be re-implemented since size of output is modified
+  virtual void GenerateInputRequestedRegion() override;
+
+  // Actual processing
+  virtual void ThreadedGenerateData(const RegionType& outputRegionForThread, itk::ThreadIdType threadId) override;
+
+  RegionType OutputRegionToInputRegion(const RegionType& outputRegion) const;
+  
+private:
+  SarBurstExtractionImageFilter(const Self&) = delete;
+  void operator=(const Self &) = delete;
+  
+  // Pair for sample valid selection
+  RecordType m_LinesRecord;
+
+  // Pair for sample valid selection
+  RecordType m_SamplesRecord;
+
+  // Burst index
+  unsigned int m_BurstIndex;
+
+  // Mode for extraction : 
+  // If true : all pixels of the burst are selected
+  // If false : only valid pixels are selected
+  bool m_AllPixels;  
+};
+
+} // End namespace otb
+
+#ifndef OTB_MANUAL_INSTANTIATION
+#include "otbSarBurstExtractionImageFilter.hxx"
+#endif
+
+
+
+#endif
diff --git a/Modules/Radiometry/SARCalibration/include/otbSarBurstExtractionImageFilter.hxx b/Modules/Radiometry/SARCalibration/include/otbSarBurstExtractionImageFilter.hxx
new file mode 100644
index 0000000000000000000000000000000000000000..b4c7d2f5545dfab2ff06d46049643f2f82813319
--- /dev/null
+++ b/Modules/Radiometry/SARCalibration/include/otbSarBurstExtractionImageFilter.hxx
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef otbSarBurstExtractionImageFilter_hxx
+#define otbSarBurstExtractionImageFilter_hxx
+
+#include "otbSarBurstExtractionImageFilter.h"
+
+#include "otbSarSensorModelAdapter.h"
+#include "otbImageKeywordlist.h"
+#include "itkImageScanlineIterator.h"
+#include "itkImageScanlineConstIterator.h"
+#include "itkImageRegionIterator.h"
+#include "itkImageRegionConstIterator.h"
+
+namespace otb
+{
+// Constructor
+template <class TImage> SarBurstExtractionImageFilter<TImage>::SarBurstExtractionImageFilter()
+  : m_LinesRecord(), m_SamplesRecord(), m_BurstIndex(0), m_AllPixels(false)
+{}
+
+// Needs to be re-implemented since size of output is modified
+template< class TImage>
+void
+SarBurstExtractionImageFilter<TImage>::GenerateOutputInformation()
+{
+  // Call superclass implementation
+  Superclass::GenerateOutputInformation();
+
+  // Retrieve the input image pointer
+  const ImageType * inputPtr = this->GetInput();
+  ImageType * outputPtr = this->GetOutput();
+
+  // Check that azimuth spacing has not been modified
+  if(std::abs(inputPtr->GetSignedSpacing()[1]-1.)>=std::numeric_limits<double>::epsilon())
+    itkExceptionMacro("Can not perform deburst if input image azimuth spacing is not 1.");
+  
+  // Check that the azimuth sampling grid has not been modified
+  if(std::abs(inputPtr->GetOrigin()[1]-static_cast<long>(inputPtr->GetOrigin()[1])-0.5)>=std::numeric_limits<double>::epsilon())
+    itkExceptionMacro("Can not perform burst extraction if input image azimuth origin is not N.5");
+  
+  // Retrieve input image keywordlist
+  ImageKeywordlist inputKwl = inputPtr->GetImageKeywordlist();
+  
+  // Try to create a SarSensorModelAdapter
+  SarSensorModelAdapter::Pointer sarSensorModel = SarSensorModelAdapter::New();
+  bool loadOk = sarSensorModel->LoadState(inputKwl);
+
+  if(!loadOk || !sarSensorModel->IsValidSensorModel())
+    itkExceptionMacro(<<"Input image does not contain a valid SAR sensor model.");
+  
+  // Try to call the burst extraction function
+  bool burstExtractionOk = sarSensorModel->BurstExtraction(m_BurstIndex, m_LinesRecord, m_SamplesRecord, 
+							   m_AllPixels);
+
+  if(!burstExtractionOk)
+    itkExceptionMacro(<<"Could not etract Burst from input image");
+  
+  // Compute the actual lines to remove
+  typename ImageType::RegionType largestPossibleRegion = this->GetInput()->GetLargestPossibleRegion();
+  typename ImageType::PointType origin = this->GetInput()->GetOrigin();
+
+  // Export the new keywordlist
+  ImageKeywordlist newKwl;
+
+  bool saveOk = sarSensorModel->SaveState(newKwl);
+
+  if(!saveOk)
+    itkExceptionMacro(<<"Could not export deburst SAR sensor model to keyword list");
+
+  // Move origin and size (if necessary)
+  long originOffset_samples = static_cast<long>(this->GetInput()->GetOrigin()[0]-0.5);
+  long originOffset_lines = static_cast<long>(this->GetInput()->GetOrigin()[1]-0.5);
+  unsigned long outputOriginSample = 0;
+  unsigned long outputOriginLine = 0;
+
+  typename ImageType::SizeType burstSize = largestPossibleRegion.GetSize();
+  
+  if (static_cast<int>(m_SamplesRecord.first) > originOffset_samples)
+    {
+      outputOriginSample = 0;
+    }
+  else
+    {
+      outputOriginSample = originOffset_samples - static_cast<int>(m_SamplesRecord.first);
+    }
+
+  if (static_cast<int>(m_LinesRecord.first) > originOffset_lines)
+    {
+      outputOriginLine = 0;
+    }
+  else
+    {
+      outputOriginLine = originOffset_lines - static_cast<int>(m_LinesRecord.first);
+    }
+
+  long firstOutSample = static_cast<long>(std::max( static_cast<long>(m_SamplesRecord.first), originOffset_samples));
+  long secondOutSample = static_cast<long>(std::min(static_cast<long>(m_SamplesRecord.second), 
+						    static_cast<long>(largestPossibleRegion.GetSize()[0] + 
+								      originOffset_samples - 1)));
+
+  long firstOutLine = static_cast<long>(std::max(static_cast<long>(m_LinesRecord.first), originOffset_lines));
+  long secondOutLine = static_cast<long>(std::min(static_cast<long>(m_LinesRecord.second), 
+						  static_cast<long>(largestPossibleRegion.GetSize()[1] + 
+								    originOffset_lines - 1)));
+
+  burstSize[0] = secondOutSample - firstOutSample + 1;
+  burstSize[1] = secondOutLine - firstOutLine + 1;
+  
+  origin[0]=0.5+outputOriginSample;
+  origin[1]=0.5+outputOriginLine;
+  
+  outputPtr->SetOrigin(origin);
+ 
+  // Set largest possible region
+  typename ImageType::RegionType outputLargestPossibleRegion = largestPossibleRegion;
+  largestPossibleRegion.SetSize(burstSize);
+  outputPtr->SetLargestPossibleRegion(largestPossibleRegion);
+
+  newKwl.AddKey("support_data.number_samples", std::to_string(burstSize[0]));
+  newKwl.AddKey("support_data.number_lines", std::to_string(burstSize[1]));
+
+  newKwl.AddKey("number_samples", std::to_string(burstSize[0]));
+  newKwl.AddKey("number_lines", std::to_string(burstSize[1]));
+  
+  // Set new keyword list to output image
+  outputPtr->SetImageKeywordList(newKwl);
+}
+
+template<class TImage>
+typename SarBurstExtractionImageFilter<TImage>::RegionType
+SarBurstExtractionImageFilter<TImage>::OutputRegionToInputRegion(const RegionType& outputRegion) const
+{
+  RegionType inputRegion = outputRegion;
+
+  typename RegionType::IndexType index = inputRegion.GetIndex();
+  
+  long originOffset = static_cast<long>(this->GetInput()->GetOrigin()[1]-0.5);
+  long originOffset_samples = static_cast<long>(this->GetInput()->GetOrigin()[0]-0.5);
+
+  if (static_cast<int>(m_SamplesRecord.first) > originOffset_samples)
+    {
+      index[0] += m_SamplesRecord.first - originOffset_samples;
+    }
+  if (static_cast<int>(m_LinesRecord.first) > originOffset)
+    {
+      index[1] += m_LinesRecord.first - originOffset;
+    }
+
+  inputRegion.SetIndex(index);
+  
+  return inputRegion;
+}
+
+  
+// Needs to be re-implemented since size of output is modified
+template <class TImage> void SarBurstExtractionImageFilter<TImage>::GenerateInputRequestedRegion()
+{
+  RegionType outputRequestedRegion = this->GetOutput()->GetRequestedRegion();
+  RegionType inputRequestedRegion = OutputRegionToInputRegion(outputRequestedRegion);
+
+  ImageType * inputPtr = const_cast<ImageType *>(this->GetInput());
+  
+  inputPtr->SetRequestedRegion(inputRequestedRegion);
+}
+
+
+// Actual processing
+template <class TImage> 
+void 
+SarBurstExtractionImageFilter<TImage>::ThreadedGenerateData(const RegionType& outputRegionForThread, 
+						    itk::ThreadIdType itkNotUsed(threadId))
+{
+  // Compute corresponding input region
+  RegionType inputRegionForThread = OutputRegionToInputRegion(outputRegionForThread);
+  
+  itk::ImageRegionConstIterator<ImageType> inputIt(this->GetInput(),inputRegionForThread);
+  itk::ImageRegionIterator<ImageType> outputIt(this->GetOutput(),outputRegionForThread);
+
+  inputIt.GoToBegin();
+  outputIt.GoToBegin();
+
+  int linesRecordFirst = static_cast<int>(m_LinesRecord.first);
+  int linesRecordSecond = static_cast<int>(m_LinesRecord.second);
+  int samplesRecordFirst = static_cast<int>(m_SamplesRecord.first);
+  int samplesRecordSecond = static_cast<int>(m_SamplesRecord.second);
+
+  while(!inputIt.IsAtEnd()&&!outputIt.IsAtEnd())
+    {
+      typename ImageType::IndexType currentInputIndex = inputIt.GetIndex();
+      PointType currentInputPoint;
+      this->GetInput()->TransformIndexToPhysicalPoint(currentInputIndex,currentInputPoint);
+  
+      bool lineToKeep = false;
+      bool sampleToKeep = false;
+
+      // Check lines
+      if (currentInputPoint[1]-0.5 >= linesRecordFirst && 
+	  currentInputPoint[1]-0.5 <= linesRecordSecond)
+	{
+	  lineToKeep = true;
+	}
+
+      // Check samples
+      if (currentInputPoint[0]-0.5 >= samplesRecordFirst && 
+	  currentInputPoint[0]-0.5 <= samplesRecordSecond)
+	{
+	  sampleToKeep = true;
+	} 
+
+      // If ok, copy input pixel into output image
+      if(lineToKeep && sampleToKeep)
+	{
+	  outputIt.Set(inputIt.Get());
+
+	  ++outputIt;
+	}
+
+      ++inputIt;
+    }  
+}
+
+} // End namespace otb
+
+#endif
diff --git a/Modules/Radiometry/SARCalibration/include/otbSarConcatenateBurstsImageFilter.h b/Modules/Radiometry/SARCalibration/include/otbSarConcatenateBurstsImageFilter.h
new file mode 100644
index 0000000000000000000000000000000000000000..f7960a9b91d56f42a615f4fcac412231d8b33a48
--- /dev/null
+++ b/Modules/Radiometry/SARCalibration/include/otbSarConcatenateBurstsImageFilter.h
@@ -0,0 +1,115 @@
+ /*
+ * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef otbSarConcatenateBurstsImageFilter_h
+#define otbSarConcatenateBurstsImageFilter_h
+
+#include "itkImageToImageFilter.h"
+#include "otbTileImageFilter.h"
+#include "otbImageKeywordlist.h"
+
+namespace otb
+{
+/** \class SarConcatenateBurstsImageFilter
+ *  \brief This filter allows making a spatial mosaic from a set of bursts
+ *
+ *  This filter derives from TileImagefilter and produces a spatial mosaic from a set of bursts 
+ *  from Sentinel-1 IW products . The layout parameter allows setting up of the images will 
+ *  be patched together: it is a 2D array containing the number of images in the horizontal
+ *  direction and vertical direction respectively.
+ *
+ *  Images can be set using the PushBackInput() or SetInput(unsigned
+ *  int, Image *) methods. Please note that input images are supposed
+ *  to be set in the lexicographical order.
+ *
+ *  This filter does not support missing images: the number of input
+ *  images must match exactly layout[0]*layout[1]. Additional
+ *  consistency checks are that the number of components and spacing
+ *  must be consistent for all images, and the size of the images must
+ *  match with each others.
+ *  
+ *  Metadata are adapted in order to correspond to the contatenated SAR image.
+ *
+ * \ingroup OTBSARCalibration
+ * \ingroup MultiThreaded
+ *
+ * \ingroup OTBImageManipulation
+ */
+template <class TImage>
+class ITK_EXPORT SarConcatenateBurstsImageFilter :
+    public TileImageFilter<TImage>
+{
+public:
+  /** Standard class typedef */
+  typedef SarConcatenateBurstsImageFilter         Self;
+  typedef TileImageFilter<TImage>             Superclass;
+  typedef itk::SmartPointer<Self>                 Pointer;
+  typedef itk::SmartPointer<const Self>           ConstPointer;
+
+  /** Helper typedefs */
+  typedef TImage                                  ImageType;
+  typedef typename ImageType::Pointer             ImagePointerType;
+  typedef typename ImageType::SizeType            SizeType;
+  typedef typename ImageType::RegionType          RegionType;
+
+  typedef std::pair<unsigned long, unsigned long> RecordType;
+  typedef std::vector<RecordType>            LinesRecordVectorType;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(SarConcatenateBurstsImageFilter, TileImageFilter);
+
+  // Setter
+  void SetSLCImageKeyWorList(ImageKeywordlist sarImageKWL);
+
+  bool getDeburstLinesAndSamples(LinesRecordVectorType & linesRecord, LinesRecordVectorType & samplesRecord);
+
+protected:
+  /** Constructor */
+  SarConcatenateBurstsImageFilter() = default;
+
+  /** Destructor */
+  ~SarConcatenateBurstsImageFilter() = default;
+
+  /** Generate input requested region method */
+  void GenerateOutputInformation() override;
+
+
+private:
+  SarConcatenateBurstsImageFilter(const Self &) = delete;
+  void operator =(const Self&) = delete;
+
+  // SLC KeywordList
+  ImageKeywordlist m_SLCImageKWL;
+
+  // Deburst SLC KeywordList
+  ImageKeywordlist m_DeburstSLCImageKWL;
+};
+
+} // end namespace itk
+
+#ifndef OTB_MANUAL_INSTANTIATION
+#include "otbSarConcatenateBurstsImageFilter.hxx"
+#endif
+
+#endif
diff --git a/Modules/Radiometry/SARCalibration/include/otbSarConcatenateBurstsImageFilter.hxx b/Modules/Radiometry/SARCalibration/include/otbSarConcatenateBurstsImageFilter.hxx
new file mode 100644
index 0000000000000000000000000000000000000000..b88468459ea0b1af4f63caee7c6b32b0eefbc156
--- /dev/null
+++ b/Modules/Radiometry/SARCalibration/include/otbSarConcatenateBurstsImageFilter.hxx
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef otbSarConcatenateBurstsImageFilter_hxx
+#define otbSarConcatenateBurstsImageFilter_hxx
+
+#include "otbSarConcatenateBurstsImageFilter.h"
+#include "itkImageRegionIterator.h"
+#include "otbSarSensorModelAdapter.h"
+
+namespace otb
+{
+template <class TImage>
+void
+SarConcatenateBurstsImageFilter<TImage>
+::SetSLCImageKeyWorList(ImageKeywordlist sarImageKWL)
+{
+  m_SLCImageKWL = sarImageKWL;
+}
+
+template <class TImage>
+bool 
+SarConcatenateBurstsImageFilter<TImage>
+::getDeburstLinesAndSamples(LinesRecordVectorType & linesRecord, LinesRecordVectorType & samplesRecord)
+{
+  // Try to create a SarSensorModelAdapter
+  SarSensorModelAdapter::Pointer sarSensorModel = SarSensorModelAdapter::New();
+
+  bool loadOk = sarSensorModel->LoadState(m_SLCImageKWL);
+
+  if(!loadOk || !sarSensorModel->IsValidSensorModel())
+    itkExceptionMacro(<<"Input image does not contain a valid SAR sensor model.");
+  
+  // Try to call the deburstAndConcatenate function
+  bool deburstAndConcatenateOk = sarSensorModel->DeburstAndConcatenate(linesRecord, samplesRecord);
+
+  if(!deburstAndConcatenateOk)
+    itkExceptionMacro(<<"Could not deburst or concatenate from input bursts");
+
+  // Export the new keywordlist
+  bool saveOk = sarSensorModel->SaveState(m_DeburstSLCImageKWL);
+
+  if(!saveOk)
+    itkExceptionMacro(<<"Could not export deburst SAR sensor model to keyword list");
+
+  return true;
+}
+
+template <class TImage>
+void
+SarConcatenateBurstsImageFilter<TImage>
+::GenerateOutputInformation()
+{
+  // First, call superclass implementation
+  Superclass::GenerateOutputInformation();
+
+  // Output KeywordList
+  ImageType * outputPtr = this->GetOutput();
+
+  m_DeburstSLCImageKWL.AddKey("support_data.number_samples", std::to_string(this->GetOutput()->
+									    GetLargestPossibleRegion().
+									    GetSize()[0]));
+  m_DeburstSLCImageKWL.AddKey("support_data.number_lines", std::to_string(this->GetOutput()->
+									  GetLargestPossibleRegion().
+									  GetSize()[1]));
+
+  m_DeburstSLCImageKWL.AddKey("number_samples", std::to_string(this->GetOutput()->
+									    GetLargestPossibleRegion().
+									    GetSize()[0]));
+  m_DeburstSLCImageKWL.AddKey("number_lines", std::to_string(this->GetOutput()->
+									  GetLargestPossibleRegion().
+									  GetSize()[1]));
+  
+  // Set new keyword list to output image  
+  outputPtr->SetImageKeywordList(m_DeburstSLCImageKWL);
+}
+
+
+} // end namepsace otb
+
+#endif
diff --git a/Modules/Radiometry/SARCalibration/include/otbSarDeburstImageFilter.h b/Modules/Radiometry/SARCalibration/include/otbSarDeburstImageFilter.h
index 6b771c9dbfa6052d49104cc93303a85d3572a800..5489259e10fd06dfdf67a5a0620c9f174a6c0527 100644
--- a/Modules/Radiometry/SARCalibration/include/otbSarDeburstImageFilter.h
+++ b/Modules/Radiometry/SARCalibration/include/otbSarDeburstImageFilter.h
@@ -62,8 +62,11 @@ public:
   typedef typename ImageType::RegionType         RegionType;
   typedef typename ImageType::PointType          PointType;
 
-  typedef std::pair<unsigned long, unsigned long> LinesRecordType;
-  typedef std::vector<LinesRecordType>            LinesRecordVectorType;
+  typedef std::pair<unsigned long, unsigned long> RecordType;
+  typedef std::vector<RecordType>                 LinesRecordVectorType;
+	
+  // Setter
+  itkSetMacro(OnlyValidSample, bool);
   
 protected:
   // Constructor
@@ -81,6 +84,9 @@ protected:
   // Actual processing
   virtual void ThreadedGenerateData(const RegionType& outputRegionForThread, itk::ThreadIdType threadId) override;
 
+  void ThreadedGenerateDataWithAllSamples(const RegionType& outputRegionForThread, itk::ThreadIdType threadId);
+  void ThreadedGenerateDataWithOnlyValidSamples(const RegionType& outputRegionForThread, itk::ThreadIdType threadId);
+
   RegionType OutputRegionToInputRegion(const RegionType& outputRegion) const;
   
 private:
@@ -89,7 +95,12 @@ private:
 
   // Vector of line records
   LinesRecordVectorType m_LinesRecord;
-  
+
+  // Pair for sample valid selection
+  RecordType m_SamplesRecord;
+
+  bool m_OnlyValidSample;
+ 
 };
 
 } // End namespace otb
diff --git a/Modules/Radiometry/SARCalibration/include/otbSarDeburstImageFilter.hxx b/Modules/Radiometry/SARCalibration/include/otbSarDeburstImageFilter.hxx
index d9de620dba6c6643f22426cb45f4ca74bed45232..c51edd2fb1714b65ec48892f611f46ec5dd6028a 100644
--- a/Modules/Radiometry/SARCalibration/include/otbSarDeburstImageFilter.hxx
+++ b/Modules/Radiometry/SARCalibration/include/otbSarDeburstImageFilter.hxx
@@ -27,12 +27,14 @@
 #include "otbImageKeywordlist.h"
 #include "itkImageScanlineIterator.h"
 #include "itkImageScanlineConstIterator.h"
+#include "itkImageRegionIterator.h"
+#include "itkImageRegionConstIterator.h"
 
 namespace otb
 {
 // Constructor
 template <class TImage> SarDeburstImageFilter<TImage>::SarDeburstImageFilter()
-  : m_LinesRecord()
+  : m_LinesRecord(), m_SamplesRecord(), m_OnlyValidSample(false)
 {}
 
 // Needs to be re-implemented since size of output is modified
@@ -66,7 +68,7 @@ SarDeburstImageFilter<TImage>::GenerateOutputInformation()
     itkExceptionMacro(<<"Input image does not contain a valid SAR sensor model.");
   
   // Try to call the deburst function
-  bool deburstOk = sarSensorModel->Deburst(m_LinesRecord);
+  bool deburstOk = sarSensorModel->Deburst(m_LinesRecord, m_SamplesRecord, m_OnlyValidSample);
 
   if(!deburstOk || m_LinesRecord.empty())
     itkExceptionMacro(<<"Could not deburst SAR sensor model from input image");
@@ -83,9 +85,6 @@ SarDeburstImageFilter<TImage>::GenerateOutputInformation()
   if(!saveOk)
     itkExceptionMacro(<<"Could not export deburst SAR sensor model to keyword list");
 
-  // Set new keyword list to output image
-  outputPtr->SetImageKeywordList(newKwl);
-
   // Now, filter the LinesRecord so as to account for possible
   // extracts on input image
   long firstInputLine = static_cast<long>(origin[1]-0.5);
@@ -97,7 +96,20 @@ SarDeburstImageFilter<TImage>::GenerateOutputInformation()
   unsigned long outputOriginLine = 0;
   SarSensorModelAdapter::ImageLineToDeburstLine(m_LinesRecord,firstInputLine,outputOriginLine);
 
-  // std::cout<<"OutputOriginLine: "<<outputOriginLine<<std::endl;
+  long originOffset_samples = static_cast<long>(this->GetInput()->GetOrigin()[0]-0.5);
+  unsigned long outputOriginSample = 0;
+  if (m_OnlyValidSample)
+    {
+      if (static_cast<int>(m_SamplesRecord.first) > originOffset_samples)
+	{
+	  outputOriginSample = 0;
+	}
+      else
+	{
+	  outputOriginSample = originOffset_samples - static_cast<int>(m_SamplesRecord.first);
+	}
+        origin[0]=0.5+outputOriginSample;
+    }
   
   origin[1]=0.5+outputOriginLine;
   outputPtr->SetOrigin(origin);
@@ -111,9 +123,9 @@ SarDeburstImageFilter<TImage>::GenerateOutputInformation()
     // If record is inside input image region
     if((long)it->first<=lastInputLine && (long)it->second>=firstInputLine)
       {
-      LinesRecordType filteredRecord = *it;
-      filteredRecord.first = std::max((long)filteredRecord.first,firstInputLine);
-      filteredRecord.second = std::min((long)filteredRecord.second,lastInputLine);
+      RecordType filteredRecord = *it;
+      filteredRecord.first = std::max(static_cast<long>(filteredRecord.first),firstInputLine);
+      filteredRecord.second = std::min(static_cast<long>(filteredRecord.second),lastInputLine);
       filteredRecords.push_back(filteredRecord);
       }
     }
@@ -123,6 +135,8 @@ SarDeburstImageFilter<TImage>::GenerateOutputInformation()
 
   // TODO: Ensure that records are sorted ?
 
+  
+
   // Compute deburst azimuth size
   typename ImageType::SizeType deburstSize = largestPossibleRegion.GetSize();
   deburstSize[1]=0;
@@ -134,10 +148,28 @@ SarDeburstImageFilter<TImage>::GenerateOutputInformation()
     deburstSize[1]+=it->second-it->first+1;
     }
 
+  if (m_OnlyValidSample)
+    {
+      long minEnd = static_cast<long>(std::min(static_cast<long>(m_SamplesRecord.second), 
+					       static_cast<long>(largestPossibleRegion.GetSize()[0] + originOffset_samples-1)));
+      long maxStart = static_cast<long>(std::max(static_cast<long>(m_SamplesRecord.first), 
+						 originOffset_samples));
+      deburstSize[0] = minEnd  - maxStart + 1;
+    }
+
   // Set largest possible region
   typename ImageType::RegionType outputLargestPossibleRegion = largestPossibleRegion;
   largestPossibleRegion.SetSize(deburstSize);
   outputPtr->SetLargestPossibleRegion(largestPossibleRegion);
+
+  newKwl.AddKey("support_data.number_samples", std::to_string(deburstSize[0]));
+  newKwl.AddKey("support_data.number_lines", std::to_string(deburstSize[1]));
+  
+  newKwl.AddKey("number_samples", std::to_string(deburstSize[0]));
+  newKwl.AddKey("number_lines", std::to_string(deburstSize[1]));
+
+  // Set new keyword list to output image
+  outputPtr->SetImageKeywordList(newKwl);
 }
 
 template<class TImage>
@@ -163,6 +195,7 @@ SarDeburstImageFilter<TImage>::OutputRegionToInputRegion(const RegionType& outpu
   SarSensorModelAdapter::DeburstLineToImageLine(m_LinesRecord,lowerLeftLine,inputLowerLeftLine);
   
   long originOffset = static_cast<long>(this->GetInput()->GetOrigin()[1]-0.5);
+  long originOffset_samples = static_cast<long>(this->GetInput()->GetOrigin()[0]-0.5);
   
   inputUpperLeftLine-=originOffset;
   inputLowerLeftLine-=originOffset;
@@ -171,6 +204,14 @@ SarDeburstImageFilter<TImage>::OutputRegionToInputRegion(const RegionType& outpu
 
   typename RegionType::SizeType size = inputRegion.GetSize();
   typename RegionType::IndexType index = inputRegion.GetIndex();
+
+  if (m_OnlyValidSample)
+    {
+      if (static_cast<int>(m_SamplesRecord.first) > originOffset_samples)
+	{
+	  index[0]+= m_SamplesRecord.first - originOffset_samples;
+	}
+    }
   
   index[1]=inputUpperLeftLine;
   size[1]=inputLowerLeftLine-inputUpperLeftLine+1;
@@ -194,7 +235,26 @@ template <class TImage> void SarDeburstImageFilter<TImage>::GenerateInputRequest
 }
 
 // Actual processing
-template <class TImage> void SarDeburstImageFilter<TImage>::ThreadedGenerateData(const RegionType& outputRegionForThread, itk::ThreadIdType itkNotUsed(threadId))
+template <class TImage> 
+void 
+SarDeburstImageFilter<TImage>::ThreadedGenerateData(const RegionType& outputRegionForThread, 
+						    itk::ThreadIdType itkNotUsed(threadId))
+{
+  if (m_OnlyValidSample)
+    {
+      this->ThreadedGenerateDataWithOnlyValidSamples(outputRegionForThread, 0);
+    }
+  else
+    {
+      this->ThreadedGenerateDataWithAllSamples(outputRegionForThread, 0);
+    }
+}
+
+// Actual processing with all samples
+template <class TImage> 
+void 
+SarDeburstImageFilter<TImage>::ThreadedGenerateDataWithAllSamples(const RegionType& outputRegionForThread, 
+								  itk::ThreadIdType itkNotUsed(threadId))
 {
   // Compute corresponding input region
   RegionType inputRegionForThread = OutputRegionToInputRegion(outputRegionForThread);
@@ -213,25 +273,24 @@ template <class TImage> void SarDeburstImageFilter<TImage>::ThreadedGenerateData
 
     bool lineToKeep = false;
 
-    for(LinesRecordVectorType::const_iterator it  = m_LinesRecord.begin();
-      it!=m_LinesRecord.end();++it)
-      {
-      if(currentInputPoint[1]-0.5>=it->first && currentInputPoint[1]-0.5<=it->second)
-        {
-        lineToKeep = true;
-        break;
-        }
-      }
+    for (auto const& record : m_LinesRecord)
+	{
+	  if (currentInputPoint[1]-0.5>=record.first && currentInputPoint[1]-0.5<=record.second)
+	    {
+	      lineToKeep = true;
+	      break;
+	    }
+	}
     if(lineToKeep)
       {
-      for(inputIt.GoToBeginOfLine(),outputIt.GoToBeginOfLine();
-          !inputIt.IsAtEndOfLine() && !outputIt.IsAtEndOfLine();
-          ++inputIt,++outputIt)
-        {
-        outputIt.Set(inputIt.Get());
-
-        }
-      outputIt.NextLine();
+	for(inputIt.GoToBeginOfLine(),outputIt.GoToBeginOfLine();
+	    !inputIt.IsAtEndOfLine() && !outputIt.IsAtEndOfLine();
+	    ++inputIt,++outputIt)
+	  {
+	    outputIt.Set(inputIt.Get());
+
+	  }
+	outputIt.NextLine();
       }
     
 
@@ -239,6 +298,58 @@ template <class TImage> void SarDeburstImageFilter<TImage>::ThreadedGenerateData
     }  
 }
 
+// Actual processing with only valid samples
+template <class TImage> 
+void 
+SarDeburstImageFilter<TImage>::ThreadedGenerateDataWithOnlyValidSamples(const RegionType& outputRegionForThread, 
+									itk::ThreadIdType itkNotUsed(threadId))
+{
+  // Compute corresponding input region
+  RegionType inputRegionForThread = OutputRegionToInputRegion(outputRegionForThread);
+  
+  itk::ImageRegionConstIterator<ImageType> inputIt(this->GetInput(),inputRegionForThread);
+  itk::ImageRegionIterator<ImageType> outputIt(this->GetOutput(),outputRegionForThread);
+
+  inputIt.GoToBegin();
+  outputIt.GoToBegin();
+
+  while(!inputIt.IsAtEnd()&&!outputIt.IsAtEnd())
+    {
+      typename ImageType::IndexType currentInputIndex = inputIt.GetIndex();
+      PointType currentInputPoint;
+      this->GetInput()->TransformIndexToPhysicalPoint(currentInputIndex,currentInputPoint);
+
+      bool lineToKeep = false;
+      bool sampleToKeep = false;
+
+      for (auto const& record : m_LinesRecord)
+	{
+	  if (currentInputPoint[1]-0.5>=record.first && currentInputPoint[1]-0.5<=record.second)
+	    {
+	      lineToKeep = true;
+	      break;
+	    }
+	}
+
+      if (currentInputPoint[0]-0.5 >= static_cast<int>(m_SamplesRecord.first) && 
+	  currentInputPoint[1]-0.5 <= static_cast<int>(m_SamplesRecord.second))
+	{
+	  sampleToKeep = true;
+	} 
+
+      if(lineToKeep && sampleToKeep)
+	{
+	  outputIt.Set(inputIt.Get());
+
+	  ++outputIt;
+	}
+    
+
+      ++inputIt;
+    }  
+}
+
+
 } // End namespace otb
 
 #endif
diff --git a/Modules/Radiometry/SARCalibration/otb-module.cmake b/Modules/Radiometry/SARCalibration/otb-module.cmake
index 54f896fe57f4c29e84534e292558d9025cfc7cd1..13eb2a48f5d24f0e1f3dc653f47ef2642d041e5a 100644
--- a/Modules/Radiometry/SARCalibration/otb-module.cmake
+++ b/Modules/Radiometry/SARCalibration/otb-module.cmake
@@ -27,6 +27,7 @@ otb_module(OTBSARCalibration
     OTBITK
     OTBMetadata
     OTBOSSIMAdapters
+    OTBImageManipulation
 
   TEST_DEPENDS
     OTBImageBase
diff --git a/Modules/Radiometry/SARCalibration/test/CMakeLists.txt b/Modules/Radiometry/SARCalibration/test/CMakeLists.txt
index 1c8f86f42639f2b3ffb247677b0ac42ad914323e..ae7b2bb8356bfc1a58de54394acefbd4ad9b1575 100644
--- a/Modules/Radiometry/SARCalibration/test/CMakeLists.txt
+++ b/Modules/Radiometry/SARCalibration/test/CMakeLists.txt
@@ -42,6 +42,7 @@ otbTerraSarBrightnessImageComplexFilterTest.cxx
 otbSarRadiometricCalibrationToImageFilterWithComplexPixelTest.cxx
 otbSarBrightnessToImageFilterTest.cxx
 otbSarDeburstFilterTest.cxx
+otbSarBurstExtractionFilterTest.cxx
 )
 
 add_executable(otbSARCalibrationTestDriver ${OTBSARCalibrationTests})
@@ -297,3 +298,39 @@ otb_add_test(NAME saTvSarDeburstImageFilterTest COMMAND otbSARCalibrationTestDri
   otbSarDeburstFilterTest
   ${INPUTDATA}/s1a-iw1-slc-vh-amp_xt.tif
   ${TEMP}/saTvSarDeburstImageFilterTestOutput.tif)
+
+otb_add_test(NAME saTvSarDeburstImageFilterTest2 COMMAND otbSARCalibrationTestDriver
+  --compare-image ${NOTOL}
+  ${BASELINE}/saTvSarDeburstImageFilterTest2Output.tif
+  ${TEMP}/saTvSarDeburstImageFilterTest2Output.tif
+  otbSarDeburstFilterTest
+  ${INPUTDATA}/s1a-iw1-slc-vv-20170111_Burst01_amp.tiff
+  ${TEMP}/saTvSarDeburstImageFilterTest2Output.tif)
+
+otb_add_test(NAME saTvSarDeburstImageFilterTest3 COMMAND otbSARCalibrationTestDriver
+  --compare-image ${NOTOL}
+  ${BASELINE}/saTvSarDeburstImageFilterTest3Output.tif
+  ${TEMP}/saTvSarDeburstImageFilterTest3Output.tif
+  otbSarDeburstFilterTest
+  ${INPUTDATA}/s1a-iw1-slc-vv-20170111_Burst01_amp.tiff
+  ${TEMP}/saTvSarDeburstImageFilterTest3Output.tif
+  WithOnlyValidSamples)
+
+
+otb_add_test(NAME saTvSarBurstExtractionImageFilterTest1 COMMAND otbSARCalibrationTestDriver
+  --compare-image ${NOTOL}
+  ${BASELINE}/saTvSarBurstImageFilterTest1Output.tif
+  ${TEMP}/saTvSarBurstImageFilterTest1Output.tif
+  otbSarBurstExtractionFilterTest
+  ${INPUTDATA}/s1a-iw1-slc-vv-20170111_Burst01_amp.tiff
+  ${TEMP}/saTvSarBurstImageFilterTest1Output.tif
+  0)
+
+otb_add_test(NAME saTvSarBurstExtractionImageFilterTest2 COMMAND otbSARCalibrationTestDriver
+  --compare-image ${NOTOL}
+  ${BASELINE}/saTvSarBurstImageFilterTest2Output.tif
+  ${TEMP}/saTvSarBurstImageFilterTest2Output.tif
+  otbSarBurstExtractionFilterTest
+  ${INPUTDATA}/s1a-iw1-slc-vv-20170111_Burst01_amp.tiff
+  ${TEMP}/saTvSarBurstImageFilterTest2Output.tif
+  1)
diff --git a/Modules/Radiometry/SARCalibration/test/otbSARCalibrationTestDriver.cxx b/Modules/Radiometry/SARCalibration/test/otbSARCalibrationTestDriver.cxx
index 35733b76f1852d7435fcdf2c9f8d4a09dc7a4361..3438d9c62eaeda5ad791ba0a5e711bc953e4b416 100644
--- a/Modules/Radiometry/SARCalibration/test/otbSARCalibrationTestDriver.cxx
+++ b/Modules/Radiometry/SARCalibration/test/otbSARCalibrationTestDriver.cxx
@@ -42,4 +42,5 @@ void RegisterTests()
   REGISTER_TEST(otbSarRadiometricCalibrationToImageFilterWithComplexPixelTest);
   REGISTER_TEST(otbSarBrightnessToImageFilterTest);
   REGISTER_TEST(otbSarDeburstFilterTest);
+  REGISTER_TEST(otbSarBurstExtractionFilterTest);
 }
diff --git a/Modules/Radiometry/SARCalibration/test/otbSarBurstExtractionFilterTest.cxx b/Modules/Radiometry/SARCalibration/test/otbSarBurstExtractionFilterTest.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..e0602f305e91da342a60b5e384258602cf542881
--- /dev/null
+++ b/Modules/Radiometry/SARCalibration/test/otbSarBurstExtractionFilterTest.cxx
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
+ *
+ * This file is part of Orfeo Toolbox
+ *
+ *     https://www.orfeo-toolbox.org/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "otbSarBurstExtractionImageFilter.h"
+#include "otbImage.h"
+#include "otbImageFileReader.h"
+#include "otbImageFileWriter.h"
+
+typedef otb::Image<unsigned short>            ImageType;
+typedef otb::ImageFileReader<ImageType>       ReaderType;
+typedef otb::ImageFileWriter<ImageType>       WriterType;
+typedef otb::SarBurstExtractionImageFilter<ImageType> BurstExtractionFilterType;
+
+int otbSarBurstExtractionFilterTest(int itkNotUsed(argc), char * argv[])
+{
+  ReaderType::Pointer reader = ReaderType::New();
+  reader->SetFileName(argv[1]);
+
+  BurstExtractionFilterType::Pointer filter = BurstExtractionFilterType::New();
+  filter->SetInput(reader->GetOutput());
+  filter->SetBurstIndex(std::stoi(argv[3]));
+
+  WriterType::Pointer writer = WriterType::New();
+  writer->SetInput(filter->GetOutput());
+  writer->SetFileName(argv[2]);
+  writer->Update();
+
+  // check that there is now a single burst in data
+  reader = ReaderType::New();
+  reader->SetFileName(argv[2]);
+  reader->UpdateOutputInformation();
+
+  unsigned int nb_bursts = atoi(reader->GetOutput()->GetImageKeywordlist().GetMetadataByKey("support_data.geom.bursts.number").c_str());
+
+  if(nb_bursts != 1)
+    {
+    std::cerr<<"Error: more than 1 burst ("<<nb_bursts<<" bursts) found in output metadata."<<std::endl;
+    }
+  else
+    {
+    std::cout<<"Metadata have a single burst as expected."<<std::endl;
+    }
+
+  return EXIT_SUCCESS;
+}
+
diff --git a/Modules/Radiometry/SARCalibration/test/otbSarDeburstFilterTest.cxx b/Modules/Radiometry/SARCalibration/test/otbSarDeburstFilterTest.cxx
index d221088626f509462223f9cbbb93a6ce8d96c75a..deac69d67dfad7a7dc8b28a1126945dfe5676a7f 100644
--- a/Modules/Radiometry/SARCalibration/test/otbSarDeburstFilterTest.cxx
+++ b/Modules/Radiometry/SARCalibration/test/otbSarDeburstFilterTest.cxx
@@ -28,13 +28,20 @@ typedef otb::ImageFileReader<ImageType>       ReaderType;
 typedef otb::ImageFileWriter<ImageType>       WriterType;
 typedef otb::SarDeburstImageFilter<ImageType> DeburstFilterType;
 
-int otbSarDeburstFilterTest(int itkNotUsed(argc), char * argv[])
+int otbSarDeburstFilterTest(int argc, char * argv[])
 {
   ReaderType::Pointer reader = ReaderType::New();
   reader->SetFileName(argv[1]);
 
+  bool onlyValidSamples = false;
+  if (argc == 4)
+    {
+      onlyValidSamples = true;
+    }
+
   DeburstFilterType::Pointer filter = DeburstFilterType::New();
   filter->SetInput(reader->GetOutput());
+  filter->SetOnlyValidSample(onlyValidSamples);
 
   WriterType::Pointer writer = WriterType::New();
   writer->SetInput(filter->GetOutput());
diff --git a/Modules/Remote/temporal-gapfilling.remote.cmake b/Modules/Remote/temporal-gapfilling.remote.cmake
index 2dd788d21391a19390f40ac90ff3af1b5271311b..5d948a6ddaecceb5f4ff6a5324e463ec80030340 100644
--- a/Modules/Remote/temporal-gapfilling.remote.cmake
+++ b/Modules/Remote/temporal-gapfilling.remote.cmake
@@ -27,5 +27,5 @@ https://gitlab.orfeo-toolbox.org/jinglada/temporalgapfilling
 "
   GIT_REPOSITORY https://gitlab.orfeo-toolbox.org/jinglada/temporalgapfilling.git
   # Commit on develop branch which includes patches for Windows support
-  GIT_TAG 4fc4a71acf7b9b051cda5a3b950de2cdb9d26287
+  GIT_TAG 9d97764f0411de1a32dd5e0a90bdcdd8adfa049f
 )
diff --git a/Modules/Segmentation/Conversion/include/otbRasterizeVectorDataFilter.h b/Modules/Segmentation/Conversion/include/otbRasterizeVectorDataFilter.h
index d719606ae3492d9589f49fa15429bbb00b32d640..f7fbf00ff58fe49e17d28c672ad982426fb3badc 100644
--- a/Modules/Segmentation/Conversion/include/otbRasterizeVectorDataFilter.h
+++ b/Modules/Segmentation/Conversion/include/otbRasterizeVectorDataFilter.h
@@ -31,7 +31,6 @@
 #include "gdal.h"
 #include "gdal_alg.h"
 #include "ogr_srs_api.h"
-#include "otbOGRVersionProxy.h"
 
 namespace otb {
 
@@ -148,7 +147,7 @@ protected:
   {
     if (m_OGRDataSourcePointer != nullptr)
       {
-      ogr::version_proxy::Close(m_OGRDataSourcePointer);
+      GDALClose(m_OGRDataSourcePointer);
       }
   }
 
@@ -160,7 +159,7 @@ private:
   RasterizeVectorDataFilter(const Self&) = delete;
   void operator=(const Self&) = delete;
 
-  ogr::version_proxy::GDALDatasetType * m_OGRDataSourcePointer;
+  GDALDataset * m_OGRDataSourcePointer;
 
   // Vector Of LayersH
   std::vector< OGRLayerH >    m_SrcDataSetLayers;
diff --git a/Modules/Segmentation/Conversion/include/otbVectorDataToLabelImageFilter.h b/Modules/Segmentation/Conversion/include/otbVectorDataToLabelImageFilter.h
index 6cdbabc3974e38da1993b092a130ea042879fffc..d67617fc170887bdc864770ba7655131c1e9f14e 100644
--- a/Modules/Segmentation/Conversion/include/otbVectorDataToLabelImageFilter.h
+++ b/Modules/Segmentation/Conversion/include/otbVectorDataToLabelImageFilter.h
@@ -29,7 +29,6 @@
 
 #include "gdal.h"
 #include "ogr_api.h"
-#include "otbOGRVersionProxy.h"
 #include <string>
 
 namespace otb {
@@ -151,7 +150,7 @@ protected:
 
     if (m_OGRDataSourcePointer != nullptr)
       {
-      ogr::version_proxy::Close(m_OGRDataSourcePointer);
+      GDALClose(m_OGRDataSourcePointer);
       }
   }
 
@@ -163,7 +162,7 @@ private:
   VectorDataToLabelImageFilter(const Self&) = delete;
   void operator=(const Self&) = delete;
 
-  ogr::version_proxy::GDALDatasetType * m_OGRDataSourcePointer;
+  GDALDataset * m_OGRDataSourcePointer;
 
   // Vector Of OGRGeometyH
   std::vector< OGRGeometryH >   m_SrcDataSetGeometries;
diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbClosingOpeningMorphologicalFilter.hxx b/Modules/Segmentation/MorphologicalProfiles/include/otbClosingOpeningMorphologicalFilter.hxx
index 9624d10ad77d5b713f46b0b54e5ea98ce2a9e47d..efe975f0b356185d3c350f0ace0c9f23ca069686 100644
--- a/Modules/Segmentation/MorphologicalProfiles/include/otbClosingOpeningMorphologicalFilter.hxx
+++ b/Modules/Segmentation/MorphologicalProfiles/include/otbClosingOpeningMorphologicalFilter.hxx
@@ -22,7 +22,6 @@
 #define otbClosingOpeningMorphologicalFilter_hxx
 
 #include "otbClosingOpeningMorphologicalFilter.h"
-#include "itkUnaryFunctorImageFilter.h"
 #include "itkGrayscaleMorphologicalOpeningImageFilter.h"
 #include "itkGrayscaleMorphologicalClosingImageFilter.h"
 #include "itkProgressAccumulator.h"
diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.h b/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.h
index 4b2ef4d9bd4f79a25d6e820dba48a907c6c43c94..bcdcd54c024279112162d91a93bd9bd695b1530e 100644
--- a/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.h
+++ b/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.h
@@ -22,7 +22,6 @@
 #define otbGeodesicMorphologyDecompositionImageFilter_h
 
 #include "otbGeodesicMorphologyLevelingFilter.h"
-#include "itkUnaryFunctorImageFilter.h"
 #include "itkSubtractImageFilter.h"
 #include "itkOpeningByReconstructionImageFilter.h"
 #include "itkClosingByReconstructionImageFilter.h"
diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.hxx b/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.hxx
index 514b4e0e56177912beb3ab603de409082e268dec..d5e9fda923b7d1da8caef571f544e874ffd2a1c2 100644
--- a/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.hxx
+++ b/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyDecompositionImageFilter.hxx
@@ -88,9 +88,12 @@ GeodesicMorphologyDecompositionImageFilter<TInputImage, TOutputImage, TStructuri
   m_ConcaveFilter->SetInput1(m_ClosingFilter->GetOutput());
   m_ConcaveFilter->SetInput2(this->GetInput());
 
-  m_LevelingFilter->SetInput(this->GetInput());
-  m_LevelingFilter->SetInputConvexMap(m_ConvexFilter->GetOutput());
-  m_LevelingFilter->SetInputConcaveMap(m_ConcaveFilter->GetOutput());
+  using namespace otb::Functor::LevelingFunctor_tags;
+  // Template keyword mandatory to avoid parsing error when using
+  // template methods within template code
+  m_LevelingFilter->template SetVariadicNamedInput<pixel>(this->GetInput());
+  m_LevelingFilter->template SetVariadicNamedInput<convex_pixel>(m_ConvexFilter->GetOutput());
+  m_LevelingFilter->template SetVariadicNamedInput<concave_pixel>(m_ConcaveFilter->GetOutput());
 
   m_ConvexFilter->GraftOutput(this->GetConvexMap());
   m_ConvexFilter->Update();
diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyLevelingFilter.h b/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyLevelingFilter.h
index c0e57a2343e6bccadd2a8a7622d19f0613dc9cf4..e2cbc4c84e53ec7265e97278e661f585ae82b403 100644
--- a/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyLevelingFilter.h
+++ b/Modules/Segmentation/MorphologicalProfiles/include/otbGeodesicMorphologyLevelingFilter.h
@@ -21,16 +21,25 @@
 #ifndef otbGeodesicMorphologyLevelingFilter_h
 #define otbGeodesicMorphologyLevelingFilter_h
 
-#include "itkTernaryFunctorImageFilter.h"
+#include "otbFunctorImageFilter.h"
 
 namespace otb
 {
 namespace Functor
 {
+namespace LevelingFunctor_tags
+{
+struct pixel {};
+struct convex_pixel {};
+struct concave_pixel {};
+}
 /** \class LevelingFunctor
  * \brief This functor performs the pixel-wise leveling operation needed in the
  * geodesic morphology decomposition filter. For more details, please refer to
  * the documentation of this filter.
+ * 
+ * Use otb::GeodesicMorphologyLevelingFilter to apply it image-wise.
+ * 
  * \sa GeodesicMorphologyDecompositionImageFilter
  *
  * \ingroup OTBMorphologicalProfiles
@@ -44,7 +53,7 @@ public:
   /// Destructor
   virtual ~LevelingFunctor() {}
 
-  inline TOutput operator ()(const TInput& pixel, const TInputMap& convexPixel, const TInputMap& concavePixel)
+  inline TOutput operator ()(const TInput& pixel, const TInputMap& convexPixel, const TInputMap& concavePixel) const
   {
     TOutput result;
 
@@ -65,77 +74,25 @@ public:
 };
 } // end namespace Functor
 
-/** \class GeodesicMorphologyLevelingFilter
+/** \typedef GeodesicMorphologyLevelingFilter
  *  \brief This filter performs the leveling operation defined in the documentation of
  *  the geodesic decomposition image filter, given the original image, convex and concave membership
  *  functions. Please refer to the documentation of this filter for more details.
  *
+ * It applies the Functor::LevelingFunctor image-wise.
+ * 
  * \sa GeodesicMorphologyDecompositionImageFilter
- *
+ * 
  * \ingroup OTBMorphologicalProfiles
  */
-template <class TInputImage, class TInputMaps, class TOutputImage>
-class ITK_EXPORT GeodesicMorphologyLevelingFilter
-  : public itk::TernaryFunctorImageFilter<TInputImage, TInputImage,
-      TInputImage, TOutputImage,
-      Functor::LevelingFunctor<typename TInputImage::PixelType,
-          typename TInputMaps::PixelType,
-          typename TOutputImage::PixelType> >
-{
-public:
-  /** Standard typedefs */
-  typedef GeodesicMorphologyLevelingFilter Self;
-  typedef   itk::TernaryFunctorImageFilter<TInputImage, TInputImage,
-      TInputImage, TOutputImage,
-      Functor::LevelingFunctor<typename TInputImage::PixelType,
-          typename TInputMaps::PixelType,
-          typename TOutputImage::PixelType> > Superclass;
-  typedef itk::SmartPointer<Self>       Pointer;
-  typedef itk::SmartPointer<const Self> ConstPointer;
 
-  /** Type macro */
-  itkNewMacro(Self);
-
-  /** Creation through object factory macro */
-  itkTypeMacro(GeodesicMorphologyLevelingFilter, TernaryFunctorImageFilter);
-
-  /**
-   * Set the convex membership image.
-   */
-  void SetInputConvexMap(const TInputMaps * convexMap)
-  {
-    this->SetInput2(convexMap);
-  }
-  /**
-   * Set the concave membership image.
-   */
-  void SetInputConcaveMap(const TInputMaps * concaveMap)
-  {
-    this->SetInput3(concaveMap);
-  }
-  /**
-   * Set the original input image
-   */
-  using Superclass::SetInput;
-  void SetInput(const TInputImage * input) override
-  {
-    this->SetInput1(input);
-  }
-
-protected:
-  /** Constructor */
-  GeodesicMorphologyLevelingFilter() {};
-  /** Destructor */
-  ~GeodesicMorphologyLevelingFilter() override {}
-  /**PrintSelf method */
-  void PrintSelf(std::ostream& os, itk::Indent indent) const override
-  {
-    Superclass::PrintSelf(os, indent);
-  }
-
-private:
-  GeodesicMorphologyLevelingFilter(const Self &) = delete;
-  void operator =(const Self&) = delete;
-};
+template <class TInputImage, class TInputMaps, class TOutputImage>
+using GeodesicMorphologyLevelingFilter = FunctorImageFilter
+  < Functor::LevelingFunctor<typename TInputImage::PixelType,
+                             typename TInputMaps::PixelType,
+                             typename TOutputImage::PixelType>, 
+    std::tuple<typename Functor::LevelingFunctor_tags::pixel,
+               typename Functor::LevelingFunctor_tags::convex_pixel,
+               typename Functor::LevelingFunctor_tags::concave_pixel > >;
 } // End namespace otb
 #endif
diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalClosingProfileFilter.h b/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalClosingProfileFilter.h
index 151dca67a3fc4b0a68c3f585b6cab925a476125e..ef89706a0b4770d16046e879e87f06f2fedd958d 100644
--- a/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalClosingProfileFilter.h
+++ b/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalClosingProfileFilter.h
@@ -22,7 +22,6 @@
 #define otbMorphologicalClosingProfileFilter_h
 
 #include "otbImageToProfileFilter.h"
-#include "itkUnaryFunctorImageFilter.h"
 #include "itkClosingByReconstructionImageFilter.h"
 
 namespace otb
diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalOpeningProfileFilter.h b/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalOpeningProfileFilter.h
index 3b9668b04af5288c14f13ee1268459ce50c4e45c..803fc651107b950dd90dfe3fb8de61c9b6c7717c 100644
--- a/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalOpeningProfileFilter.h
+++ b/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalOpeningProfileFilter.h
@@ -22,7 +22,6 @@
 #define otbMorphologicalOpeningProfileFilter_h
 
 #include "otbImageToProfileFilter.h"
-#include "itkUnaryFunctorImageFilter.h"
 #include "itkOpeningByReconstructionImageFilter.h"
 
 namespace otb
diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalProfilesSegmentationFilter.hxx b/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalProfilesSegmentationFilter.hxx
index 11a772035d919dc70ecb1d2993b118cec4e5668b..68c37cf462a8fd8cf90dda0016dee707842df991 100644
--- a/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalProfilesSegmentationFilter.hxx
+++ b/Modules/Segmentation/MorphologicalProfiles/include/otbMorphologicalProfilesSegmentationFilter.hxx
@@ -49,10 +49,13 @@ MorphologicalProfilesSegmentationFilter<TInputImage,TOutputImage,TInternalPrecis
   m_OpeningCharacteristicsFilter->SetInput(m_OpeningDerivativeProfile->GetOutput());
   m_ClosingCharacteristicsFilter->SetInput(m_ClosingDerivativeProfile->GetOutput());
 
-  m_ClassificationFilter->SetOpeningProfileDerivativeMaxima(m_OpeningCharacteristicsFilter->GetOutput());
-  m_ClassificationFilter->SetOpeningProfileCharacteristics(m_OpeningCharacteristicsFilter->GetOutputCharacteristics());
-  m_ClassificationFilter->SetClosingProfileDerivativeMaxima(m_ClosingCharacteristicsFilter->GetOutput());
-  m_ClassificationFilter->SetClosingProfileCharacteristics(m_ClosingCharacteristicsFilter->GetOutputCharacteristics());
+  using namespace Functor::MultiScaleConvexOrConcaveDecisionRule_tags;
+  // Template keyword mandatory to avoid parsing error when using
+  // template methods within template code
+  m_ClassificationFilter->template SetVariadicNamedInput<max_opening_profile_derivative>(m_OpeningCharacteristicsFilter->GetOutput());
+  m_ClassificationFilter->template SetVariadicNamedInput<opening_profile_characteristics>(m_OpeningCharacteristicsFilter->GetOutputCharacteristics());
+  m_ClassificationFilter->template SetVariadicNamedInput<max_closing_profile_derivative>(m_ClosingCharacteristicsFilter->GetOutput());
+  m_ClassificationFilter->template SetVariadicNamedInput<closing_profile_characteristics>(m_ClosingCharacteristicsFilter->GetOutputCharacteristics());
 
   m_ConnectedComponentsFilter->SetInput(m_ClassificationFilter->GetOutput());
 
@@ -85,8 +88,8 @@ MorphologicalProfilesSegmentationFilter<TInputImage,TOutputImage,TInternalPrecis
   m_ClosingCharacteristicsFilter->SetInitialValue(m_ProfileStart);
   m_ClosingCharacteristicsFilter->SetStep(m_ProfileStep);
 
-  m_ClassificationFilter->SetSigma(m_Sigma);
-  m_ClassificationFilter->SetLabelSeparator(m_ProfileStart + m_ProfileSize * m_ProfileStep);
+  m_ClassificationFilter->GetModifiableFunctor().SetSigma(m_Sigma);
+  m_ClassificationFilter->GetModifiableFunctor().SetLabelSeparator(m_ProfileStart + m_ProfileSize * m_ProfileStep);
 
   m_ConnectedComponentsFilter->GraftOutput(this->GetOutput());
   m_ConnectedComponentsFilter->Update();
diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbMultiScaleConvexOrConcaveClassificationFilter.h b/Modules/Segmentation/MorphologicalProfiles/include/otbMultiScaleConvexOrConcaveClassificationFilter.h
index fc23f5a6a95577067144f9a81d6bd9691ac58588..8819ff33b4e9485519e0984e6bb3d89660aab75d 100644
--- a/Modules/Segmentation/MorphologicalProfiles/include/otbMultiScaleConvexOrConcaveClassificationFilter.h
+++ b/Modules/Segmentation/MorphologicalProfiles/include/otbMultiScaleConvexOrConcaveClassificationFilter.h
@@ -21,14 +21,26 @@
 #ifndef otbMultiScaleConvexOrConcaveClassificationFilter_h
 #define otbMultiScaleConvexOrConcaveClassificationFilter_h
 
-#include "otbQuaternaryFunctorImageFilter.h"
+#include "otbFunctorImageFilter.h"
+
 namespace otb
 {
 namespace Functor
 {
+namespace MultiScaleConvexOrConcaveDecisionRule_tags
+{
+struct max_opening_profile_derivative  {};
+struct max_closing_profile_derivative  {};
+struct opening_profile_characteristics {};
+struct closing_profile_characteristics {};
+
+} // End namespace MultiScaleConvexOrConcaveDecisionRule_tags
+
 /** \class MultiScaleConvexOrConcaveDecisionRule
  *  \brief This Functor apply a classification rule on two membership value along with two labels.
  *
+ * Use otb::MultiScaleConvexOrConcaveClassificationFilter to apply it image-wise.
+ *
  * \par
  * This algorithm is based on the following publication:
  * \par
@@ -82,10 +94,10 @@ public:
    * \param opDeChar The characteristic of the opening profile
    * \param cloDeChar The characteristic of the closing profile
    */
-  inline TLabeled operator ()(const TInput& opDeMax,
-                              const TInput& cloDeMax,
-                              const TLabeled& opDeChar,
-                              const TLabeled& cloDeChar)
+  TLabeled operator ()(const TInput& opDeMax,
+                       const TInput& cloDeMax,
+                       const TLabeled& opDeChar,
+                       const TLabeled& cloDeChar) const
   {
     TLabeled resp = 0;
 
@@ -141,118 +153,29 @@ private:
 };
 } //end namespace Functor
 
-/** \class MultiScaleConvexOrConcaveClassificationFilter
- *  \brief Apply the MultiScaleConvexOrConcaveDecisionRule to whole images.
+/** \typedef MultiScaleConvexOrConcaveClassificationFilter
+ *  \brief Apply the otb::Functor::MultiScaleConvexOrConcaveDecisionRule to whole images.
  *
- * See MultiScaleConvexOrConcaveDecisionRule functor documentation for more details.
+ * See otb::Functor::MultiScaleConvexOrConcaveDecisionRule functor documentation for more details.
  *
+ * Set inputs with:
+ * \code
+ * 
+ * SetVariadicNamedInput<MultiScaleConvexOrConcaveDecisionRule_tags::max_opening_profile_derivative>(in1);
+ * SetVariadicNamedInput<MultiScaleConvexOrConcaveDecisionRule_tags::max_closing_profile_derivative>(in2);
+ * SetVariadicNamedInput<MultiScaleConvexOrConcaveDecisionRule_tags::opening_profile_characteristics>(in3);
+ * SetVariadicNamedInput<MultiScaleConvexOrConcaveDecisionRule_tags::closing_profile_characteristics>(in4); 
  *
+ * \endcode
+ * 
  * \ingroup OTBMorphologicalProfiles
  */
 template <class TInputImage, class TOutputImage>
-class ITK_EXPORT MultiScaleConvexOrConcaveClassificationFilter
-  : public QuaternaryFunctorImageFilter<TInputImage, TInputImage, TOutputImage, TOutputImage, TOutputImage,
-      Functor::MultiScaleConvexOrConcaveDecisionRule<typename TInputImage::PixelType,
-          typename TOutputImage::PixelType> >
-{
-public:
-  /** Standard typedefs */
-  typedef MultiScaleConvexOrConcaveClassificationFilter Self;
-  typedef QuaternaryFunctorImageFilter<TInputImage, TInputImage, TOutputImage, TOutputImage, TOutputImage,
-      Functor::MultiScaleConvexOrConcaveDecisionRule<typename TInputImage::PixelType,
-          typename TOutputImage::PixelType> >
-  Superclass;
-  typedef itk::SmartPointer<Self>       Pointer;
-  typedef itk::SmartPointer<const Self> ConstPointer;
-
-  /** Type macro */
-  itkNewMacro(Self);
-
-  /** Creation through object factory macro */
-  itkTypeMacro(MultiScaleConvexOrConcaveClassificationFilter, QuaternaryFunctorImageFilter);
-
-  /** Template class typedef */
-  typedef TInputImage                         InputImageType;
-  typedef TOutputImage                        OutputImageType;
-  typedef typename OutputImageType::PixelType LabelType;
-  typedef Functor::MultiScaleConvexOrConcaveDecisionRule<typename TInputImage::PixelType,
-      typename TOutputImage::PixelType> DecisionFunctorType;
-  /**
-   * Set the opening profile derivative maxima image
-   * \param derivativeMaxima the opening profile derivative maxima image
-   *
-   */
-  void SetOpeningProfileDerivativeMaxima(const TInputImage * derivativeMaxima)
-  {
-    this->SetInput1(derivativeMaxima);
-  }
-  /**
-   * Set the opening profile characteristics image
-   * \param characteristics the opening profile characteristics image
-   *
-   */
-  void SetOpeningProfileCharacteristics(const TOutputImage * characteristics)
-  {
-    this->SetInput3(characteristics);
-  }
-  /**
-   * Set the closing profile derivative maxima image
-   * \param derivativeMaxima the closing profile derivative maxima image
-   *
-   */
-  void SetClosingProfileDerivativeMaxima(const TInputImage * derivativeMaxima)
-  {
-    this->SetInput2(derivativeMaxima);
-  }
-  /**
-   * Set the closing profile characteristics image
-   * \param characteristics the closing profile characteristics image
-   *
-   */
-  void SetClosingProfileCharacteristics(const TOutputImage * characteristics)
-  {
-    this->SetInput4(characteristics);
-  }
-
-  /** Set/Get the tolerance value */
-  itkSetMacro(Sigma, double);
-  itkGetMacro(Sigma, double);
-  /** Set/Get the label separator */
-  itkSetMacro(LabelSeparator, LabelType);
-  itkGetMacro(LabelSeparator, LabelType);
-
-  /** Set the functor parameters before calling the ThreadedGenerateData() */
-  void BeforeThreadedGenerateData(void) override
-  {
-    this->GetFunctor().SetLabelSeparator(m_LabelSeparator);
-    this->GetFunctor().SetSigma(m_Sigma);
-  }
-
-protected:
-  /** Constructor */
-  MultiScaleConvexOrConcaveClassificationFilter()
-    {
-    m_LabelSeparator = 10;
-    m_Sigma          = 0.0;
-    };
-  /** Destructor */
-  ~MultiScaleConvexOrConcaveClassificationFilter() override {}
-  /**PrintSelf method */
-  void PrintSelf(std::ostream& os, itk::Indent indent) const override
-  {
-    Superclass::PrintSelf(os, indent);
-    os << indent << "LabelSeparator: " << m_LabelSeparator << std::endl;
-    os << indent << "Sigma: " << m_Sigma << std::endl;
-  }
-
-private:
-  MultiScaleConvexOrConcaveClassificationFilter(const Self &) = delete;
-  void operator =(const Self&) = delete;
-
-  /** Label separator between convex and concave labels */
-  LabelType m_LabelSeparator;
-  /** Tolerance value */
-  double m_Sigma;
-};
+using MultiScaleConvexOrConcaveClassificationFilter
+= FunctorImageFilter<Functor::MultiScaleConvexOrConcaveDecisionRule<typename TInputImage::PixelType, typename TOutputImage::PixelType>,
+                     std::tuple<Functor::MultiScaleConvexOrConcaveDecisionRule_tags::max_opening_profile_derivative,
+                                Functor::MultiScaleConvexOrConcaveDecisionRule_tags::max_closing_profile_derivative,
+                                Functor::MultiScaleConvexOrConcaveDecisionRule_tags::opening_profile_characteristics,
+                                Functor::MultiScaleConvexOrConcaveDecisionRule_tags::closing_profile_characteristics> >;
 } // End namespace otb
 #endif
diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbOpeningClosingMorphologicalFilter.hxx b/Modules/Segmentation/MorphologicalProfiles/include/otbOpeningClosingMorphologicalFilter.hxx
index fc3f05561ccabc085ef29ac6ffeff19748e3c37e..8380c1110a63c35c97a6813cb5ada983748292da 100644
--- a/Modules/Segmentation/MorphologicalProfiles/include/otbOpeningClosingMorphologicalFilter.hxx
+++ b/Modules/Segmentation/MorphologicalProfiles/include/otbOpeningClosingMorphologicalFilter.hxx
@@ -22,7 +22,6 @@
 #define otbOpeningClosingMorphologicalFilter_hxx
 
 #include "otbOpeningClosingMorphologicalFilter.h"
-#include "itkUnaryFunctorImageFilter.h"
 #include "itkGrayscaleMorphologicalOpeningImageFilter.h"
 #include "itkGrayscaleMorphologicalClosingImageFilter.h"
 #include "itkProgressAccumulator.h"
diff --git a/Modules/Segmentation/MorphologicalProfiles/include/otbProfileToProfileDerivativeFilter.h b/Modules/Segmentation/MorphologicalProfiles/include/otbProfileToProfileDerivativeFilter.h
index 80230dff776078976def7bb921a8c87217e4baac..f459a85abbf76f226211c485adaade1b51be996a 100644
--- a/Modules/Segmentation/MorphologicalProfiles/include/otbProfileToProfileDerivativeFilter.h
+++ b/Modules/Segmentation/MorphologicalProfiles/include/otbProfileToProfileDerivativeFilter.h
@@ -22,7 +22,6 @@
 #define otbProfileToProfileDerivativeFilter_h
 
 #include "otbImageListToImageListFilter.h"
-#include "itkUnaryFunctorImageFilter.h"
 #include "itkSubtractImageFilter.h"
 #include "itkAbsImageFilter.h"
 
diff --git a/Modules/Segmentation/MorphologicalProfiles/otb-module.cmake b/Modules/Segmentation/MorphologicalProfiles/otb-module.cmake
index d05a0c719d87ec054fd64352751e9e8e222d34b4..005074cff8e2b4bde4a2995fbcb3cc58727a3814 100644
--- a/Modules/Segmentation/MorphologicalProfiles/otb-module.cmake
+++ b/Modules/Segmentation/MorphologicalProfiles/otb-module.cmake
@@ -27,6 +27,7 @@ otb_module(OTBMorphologicalProfiles
     OTBITK
     OTBImageBase
     OTBObjectList
+    OTBFunctor
 
   TEST_DEPENDS
     OTBImageIO
diff --git a/Modules/Segmentation/MorphologicalProfiles/test/otbGeodesicMorphologyLevelingFilter.cxx b/Modules/Segmentation/MorphologicalProfiles/test/otbGeodesicMorphologyLevelingFilter.cxx
index 0c1faa3267f5cbc89b439f7b32c19a137e629671..3fe3e2ee05e18d911369e1b455afa0c1a5118280 100644
--- a/Modules/Segmentation/MorphologicalProfiles/test/otbGeodesicMorphologyLevelingFilter.cxx
+++ b/Modules/Segmentation/MorphologicalProfiles/test/otbGeodesicMorphologyLevelingFilter.cxx
@@ -46,9 +46,10 @@ int otbGeodesicMorphologyLevelingFilter(int itkNotUsed(argc), char * argv[])
 
   FilterType::Pointer filter = FilterType::New();
 
-  filter->SetInput(reader->GetOutput());
-  filter->SetInputConvexMap(convreader->GetOutput());
-  filter->SetInputConcaveMap(concreader->GetOutput());
+  using namespace otb::Functor::LevelingFunctor_tags;
+  filter->SetVariadicNamedInput<pixel>(reader->GetOutput());
+  filter->SetVariadicNamedInput<convex_pixel>(convreader->GetOutput());
+  filter->SetVariadicNamedInput<concave_pixel>(concreader->GetOutput());
 
   WriterType::Pointer writer = WriterType::New();
   writer->SetFileName(outfname);
diff --git a/Modules/Segmentation/MorphologicalProfiles/test/otbMultiScaleConvexOrConcaveClassificationFilter.cxx b/Modules/Segmentation/MorphologicalProfiles/test/otbMultiScaleConvexOrConcaveClassificationFilter.cxx
index 6dddf61e56c06ac9180ba23f1c78d4f047413b3e..a01e2ba2f7e3290adc1823cc2bb8e5bd9bbb9046 100644
--- a/Modules/Segmentation/MorphologicalProfiles/test/otbMultiScaleConvexOrConcaveClassificationFilter.cxx
+++ b/Modules/Segmentation/MorphologicalProfiles/test/otbMultiScaleConvexOrConcaveClassificationFilter.cxx
@@ -96,12 +96,13 @@ int otbMultiScaleConvexOrConcaveClassificationFilter(int itkNotUsed(argc), char
   cmsCharFilter->SetStep(step);
 
   MultiScaleClassificationFilterType::Pointer classificationFilter = MultiScaleClassificationFilterType::New();
-  classificationFilter->SetOpeningProfileDerivativeMaxima(omsCharFilter->GetOutput());
-  classificationFilter->SetOpeningProfileCharacteristics(omsCharFilter->GetOutputCharacteristics());
-  classificationFilter->SetClosingProfileDerivativeMaxima(cmsCharFilter->GetOutput());
-  classificationFilter->SetClosingProfileCharacteristics(cmsCharFilter->GetOutputCharacteristics());
-  classificationFilter->SetSigma(sigma);
-  classificationFilter->SetLabelSeparator(initialValue + profileSize * step);
+  using namespace otb::Functor::MultiScaleConvexOrConcaveDecisionRule_tags;
+  classificationFilter->SetVariadicNamedInput<max_opening_profile_derivative>(omsCharFilter->GetOutput());
+  classificationFilter->SetVariadicNamedInput<opening_profile_characteristics>(omsCharFilter->GetOutputCharacteristics());
+  classificationFilter->SetVariadicNamedInput<max_closing_profile_derivative>(cmsCharFilter->GetOutput());
+  classificationFilter->SetVariadicNamedInput<closing_profile_characteristics>(cmsCharFilter->GetOutputCharacteristics());
+  classificationFilter->GetModifiableFunctor().SetSigma(sigma);
+  classificationFilter->GetModifiableFunctor().SetLabelSeparator(initialValue + profileSize * step);
 
   LabeledWriterType::Pointer labeledWriter = LabeledWriterType::New();
 
diff --git a/Modules/Segmentation/OGRProcessing/include/otbOGRLayerStreamStitchingFilter.h b/Modules/Segmentation/OGRProcessing/include/otbOGRLayerStreamStitchingFilter.h
index b3702ad155522de6e79a96f313059dee0b38d472..43750ae207e7cf346d96561050656b005b1d18ba 100644
--- a/Modules/Segmentation/OGRProcessing/include/otbOGRLayerStreamStitchingFilter.h
+++ b/Modules/Segmentation/OGRProcessing/include/otbOGRLayerStreamStitchingFilter.h
@@ -24,10 +24,6 @@
 #include "otbOGRDataSourceWrapper.h"
 #include "otbMacro.h"
 
-//#if(GDAL_VERSION_NUM < 1800)
-//#error OGRLayerStreamStitchingFilter requires GDAL version >= 1.8.0
-//#endif
-
 #include "itkProgressReporter.h"
 
 #include <algorithm>
diff --git a/Modules/Segmentation/OGRProcessing/include/otbOGRLayerStreamStitchingFilter.hxx b/Modules/Segmentation/OGRProcessing/include/otbOGRLayerStreamStitchingFilter.hxx
index 5359e967bfb7224311aa9d452965ea4cc9c4315c..a3c72bb38bdfad22e828baa0e041b102549658c1 100644
--- a/Modules/Segmentation/OGRProcessing/include/otbOGRLayerStreamStitchingFilter.hxx
+++ b/Modules/Segmentation/OGRProcessing/include/otbOGRLayerStreamStitchingFilter.hxx
@@ -291,12 +291,8 @@ OGRLayerStreamStitchingFilter<TInputImage>
                      }
                      else if (intersection->getGeometryType() == wkbMultiLineString)
                      {
-                         #if(GDAL_VERSION_NUM < 1800)
-                     fusion.overlap = GetLengthOGRGeometryCollection(dynamic_cast<OGRGeometryCollection *> (intersection.get()));
-                         #else
                      fusion.overlap = dynamic_cast<OGRMultiLineString *>(intersection.get())->get_Length();
-                         #endif
-                    }
+                     }
 
                      /** -Wunused-variable
                      long upperFID = upper.feat.GetFID();
@@ -325,9 +321,6 @@ OGRLayerStreamStitchingFilter<TInputImage>
                ogr::Field field = upper.feat[0];
                try
                  {
-                 #ifdef OTB_USE_GDAL_20
-                 // In this case, the feature id can be either
-                 // OFTInteger64 or OFTInteger
                  switch(field.GetType())
                    {
                    case OFTInteger64:
@@ -340,10 +333,6 @@ OGRLayerStreamStitchingFilter<TInputImage>
                    fusionFeature[0].SetValue(field.GetValue<int>());
                    }
                    }
-                 #else
-                 // Only OFTInteger supported in this case
-                 fusionFeature[0].SetValue(field.GetValue<int>());
-                 #endif
                  m_OGRLayer.CreateFeature(fusionFeature);
                  m_OGRLayer.DeleteFeature(lower.feat.GetFID());
                  m_OGRLayer.DeleteFeature(upper.feat.GetFID());
diff --git a/Modules/ThirdParty/GDAL/otb-module-init.cmake b/Modules/ThirdParty/GDAL/otb-module-init.cmake
index b13104318f0de04de73b78aaeb59d1aafd203e3c..68bdd5597c3258a8fd27c27a2b1d38814e0a99b2 100644
--- a/Modules/ThirdParty/GDAL/otb-module-init.cmake
+++ b/Modules/ThirdParty/GDAL/otb-module-init.cmake
@@ -35,8 +35,8 @@ if(NOT GDAL_CONFIG_CHECKING)
   return()
 endif()
 
-set(MIN_MAJOR_VERSION 1)
-set(MIN_MINOR_VERSION 10)
+set(MIN_MAJOR_VERSION 2)
+set(MIN_MINOR_VERSION 0)
 
 # Ensure that the temporary dir always exists before starting tests
 if(NOT EXISTS ${TEMP})
@@ -95,11 +95,6 @@ if(EXISTS "${TEMP}/gdalVersion.txt")
   file(READ "${TEMP}/gdalVersion.txt" _GDAL_VERSION_STRING)
   #can't we use GDAL_VERSION_NUM ?
   string(SUBSTRING ${_GDAL_VERSION_STRING} 0 2 VER2)
-  if("${VER2}" STREQUAL "2.")
-    set(OTB_USE_GDAL_20 true CACHE INTERNAL "True if GDAL >= 2.0.0 has been detected" FORCE )
-  else()
-    set(OTB_USE_GDAL_20 false CACHE INTERNAL "True if GDAL >= 2.0.0 has been detected" FORCE )
-  endif()
   set(GDAL_VERSION_STRING "${_GDAL_VERSION_STRING}" CACHE INTERNAL "" FORCE)
 else()
   error_message( "${TEMP}/gdalVersion.txt does not exist. Cannot continue.")
diff --git a/Modules/ThirdParty/OssimPlugins/include/ossim/ossimSarSensorModel.h b/Modules/ThirdParty/OssimPlugins/include/ossim/ossimSarSensorModel.h
index 7bbc7f2df4e4939f9b66d123886abce9bef52da8..8cd2881e0e1fd1b6794ceb44a8562b68aa25a0ce 100644
--- a/Modules/ThirdParty/OssimPlugins/include/ossim/ossimSarSensorModel.h
+++ b/Modules/ThirdParty/OssimPlugins/include/ossim/ossimSarSensorModel.h
@@ -288,12 +288,19 @@ public:
     * Note that the deburst operation has no effect if theBurstRecords
     * contains a single burst. Otherwise it will merge burst together
     * into a single burst, and update GCPs accordingly.
+    * Two modes are available for the output image : with all samples and
+    * with only valid samples. A pair of samples specifies first and last samples
     * \return true if the deburst operation succeeded. No changes is
     * made to the object if the operation fails.
     * \param lines A container for the lines ranges to keep in the
     * deburst image.
+    * \param samples A container for the samples to keep in the
+    * deburst image.
+    * \param onlyValidSample If true, the selected mode is with only valid sample.
     */
-   bool deburst(std::vector<std::pair<unsigned long,unsigned long> >& lines);
+   bool deburst(std::vector<std::pair<unsigned long,unsigned long> >& lines, 
+		std::pair<unsigned long,unsigned long> & samples, bool onlyValidSample=false);
+   
 
    /**
     * This is a helper function to convert image line to deburst image
@@ -314,6 +321,38 @@ public:
     */
    static void deburstLineToImageLine(const std::vector<std::pair<unsigned long,unsigned long> >& lines, unsigned long deburstLine, unsigned long & imageLine);
 
+   /**
+    * This method will perform an extration of one burst. It wil return the
+    * lines and samples to extract in the image file.
+    * \return true if the extraction operation succeeded. No changes is
+    * made to the object if the operation fails.
+    * \param burst_index Index of Burst.
+    * \param lines A container for the lines to keep in the
+    * standalone burst.
+    * \param samples A container for the samples to keep in the
+    * standalone burst.
+    */
+   bool burstExtraction(const unsigned int burst_index, std::pair<unsigned long,unsigned long> & lines, 
+			std::pair<unsigned long,unsigned long> & samples, bool allPixels=false);
+
+   /**
+    * This method will perform a deburst and concatenation operation, and return the
+    * vector of lines and the vector of samples to keep in the 
+    * image file. The lines and samples represents start/size into each indepedent bursts. 
+    * Note that the deburst operation has no effect if theBurstRecords
+    * contains a single burst. Otherwise it will merge burst together
+    * into a single burst, and update GCPs accordingly.
+    * \return true if the deburst operation succeeded. No changes is
+    * made to the object if the operation fails.
+    * \param lines A container for the lines ranges to keep in the
+    * deburst image.
+    * \param samples A container for the samples ranges to keep in the
+    * deburst image.
+    * \param lines A Boolean to indicate only valids samples are required.
+    */
+   bool deburstAndConcatenate(std::vector<std::pair<unsigned long,unsigned long> >& linesBursts, 
+			      std::vector<std::pair<unsigned long,unsigned long> >& samplesBursts);
+
    /**
     * Returns pointer to a new instance, copy of this.
     */
@@ -453,6 +492,14 @@ protected:
    double                                      theRangeTimeOffset; // Offset in seconds, computed
    bool                                        theRightLookingFlag;
    
+   TimeType                                    theFirstLineTime;
+   TimeType                                    theLastLineTime;
+
+   unsigned long                                theNumberOfLinesPerBurst;
+   unsigned long                                theNumberOfSamplesPerBurst;
+
+   bool redaptMedataAfterDeburst;
+   
    static const double C;
 
    static const unsigned int thePluginVersion; // version of the SarSensorModel plugin
diff --git a/Modules/ThirdParty/OssimPlugins/src/ossim/ossimSarSensorModel.cpp b/Modules/ThirdParty/OssimPlugins/src/ossim/ossimSarSensorModel.cpp
index 31c046fe6baed47cf66876f07021e43d2c7a5fd5..ddb5bda193e99aade9a595a29b932245cee695ab 100644
--- a/Modules/ThirdParty/OssimPlugins/src/ossim/ossimSarSensorModel.cpp
+++ b/Modules/ThirdParty/OssimPlugins/src/ossim/ossimSarSensorModel.cpp
@@ -139,7 +139,8 @@ namespace ossimplugins
       theBistaticCorrectionNeeded(false),
       theAzimuthTimeOffset(seconds(0)),
       theRangeTimeOffset(0.),
-      theRightLookingFlag(true)
+      theRightLookingFlag(true),
+      redaptMedataAfterDeburst(false)
       {}
 
    ossimSarSensorModel::GCPRecordType const&
@@ -1359,6 +1360,14 @@ bool ossimSarSensorModel::worldToAzimuthRangeTime(const ossimGpt& worldPt, TimeT
 
      add(kwl, HEADER_PREFIX, "version", thePluginVersion);
 
+     if (redaptMedataAfterDeburst)
+       {
+	 add(kwl, SUPPORT_DATA_PREFIX, "first_line_time", theFirstLineTime);
+	 add(kwl, SUPPORT_DATA_PREFIX, "last_line_time", theLastLineTime);
+	 add(kwl, HEADER_PREFIX, "first_line_time", theFirstLineTime);
+	 add(kwl, HEADER_PREFIX, "last_line_time", theLastLineTime);
+       }
+
      return ossimSensorModel::saveState(kwl, prefix);
    }
 
@@ -1386,17 +1395,32 @@ bool ossimSarSensorModel::worldToAzimuthRangeTime(const ossimGpt& worldPt, TimeT
          get(kwl, SUPPORT_DATA_PREFIX, "radar_frequency"           , theRadarFrequency     );
          double azimuthTimeInterval = 0.; // in seconds
          get(kwl, SUPPORT_DATA_PREFIX, "line_time_interval"        , azimuthTimeInterval);
+
 #if defined(USE_BOOST_TIME)
          theAzimuthTimeInterval = boost::posix_time::precise_duration(azimuthTimeInterval * 1000000.);
 #else
          theAzimuthTimeInterval = seconds(azimuthTimeInterval);
 #endif
-
          get(kwl, theOrbitRecords);
          // TODO: don't fetch burst records if already read thanks to xml loading
          // that required them
          theBurstRecords.clear();
          get(kwl, theBurstRecords);
+	 
+	 if(theBurstRecords.size() > 1)
+	   {
+	     unsigned int version;
+	     get(kwl, HEADER_PREFIX, "version", version);
+
+	     if (version > 2)
+	       {
+		 const std::string BURST_NUMBER_LINES_KEY    = "support_data.geom.bursts.number_lines_per_burst";
+		 const std::string BURST_NUMBER_SAMPLES_KEY    = "support_data.geom.bursts.number_samples_per_burst";
+		 get(kwl, BURST_NUMBER_LINES_KEY, theNumberOfLinesPerBurst);
+		 get(kwl, BURST_NUMBER_SAMPLES_KEY, theNumberOfSamplesPerBurst);
+	       }
+	   }
+	 
          if (isGRD())
          {
             get(kwl, SR_PREFIX, keySr0, theSlantRangeToGroundRangeRecords);
@@ -1425,7 +1449,8 @@ bool ossimSarSensorModel::worldToAzimuthRangeTime(const ossimGpt& worldPt, TimeT
       return false;
    }
 
-bool ossimSarSensorModel::deburst(std::vector<std::pair<unsigned long, unsigned long> >& lines)
+bool ossimSarSensorModel::deburst(std::vector<std::pair<unsigned long, unsigned long> >& lines, 
+				  std::pair<unsigned long,unsigned long> & samples, bool onlyValidSample)
 {
   if(theBurstRecords.empty())
     return false;
@@ -1452,6 +1477,8 @@ bool ossimSarSensorModel::deburst(std::vector<std::pair<unsigned long, unsigned
   TimeType deburstAzimuthStartTime = it->azimuthStartTime;
 
   unsigned long deburstEndLine = 0;
+
+  samples = std::make_pair(it->startSample, it->endSample);
   
   for(; next!= itend ;++it,++next)
     {
@@ -1466,17 +1493,44 @@ bool ossimSarSensorModel::deburst(std::vector<std::pair<unsigned long, unsigned
       
     unsigned long currentStop = it->endLine-halfLineOverlapEnd;
 
-    deburstEndLine+=currentStop-currentStart;
+    deburstEndLine+= currentStop - currentStart + 1; // +1 because currentStart/Stop are both valids
+
     
     lines.push_back(std::make_pair(currentStart,currentStop));
 
-    currentStart = next->startLine+halfLineOverlapBegin;    
+    currentStart = next->startLine+halfLineOverlapBegin;
+
+     if (onlyValidSample)
+      {
+	// Find the first and last valid sampleburst
+	if (it->startSample > samples.first)
+	  {
+	    samples.first = it->startSample;
+	  }
+	if (it->endSample < samples.second)
+	  {
+	    samples.second = it->endSample;
+	  }
+      }
     }
 
   TimeType deburstAzimuthStopTime = it->azimuthStopTime;
   deburstEndLine+=it->endLine-currentStart;
 
   lines.push_back(std::make_pair(currentStart,it->endLine));
+
+  if (onlyValidSample)
+    {
+      if (it->startSample > samples.first)
+	{
+	  samples.first = it->startSample;
+	}
+      if (it->endSample < samples.second)
+	{
+	  samples.second = it->endSample;
+	}
+    }
+
   
   // Now, update other metadata accordingly
 
@@ -1489,6 +1543,13 @@ bool ossimSarSensorModel::deburst(std::vector<std::pair<unsigned long, unsigned
   deburstBurst.azimuthStartTime = deburstAzimuthStartTime;
   deburstBurst.endLine = deburstEndLine;
   deburstBurst.azimuthStopTime = deburstAzimuthStopTime;
+
+  if (onlyValidSample)
+    {
+      deburstBurst.startSample = 0;
+      deburstBurst.endSample = samples.second - samples.first;
+    }
+
   
   theBurstRecords.push_back(deburstBurst);
 
@@ -1501,24 +1562,355 @@ bool ossimSarSensorModel::deburst(std::vector<std::pair<unsigned long, unsigned
       unsigned long newLine=0;
 
       unsigned long gcpLine = std::floor(currentGCP.imPt.y+0.5);
+      unsigned long gcpSample = std::floor(currentGCP.imPt.x+0.5);
+
 
       // Be careful about fractional part of GCPs
-      double fractional = currentGCP.imPt.y - gcpLine;
-      
-      bool deburstOk = imageLineToDeburstLine(lines,gcpLine,newLine);
+      double fractionalLines = currentGCP.imPt.y - gcpLine;
+      double fractionalSamples = currentGCP.imPt.x - gcpSample;
 
-      if(deburstOk)
+      bool linesOk = imageLineToDeburstLine(lines,gcpLine,newLine);
+
+      // Gcp into valid samples
+      bool samplesOk = true;
+      unsigned long newSample = gcpSample;
+      
+      if (onlyValidSample)
+	{
+	  samplesOk = false;
+	  if (gcpSample >= samples.first && gcpSample <= samples.second)
+	    {
+	      samplesOk = true;
+	      newSample -= samples.first; // Offset with first valid sample
+	    } 
+	}
+
+      if(linesOk && samplesOk)
         {
-        currentGCP.imPt.y = newLine+fractional;
-        deburstGCPs.push_back(currentGCP);
+	  currentGCP.imPt.y = newLine + fractionalLines;
+	  currentGCP.imPt.x = newSample + fractionalSamples;
+	  
+	  deburstGCPs.push_back(currentGCP);
         }        
       }
 
   theGCPRecords.swap(deburstGCPs);
 
+
+  // Adapt general metadata : theNearRangeTime, first_time_line, last_time_line
+  redaptMedataAfterDeburst = true;
+  theFirstLineTime = deburstBurst.azimuthStartTime;
+  theLastLineTime = deburstBurst.azimuthStopTime;
+  
+  if (onlyValidSample)
+    theNearRangeTime += samples.first*(1/theRangeSamplingRate); 
+
+
   return true;
 }
 
+
+bool 
+ossimSarSensorModel::burstExtraction(const unsigned int burst_index, 
+				     std::pair<unsigned long,unsigned long> & lines, 
+				     std::pair<unsigned long,unsigned long> & samples, bool allPixels)
+{
+   if(theBurstRecords.empty())
+    return false;
+
+   // Check the single burst record case
+   if(theBurstRecords.size() == 1)
+     {
+       lines = std::make_pair(theBurstRecords.front().startLine,theBurstRecords.front().endLine);
+       return false;
+     }
+
+   // If all pixels is required
+   if (allPixels)
+     {
+       samples = std::make_pair(0, theNumberOfSamplesPerBurst - 1);
+       lines = std::make_pair(burst_index*theNumberOfLinesPerBurst, (burst_index+1)*theNumberOfLinesPerBurst - 1);
+       
+       redaptMedataAfterDeburst = true;
+       theFirstLineTime = theBurstRecords[burst_index].azimuthStartTime - (theBurstRecords[burst_index].startLine - lines.first) * theAzimuthTimeInterval;
+       theLastLineTime = theFirstLineTime + (lines.second - lines.first) * theAzimuthTimeInterval;
+
+       // Clear the previous burst records
+       theBurstRecords.clear();
+
+       // Create the single burst
+       BurstRecordType oneBurst;
+       oneBurst.startLine = 0;
+       oneBurst.azimuthStartTime = theFirstLineTime;
+       oneBurst.endLine = lines.second - lines.first;
+       oneBurst.azimuthStopTime = theLastLineTime;
+       oneBurst.startSample = 0;
+       oneBurst.endSample = samples.second - samples.first;
+   
+       theBurstRecords.push_back(oneBurst);
+     }
+   else
+     {
+       // Retrieve into TheBurstRecord, the required index
+       BurstRecordType burstInd_Record = theBurstRecords[burst_index];
+       lines = std::make_pair(burstInd_Record.startLine, burstInd_Record.endLine);
+       samples = std::make_pair(burstInd_Record.startSample, burstInd_Record.endSample);
+       TimeType burstAzimuthStartTime = burstInd_Record.azimuthStartTime;
+       TimeType burstAzimuthStopTime = burstInd_Record.azimuthStopTime;
+
+       // Clear the previous burst records
+       theBurstRecords.clear();
+
+       // Create the single burst
+       BurstRecordType oneBurst;
+       oneBurst.startLine = 0;
+       oneBurst.azimuthStartTime = burstAzimuthStartTime;
+       oneBurst.endLine = lines.second - lines.first;
+       oneBurst.azimuthStopTime = burstAzimuthStopTime;
+       oneBurst.startSample = 0;
+       oneBurst.endSample = samples.second - samples.first;
+   
+       theBurstRecords.push_back(oneBurst);
+
+       // Adapt general metadata : theNearRangeTime, first_time_line, last_time_line
+       redaptMedataAfterDeburst = true;
+       theFirstLineTime = oneBurst.azimuthStartTime;
+       theLastLineTime = oneBurst.azimuthStopTime;
+       theNearRangeTime += samples.first*(1/theRangeSamplingRate); 
+     }
+
+    std::vector<GCPRecordType> oneBurstGCPs;
+    
+    // Now move GCPs
+    for (auto const& token : theGCPRecords)   
+      {
+	GCPRecordType currentGCP = token;
+
+	unsigned long gcpLine = std::floor(currentGCP.imPt.y+0.5);
+	unsigned long gcpSample = std::floor(currentGCP.imPt.x+0.5);
+
+	// Be careful about fractional part of GCPs
+	double fractionalLines = currentGCP.imPt.y - gcpLine;
+	double fractionalSamples = currentGCP.imPt.x - gcpSample;
+
+
+	// Gcp into valid samples and valid lines
+	unsigned long newSample = gcpSample;
+	bool samplesOk = false;
+	
+	if (gcpSample >= samples.first && gcpSample <= samples.second)
+	  {
+	    samplesOk = true;
+	    newSample -= samples.first; // Offset with first valid sample
+	  } 
+
+	unsigned long newLine = gcpLine;
+	bool linesOk = false;
+	
+	if (gcpLine >= lines.first && gcpLine <= lines.second)
+	  {
+	    linesOk = true;
+	    newLine -= lines.first; // Offset with first valid line
+	  }
+      
+	if(linesOk && samplesOk)
+	  {
+	    currentGCP.imPt.y = newLine + fractionalLines;
+	    currentGCP.imPt.x = newSample + fractionalSamples;
+	    oneBurstGCPs.push_back(currentGCP);
+	  }        
+      }
+
+  theGCPRecords.swap(oneBurstGCPs);
+
+  return true;
+}
+
+bool 
+ossimSarSensorModel::deburstAndConcatenate(std::vector<std::pair<unsigned long,unsigned long> >& linesBursts, 
+					   std::vector<std::pair<unsigned long,unsigned long> >& samplesBursts)
+{
+   if(theBurstRecords.empty())
+    return false;
+  
+   // declare lines and samples 
+   std::vector<std::pair<unsigned long,unsigned long> > lines;
+   lines.reserve(theBurstRecords.size());
+   std::pair<unsigned long,unsigned long> samples;
+
+   // First, clear lines record
+   linesBursts.clear();
+   samplesBursts.clear();
+
+   // Check the single burst record case
+   if(theBurstRecords.size() == 1)
+     {
+       linesBursts.push_back(std::make_pair(theBurstRecords.front().startLine,theBurstRecords.front().endLine));
+       samplesBursts.push_back(std::make_pair(theBurstRecords.front().startLine,theBurstRecords.front().endLine));
+       return false;
+     }
+
+
+   ///////// deburst operation ////////
+   // Process each burst
+   std::vector<BurstRecordType>::const_iterator it = theBurstRecords.begin();
+   // Correct since we have at least 2 bursts records
+   std::vector<BurstRecordType>::const_iterator next = it+1;
+   std::vector<BurstRecordType>::const_iterator itend = theBurstRecords.end();
+
+   unsigned long currentStart  = it->startLine;  
+   TimeType deburstAzimuthStartTime = it->azimuthStartTime;
+
+   unsigned long deburstEndLine = 0;
+  
+   samples = std::make_pair(it->startSample, it->endSample);
+
+   // Store halfLineOverlapBegin/End
+   unsigned long * halfLineOverlapBegin = new unsigned long[theBurstRecords.size()];
+   unsigned long * halfLineOverlapEnd = new unsigned long[theBurstRecords.size()];
+   
+   halfLineOverlapBegin[0] = 0;
+
+   unsigned int counterBegin = 1;
+   unsigned int counterEnd = 0;
+
+   for(; next!= itend ;++it,++next)
+     {
+       DurationType timeOverlapEnd = (it->azimuthStopTime - next->azimuthStartTime);
+
+       unsigned long overlapLength = timeOverlapEnd/theAzimuthTimeInterval;
+
+       halfLineOverlapEnd[counterEnd] = overlapLength/2;
+       TimeType endTimeInNextBurst = it->azimuthStopTime-(halfLineOverlapEnd[counterEnd]-1)*theAzimuthTimeInterval;
+    
+       halfLineOverlapBegin[counterBegin] = std::floor(0.5+(endTimeInNextBurst-next->azimuthStartTime)/theAzimuthTimeInterval);
+      
+       unsigned long currentStop = it->endLine-halfLineOverlapEnd[counterEnd];
+
+       deburstEndLine+= currentStop - currentStart + 1; // +1 because currentStart/Stop are both valids
+    
+       lines.push_back(std::make_pair(currentStart,currentStop));
+
+       currentStart = next->startLine+halfLineOverlapBegin[counterBegin];
+
+       // Find the first and last valid sampleburst
+       if (it->startSample > samples.first)
+	 {
+	   samples.first = it->startSample;
+	 }
+       if (it->endSample < samples.second)
+	 {
+	   samples.second = it->endSample;
+	 }
+
+
+       ++counterBegin;
+       ++counterEnd;
+     }
+
+   halfLineOverlapEnd[theBurstRecords.size() - 1] = 0;
+   
+   TimeType deburstAzimuthStopTime = it->azimuthStopTime;
+   deburstEndLine+=it->endLine - currentStart;
+
+   lines.push_back(std::make_pair(currentStart,it->endLine));
+
+   if (it->startSample > samples.first)
+     {
+       samples.first = it->startSample;
+     }
+   if (it->endSample < samples.second)
+     {
+       samples.second = it->endSample;
+     }
+  
+   // Now, update other metadata accordingly
+   std::vector<GCPRecordType> deburstGCPs;
+  
+   // Now move GCPs
+   for(std::vector<GCPRecordType>::iterator gcpIt = theGCPRecords.begin(); gcpIt!=theGCPRecords.end();++gcpIt)
+     {
+       GCPRecordType currentGCP = *gcpIt;
+       unsigned long newLine=0;
+
+       unsigned long gcpLine = std::floor(currentGCP.imPt.y+0.5);
+       unsigned long gcpSample = std::floor(currentGCP.imPt.x+0.5);
+
+       // Be careful about fractional part of GCPs
+       double fractionalLines = currentGCP.imPt.y - gcpLine;
+       double fractionalSamples = currentGCP.imPt.x - gcpSample;
+
+       bool linesOk = imageLineToDeburstLine(lines,gcpLine,newLine);
+
+       // Gcp into valid samples
+       unsigned long newSample = gcpSample;
+      
+       if (linesOk && gcpSample >= samples.first && gcpSample <= samples.second)
+	 {
+	   newSample -= samples.first; // Offset with first valid sample
+	   currentGCP.imPt.y = newLine + fractionalLines;
+	   currentGCP.imPt.x = newSample + fractionalSamples;
+	   deburstGCPs.push_back(currentGCP);
+	 }
+     }
+
+   theGCPRecords.swap(deburstGCPs);
+
+   ///// linesBursts and samplesBursts (into Burst geometry) /////
+   std::vector<BurstRecordType>::const_iterator itBursts = theBurstRecords.begin();
+   std::vector<std::pair<unsigned long,unsigned long> >::const_iterator itlines = lines.begin();
+   
+   unsigned int counter = 0;
+
+   for(; itBursts!= theBurstRecords.end() ;++itBursts)
+     {       
+       unsigned long currentStart_L = halfLineOverlapBegin[counter];
+       unsigned long currentStop_L = itBursts->endLine - itBursts->startLine - halfLineOverlapEnd[counter];
+       linesBursts.push_back(std::make_pair(currentStart_L, currentStop_L));
+
+       unsigned long currentStart_S = 0;
+       unsigned long currentStop_S = samples.second-samples.first;
+
+       if (itBursts->startSample < samples.first)
+	 {
+	   currentStart_S = samples.first - itBursts->startSample;
+	 }
+       currentStop_S += currentStart_S;
+
+       samplesBursts.push_back(std::make_pair(currentStart_S, currentStop_S));
+
+       ++counter;
+     }
+
+   // Clear the previous burst records
+   theBurstRecords.clear();
+
+   // Create the single burst
+   BurstRecordType deburstBurst;
+   deburstBurst.startLine = 0;
+   deburstBurst.azimuthStartTime = deburstAzimuthStartTime;
+   deburstBurst.endLine = deburstEndLine;
+   deburstBurst.azimuthStopTime = deburstAzimuthStopTime;
+   deburstBurst.startSample = 0;
+   deburstBurst.endSample = samples.second - samples.first;
+
+   theBurstRecords.push_back(deburstBurst);
+
+   // Adapt general metadata : theNearRangeTime, first_time_line, last_time_line
+   redaptMedataAfterDeburst = true;
+   theFirstLineTime = deburstBurst.azimuthStartTime;
+   theLastLineTime = deburstBurst.azimuthStopTime;
+  
+   theNearRangeTime += samples.first*(1/theRangeSamplingRate); 
+
+   // Free Memory
+   delete [] halfLineOverlapBegin;
+   delete [] halfLineOverlapEnd;
+
+   return true;
+}
+
+
 bool ossimSarSensorModel::imageLineToDeburstLine(const std::vector<std::pair<unsigned long,unsigned long> >& lines, unsigned long imageLine, unsigned long & deburstLine)
 {
   std::vector<std::pair<unsigned long,unsigned long> >::const_iterator vit = lines.begin();
diff --git a/Modules/ThirdParty/OssimPlugins/test/ossimSentinel1ModelTest.cpp b/Modules/ThirdParty/OssimPlugins/test/ossimSentinel1ModelTest.cpp
index ca968e66dfa844a0bddafd6f4088814d68b91877..698519844650f95d5ca81885c017cffacea60d78 100644
--- a/Modules/ThirdParty/OssimPlugins/test/ossimSentinel1ModelTest.cpp
+++ b/Modules/ThirdParty/OssimPlugins/test/ossimSentinel1ModelTest.cpp
@@ -109,9 +109,10 @@ int main(int argc, char * argv[])
          ;
       
       std::vector<std::pair<unsigned long, unsigned long> > deburstLines;
+      std::pair<unsigned long, unsigned long> deburstSamples;
 
       std::cout<<"Trying to deburst data ..."<<std::endl;
-      bool deburstOk = sensor->deburst(deburstLines);
+      bool deburstOk = sensor->deburst(deburstLines, deburstSamples);
       std::cout<<"Deburst succeed: "<<(deburstOk?"yes":"no")<<std::endl;
 
       if(deburstOk)