diff --git a/CMake/OTBCheckCpp11Keywords.cmake b/CMake/OTBCheckCpp11Keywords.cmake
index 09e13b4182768447cee83e4bf7745a6f58f18f52..31a30c5cdea1e4a3b36c90231e486d736de68352 100644
--- a/CMake/OTBCheckCpp11Keywords.cmake
+++ b/CMake/OTBCheckCpp11Keywords.cmake
@@ -2,4 +2,4 @@
 try_compile(OTB_IS_UNIQUE_PTR_DEFINED ${CMAKE_CURRENT_BINARY_DIR}/CMake ${CMAKE_SOURCE_DIR}/CMake/otbTestUniquePtr.cpp)
 try_compile(OTB_IS_OVERRIDE_DEFINED ${CMAKE_CURRENT_BINARY_DIR}/CMake ${CMAKE_SOURCE_DIR}/CMake/otbTestUniquePtr.cpp)
 try_compile(OTB_IS_NULLPTR_DEFINED ${CMAKE_CURRENT_BINARY_DIR}/CMake ${CMAKE_SOURCE_DIR}/CMake/otbTestUniquePtr.cpp)
-
+try_compile(OTB_HAS_CXX11 ${CMAKE_CURRENT_BINARY_DIR}/CMake ${CMAKE_SOURCE_DIR}/CMake/otbTestUniquePtr.cpp)
diff --git a/CMake/OTBModuleHeaderTest.cmake b/CMake/OTBModuleHeaderTest.cmake
index c381f0d7bfa6347878d2465f1cabc5ef54366865..6a1c72158a365e323c9b4f84529f03f8ccf38b3e 100644
--- a/CMake/OTBModuleHeaderTest.cmake
+++ b/CMake/OTBModuleHeaderTest.cmake
@@ -25,7 +25,9 @@ SET(BANNED_HEADERS)
 if(NOT OTB_USE_OPENCV)
 	SET(BANNED_HEADERS "${BANNED_HEADERS} otbDecisionTreeMachineLearningModelFactory.h otbDecisionTreeMachineLearningModel.h otbKNearestNeighborsMachineLearningModelFactory.h otbKNearestNeighborsMachineLearningModel.h otbRandomForestsMachineLearningModelFactory.h otbRandomForestsMachineLearningModel.h otbSVMMachineLearningModelFactory.h otbSVMMachineLearningModel.h otbGradientBoostedTreeMachineLearningModelFactory.h otbGradientBoostedTreeMachineLearningModel.h otbBoostMachineLearningModelFactory.h otbBoostMachineLearningModel.h otbNeuralNetworkMachineLearningModelFactory.h otbNeuralNetworkMachineLearningModel.h otbNormalBayesMachineLearningModelFactory.h otbNormalBayesMachineLearningModel.h otbRequiresOpenCVCheck.h otbOpenCVUtils.h otbCvRTreesWrapper.h")
 endif()
- 
+if(NOT OTB_USE_SHARK)
+  SET(BANNED_HEADERS "${BANNED_HEADERS} otbSharkRandomForestsMachineLearningModel.h otbSharkRandomForestsMachineLearningModel.txx otbSharkUtils.h otbRequiresSharkCheck.h otbSharkRandomForestsMachineLearningModelFactory.h")  
+endif()
 if(NOT OTB_USE_LIBSVM)
 	SET(BANNED_HEADERS "${BANNED_HEADERS} otbLibSVMMachineLearningModel.h otbLibSVMMachineLearningModelFactory.h")
 endif()
diff --git a/CMake/OTBModuleMacros.cmake b/CMake/OTBModuleMacros.cmake
index 320b7f66b0a741ba1b71121a88f91e9e73efa013..4b6f20161423687471f68dc753a85e341a1e4b05 100644
--- a/CMake/OTBModuleMacros.cmake
+++ b/CMake/OTBModuleMacros.cmake
@@ -324,3 +324,9 @@ macro(otb_module_target _name)
     otb_module_target_install(${_name})
   endif()
 endmacro()
+
+macro(otb_module_requires_cxx11)
+  if(NOT ${OTB_HAS_CXX11})
+    message(FATAL_ERROR "Module ${otb-module} requires C++11 support. Consider adding --std=c++11 to your compiler flags.")
+  endif()  
+endmacro()
diff --git a/CMake/OTBSetStandardCompilerFlags.cmake b/CMake/OTBSetStandardCompilerFlags.cmake
index a264550f732429bd90158980dd49c6bdf20e77dc..d3b11b8a1f2a047bea12d451773bf2b7d53e5f7f 100644
--- a/CMake/OTBSetStandardCompilerFlags.cmake
+++ b/CMake/OTBSetStandardCompilerFlags.cmake
@@ -143,21 +143,6 @@ endfunction()
 
 
 macro(check_compiler_platform_flags)
-  # Since CMake 2.8.11, the size of the stack is not modified by CMake on
-  # windows platform, it uses the default size: with visual compiler it is 1Mbyte
-  # which is to lower for us (thanks to 6S code).
-  # if(MSVC)
-  #   if("${CMAKE_EXE_LINKER_FLAGS}" MATCHES "/STACK:[0-9]+")
-  #     message(STATUS "The size of the stack is already defined, so we don't modified it.")
-  #   else()
-  #     set(OTB_REQUIRED_LINK_FLAGS "${OTB_REQUIRED_LINK_FLAGS} /STACK:10000000")
-  #     message(STATUS "The stack size is set to 10 Mbytes (/STACK:10000000).")
-  #   endif()
-  # elseif(MINGW)
-  #   set(OTB_REQUIRED_LINK_FLAGS "${OTB_REQUIRED_LINK_FLAGS} -Wl,--stack,10000000")
-  #   message(STATUS "The stack size is set to 10 Mbytes (-Wl,--stack,10000000).")
-  # endif() # if(MSVC)
-
   # On Visual Studio 8 MS deprecated C. This removes all 1.276E1265 security
   # warnings
   if(WIN32)
diff --git a/CMake/otbCheckCXX11.cpp b/CMake/otbCheckCXX11.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..17853f2a02b63b4c226c54a553adba657b2eb596
--- /dev/null
+++ b/CMake/otbCheckCXX11.cpp
@@ -0,0 +1,8 @@
+#if __cplusplus <= 199711L
+  #error Compiler is not C++11 compliant
+#endif
+
+int main(int argc, char *argv[])
+{
+  return 0;
+}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c37da5d534cf2c4946514fe36c65850b6bda365d..4b48264c0d590f98286796188bf9981ca46e02ce 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -442,6 +442,7 @@ foreach(otb_option
     CMAKE_BUILD_TYPE
     CMAKE_C_FLAGS
     CMAKE_CXX_FLAGS
+    OTB_HAS_CXX11
     ${option_list}
     OTB_WRAP_PYTHON
     OTB_WRAP_JAVA
diff --git a/Modules/Applications/AppClassification/app/otbComputeImagesStatistics.cxx b/Modules/Applications/AppClassification/app/otbComputeImagesStatistics.cxx
index 990d41ba1a9d7fb4e80ad69ee4ef1c7db3d9a96c..b3e2a04b5ebe9ce9647f0e0c46979080971e0b4d 100644
--- a/Modules/Applications/AppClassification/app/otbComputeImagesStatistics.cxx
+++ b/Modules/Applications/AppClassification/app/otbComputeImagesStatistics.cxx
@@ -66,6 +66,8 @@ private:
     SetParameterDescription( "out", "XML filename where the statistics are saved for future reuse." );
     MandatoryOff("out");
 
+    AddRAMParameter();
+
    // Doc example parameter settings
    SetDocExampleParameterValue("il", "QB_1_ortho.tif");
    SetDocExampleParameterValue("out", "EstimateImageStatisticsQB1.xml");
@@ -128,6 +130,7 @@ private:
       processName << "Processing Image (" << imageId+1 << "/" << imageList->Size() << ")";
       AddProcess(statsEstimator->GetStreamer(), processName.str().c_str());
       statsEstimator->SetInput(image);
+      statsEstimator->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram"));
       if( HasValue( "bv" )==true )
         {
         statsEstimator->SetIgnoreUserDefinedValue(true);
diff --git a/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx b/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx
index 9a121ab8324cca321c00c2c031caa7ed854f4b36..a6167febed174d998276e97b23f8e8994a6f2d40 100644
--- a/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx
+++ b/Modules/Applications/AppClassification/app/otbPolygonClassStatistics.cxx
@@ -171,6 +171,7 @@ private:
   filter->SetOGRData(reprojVector);
   filter->SetFieldName(fieldName);
   filter->SetLayerIndex(this->GetParameterInt("layer"));
+  filter->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram"));
 
   AddProcess(filter->GetStreamer(),"Analyse polygons...");
   filter->Update();
diff --git a/Modules/Applications/AppClassification/app/otbTrainImagesClassifier.cxx b/Modules/Applications/AppClassification/app/otbTrainImagesClassifier.cxx
index 87d80a7a4410f96dbb2e0af7880c066c19e23b28..932454f0b5ebe89bd84c9367b6c582b9cd3c0970 100644
--- a/Modules/Applications/AppClassification/app/otbTrainImagesClassifier.cxx
+++ b/Modules/Applications/AppClassification/app/otbTrainImagesClassifier.cxx
@@ -120,8 +120,8 @@ void DoInit() ITK_OVERRIDE
     "validation sets per class and per image.\n Several classifier parameters can be set depending on the chosen classifier. In the "
     "validation process, the confusion matrix is organized the following way: rows = reference labels, columns = produced labels. "
     "In the header of the optional confusion matrix output file, the validation (reference) and predicted (produced) class labels"
-    " are ordered according to the rows/columns of the confusion matrix.\n This application is based on LibSVM and on OpenCV Machine Learning "
-    "classifiers, and is compatible with OpenCV 2.3.1 and later.");
+    " are ordered according to the rows/columns of the confusion matrix.\n This application is based on LibSVM and OpenCV Machine Learning "
+    "(2.3.1 and later).");
   SetDocLimitations("None");
   SetDocAuthors("OTB-Team");
   SetDocSeeAlso("OpenCV documentation for machine learning http://docs.opencv.org/modules/ml/doc/ml.html ");
diff --git a/Modules/Applications/AppClassification/include/otbLearningApplicationBase.h b/Modules/Applications/AppClassification/include/otbLearningApplicationBase.h
index aaeb2e2ebd5984bc5d7c7538c076cfc2500fc499..6fd04d059d43c7be3450bc51fcf4a17e457e2c1b 100644
--- a/Modules/Applications/AppClassification/include/otbLearningApplicationBase.h
+++ b/Modules/Applications/AppClassification/include/otbLearningApplicationBase.h
@@ -31,22 +31,26 @@
 #include "otbMachineLearningModelFactory.h"
 
 #ifdef OTB_USE_OPENCV
-# include "otbKNearestNeighborsMachineLearningModel.h"
-# include "otbRandomForestsMachineLearningModel.h"
+#include "otbKNearestNeighborsMachineLearningModel.h"
+#include "otbRandomForestsMachineLearningModel.h"
 // OpenCV SVM implementation is buggy with linear kernel
 // Users should use the libSVM implementation instead.
-//# include "otbSVMMachineLearningModel.h"
-# include "otbBoostMachineLearningModel.h"
-# include "otbDecisionTreeMachineLearningModel.h"
-# include "otbGradientBoostedTreeMachineLearningModel.h"
-# include "otbNormalBayesMachineLearningModel.h"
-# include "otbNeuralNetworkMachineLearningModel.h"
+//#include "otbSVMMachineLearningModel.h"
+#include "otbBoostMachineLearningModel.h"
+#include "otbDecisionTreeMachineLearningModel.h"
+#include "otbGradientBoostedTreeMachineLearningModel.h"
+#include "otbNormalBayesMachineLearningModel.h"
+#include "otbNeuralNetworkMachineLearningModel.h"
 #endif
 
 #ifdef OTB_USE_LIBSVM 
 #include "otbLibSVMMachineLearningModel.h"
 #endif
 
+#ifdef OTB_USE_SHARK
+#include "otbSharkRandomForestsMachineLearningModel.h"
+#endif
+
 namespace otb
 {
 namespace Wrapper
@@ -62,11 +66,12 @@ namespace Wrapper
  * methods. The classes derived from LearningApplicationBase only need these
  * 3 methods to handle the machine learning model.
  *
- * There are multiple machine learning models in OTB, some imported from OpenCV,
- * and one imported from LibSVM. They all have different parameters. The
- * purpose of this class is to handle the creation of all parameters related to
- * machine learning models (in DoInit() ), and to dispatch the calls to
- * specific train functions in function Train().
+ * There are multiple machine learning models in OTB, some imported
+ * from OpenCV and one imported from LibSVM. They all have
+ * different parameters. The purpose of this class is to handle the
+ * creation of all parameters related to machine learning models (in
+ * DoInit() ), and to dispatch the calls to specific train functions
+ * in function Train().
  *
  * This class is templated over scalar types for input and output values.
  * Typically, the input value type will be either float of double. The choice
@@ -131,7 +136,11 @@ public:
 #ifdef OTB_USE_LIBSVM 
   typedef otb::LibSVMMachineLearningModel<InputValueType, OutputValueType> LibSVMType;
 #endif
- 
+
+#ifdef OTB_USE_SHARK
+  typedef otb::SharkRandomForestsMachineLearningModel<InputValueType, OutputValueType> SharkRandomForestType;
+#endif
+  
 protected:
   LearningApplicationBase();
 
@@ -206,6 +215,13 @@ private:
                 typename TargetListSampleType::Pointer trainingLabeledListSample,
                 std::string modelPath);
 #endif
+
+#ifdef OTB_USE_SHARK
+  void InitSharkRandomForestsParams();
+  void TrainSharkRandomForests(typename ListSampleType::Pointer trainingListSample,
+                               typename TargetListSampleType::Pointer trainingLabeledListSample,
+                               std::string modelPath);
+#endif
   //@}
 };
 
@@ -229,6 +245,9 @@ private:
 #ifdef OTB_USE_LIBSVM
 #include "otbTrainLibSVM.txx"
 #endif
+#ifdef OTB_USE_SHARK
+#include "otbTrainSharkRandomForests.txx"
+#endif
 #endif
 
 #endif
diff --git a/Modules/Applications/AppClassification/include/otbLearningApplicationBase.txx b/Modules/Applications/AppClassification/include/otbLearningApplicationBase.txx
index d92296ff4b551a0ea245c4149f6fd97aff87f153..bf110c82738e1223469bb2e0c486e6f911e5afd5 100644
--- a/Modules/Applications/AppClassification/include/otbLearningApplicationBase.txx
+++ b/Modules/Applications/AppClassification/include/otbLearningApplicationBase.txx
@@ -73,6 +73,11 @@ LearningApplicationBase<TInputValue,TOutputValue>
   InitRandomForestsParams();
   InitKNNParams();
 #endif
+
+#ifdef OTB_USE_SHARK
+  InitSharkRandomForestsParams();
+#endif
+  
 }
 
 template <class TInputValue, class TOutputValue>
@@ -134,6 +139,15 @@ LearningApplicationBase<TInputValue,TOutputValue>
     otbAppLogFATAL("Module LIBSVM is not installed. You should consider turning OTB_USE_LIBSVM on during cmake configuration.");
     #endif
     }
+  if(modelName == "sharkrf")
+    {
+    #ifdef OTB_USE_SHARK
+    TrainSharkRandomForests(trainingListSample,trainingLabeledListSample,modelPath);
+    #else
+    otbAppLogFATAL("Module SharkLearning is not installed. You should consider turning OTB_USE_SHARK on during cmake configuration.");
+    #endif
+    }
+  
   // OpenCV SVM implementation is buggy with linear kernel
   // Users should use the libSVM implementation instead.
   // else if (modelName == "svm")
@@ -200,6 +214,7 @@ LearningApplicationBase<TInputValue,TOutputValue>
     otbAppLogFATAL("Module OPENCV is not installed. You should consider turning OTB_USE_OPENCV on during cmake configuration.");
     #endif
     }
+
   // update reporter
   dummyFilter->UpdateProgress(1.0f);
   dummyFilter->InvokeEvent(itk::EndEvent());
diff --git a/Modules/Applications/AppClassification/include/otbTrainSharkRandomForests.txx b/Modules/Applications/AppClassification/include/otbTrainSharkRandomForests.txx
new file mode 100644
index 0000000000000000000000000000000000000000..c9b2d565695c708da557074076fadfcaa3a6c4cd
--- /dev/null
+++ b/Modules/Applications/AppClassification/include/otbTrainSharkRandomForests.txx
@@ -0,0 +1,98 @@
+/*=========================================================================
+ Program:   ORFEO Toolbox
+ Language:  C++
+ Date:      $Date$
+ Version:   $Revision$
+
+
+ Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+ See OTBCopyright.txt for details.
+
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE.  See the above copyright notices for more information.
+
+ =========================================================================*/
+#ifndef otbTrainSharkRandomForests_txx
+#define otbTrainSharkRandomForests_txx
+
+#include "otbLearningApplicationBase.h"
+
+namespace otb
+{
+namespace Wrapper
+{
+
+template <class TInputValue, class TOutputValue>
+void
+LearningApplicationBase<TInputValue,TOutputValue>
+::InitSharkRandomForestsParams()
+{
+
+
+  AddChoice("classifier.sharkrf", "Shark Random forests classifier");
+  SetParameterDescription("classifier.sharkrf",
+                          "This group of parameters allows setting Shark Random Forests classifier parameters. "
+                          "See complete documentation here \\url{http://image.diku.dk/shark/doxygen_pages/html/classshark_1_1_r_f_trainer.html}.\n It is noteworthy that training is parallel.");
+  //MaxNumberOfTrees
+  AddParameter(ParameterType_Int, "classifier.sharkrf.nbtrees",
+               "Maximum number of trees in the forest");
+  SetParameterInt("classifier.sharkrf.nbtrees", 100);
+  SetParameterDescription(
+    "classifier.sharkrf.nbtrees",
+    "The maximum number of trees in the forest. Typically, the more trees you have, the better the accuracy. "
+    "However, the improvement in accuracy generally diminishes and reaches an asymptote for a certain number of trees. "
+    "Also to keep in mind, increasing the number of trees increases the prediction time linearly.");
+  
+  
+  //NodeSize
+  AddParameter(ParameterType_Int, "classifier.sharkrf.nodesize", "Min size of the node for a split");
+  SetParameterInt("classifier.sharkrf.nodesize", 25);
+  SetParameterDescription(
+    "classifier.sharkrf.nodesize",
+    "If the number of samples in a node is smaller than this parameter, "
+    "then the node will not be split. A reasonable value is a small percentage of the total data e.g. 1 percent.");
+
+  //MTry
+  AddParameter(ParameterType_Int, "classifier.sharkrf.mtry", "Number of features tested at each node");
+  SetParameterInt("classifier.sharkrf.mtry", 0);
+  SetParameterDescription(
+    "classifier.sharkrf.mtry",
+    "The number of features (variables) which will be tested at each node in "
+    "order to compute the split. If set to zero, the square root of the number of "
+    "features is used.");
+
+
+  //OOB Ratio
+  AddParameter(ParameterType_Float, "classifier.sharkrf.oobr", "Out of bound ratio");
+  SetParameterFloat("classifier.sharkrf.oobr", 0.66);
+  SetParameterDescription("classifier.sharkrf.oobr", 
+                          "Set the fraction of the original training dataset to use as the out of bag sample." 
+                          "A good default value is 0.66. ");
+}
+
+template <class TInputValue, class TOutputValue>
+void
+LearningApplicationBase<TInputValue,TOutputValue>
+::TrainSharkRandomForests(typename ListSampleType::Pointer trainingListSample,
+                          typename TargetListSampleType::Pointer trainingLabeledListSample,
+                          std::string modelPath)
+{
+  typename SharkRandomForestType::Pointer classifier = SharkRandomForestType::New();
+  classifier->SetRegressionMode(this->m_RegressionFlag);
+  classifier->SetInputListSample(trainingListSample);
+  classifier->SetTargetListSample(trainingLabeledListSample);
+  classifier->SetNodeSize(GetParameterInt("classifier.sharkrf.nodesize"));
+  classifier->SetOobRatio(GetParameterFloat("classifier.sharkrf.oobr"));
+  classifier->SetNumberOfTrees(GetParameterInt("classifier.sharkrf.nbtrees"));
+  classifier->SetMTry(GetParameterInt("classifier.sharkrf.mtry"));
+
+  classifier->Train();
+  classifier->Save(modelPath);
+}
+
+} //end namespace wrapper
+} //end namespace otb
+
+#endif
diff --git a/Modules/Applications/AppClassification/test/CMakeLists.txt b/Modules/Applications/AppClassification/test/CMakeLists.txt
index 5e9109e01b0a8aa3e65c06aefe3d978889a14f7b..378a1b5fd1748de513ec67bdff38d859a63df039 100644
--- a/Modules/Applications/AppClassification/test/CMakeLists.txt
+++ b/Modules/Applications/AppClassification/test/CMakeLists.txt
@@ -75,6 +75,7 @@ set(ann_output_format ".ann")
 set(bayes_output_format ".bayes")
 set(rf_output_format ".rf")
 set(knn_output_format ".knn")
+set(sharkrf_output_format ".txt")
 
 # Training algorithms parameters
 set(libsvm_parameters "-classifier.libsvm.opt" "true" "-classifier.libsvm.prob" "true")
@@ -86,6 +87,7 @@ set(ann_parameters "-classifier.ann.sizes" "100")
 set(bayes_parameters "")
 set(rf_parameters "")
 set(knn_parameters "")
+set(sharkrf_parameters "")
 
 # Validation depending on mode
 set(ascii_comparison --compare-ascii ${NOTOL})
@@ -104,8 +106,16 @@ if(OTB_USE_OPENCV)
   #list(APPEND classifierList "SVM" "BOOST" "DT" "GBT" "ANN" "BAYES" "RF" "KNN")
   list(APPEND classifierList "BOOST" "DT" "GBT" "ANN" "BAYES" "RF" "KNN")
 endif()
+if(OTB_USE_SHARK)
+  list(APPEND classifierList "SHARKRF")
+endif()
+
 set(classifier_with_confmap "LIBSVM" "BOOST" "KNN" "ANN" "RF")
 
+# This is a black list for classifier that can not have a baseline
+# because they are using randomness and seed can not be set
+set(classifier_without_basline "SHARKRF")
+
 # Loop on classifiers
 foreach(classifier ${classifierList})
   string(TOLOWER ${classifier} lclassifier)
@@ -115,6 +125,13 @@ foreach(classifier ${classifierList})
   set(OUTRASTER cl${classifier}LabeledImageQB1${raster_output_format})
   set(OUTCONFMAP cl${classifier}ConfidenceMapQB1${raster_output_format})
 
+  set(valid ${ascii_comparison} ${ascii_ref_path}/${OUTMODELFILE} ${TEMP}/${OUTMODELFILE})
+
+  list(FIND classifier_without_basline ${classifier} _classifier_has_baseline)
+  if(NOT ${_classifier_has_baseline} EQUAL -1)
+    set(valid "")
+  endif()
+  
   otb_test_application(
                        NAME     apTvClTrainMethod${classifier}ImagesClassifierQB1
                        APP      TrainImagesClassifier
@@ -126,9 +143,7 @@ foreach(classifier ${classifierList})
                                 -io.out ${TEMP}/${OUTMODELFILE}
                                 -rand 121212
 
-                       VALID    ${ascii_comparison}
-                                ${ascii_ref_path}/${OUTMODELFILE}
-                                ${TEMP}/${OUTMODELFILE}
+                       VALID    ${valid}
                        )
 
   otb_test_application(
@@ -143,9 +158,7 @@ foreach(classifier ${classifierList})
                                 -rand 121212
                                 -outxml ${TEMP}/cl${classifier}_OutXML1.xml
 
-                       VALID    ${ascii_comparison}
-                                ${ascii_ref_path}/${OUTMODELFILE}
-                                ${TEMP}/OutXML1_${OUTMODELFILE}
+                       VALID ${valid}
                        )
 
   otb_test_application(
@@ -157,9 +170,7 @@ foreach(classifier ${classifierList})
                                 -io.imstat ${INPUTDATA}/Classification/clImageStatisticsQB1${stat_input_format}
                                 -io.out ${TEMP}/OutXML2_${OUTMODELFILE}
 
-                       VALID    ${ascii_comparison}
-                                ${ascii_ref_path}/${OUTMODELFILE}
-                                ${TEMP}/OutXML2_${OUTMODELFILE}
+                       VALID    ${valid}
                        )
 
                      #set_tests_properties(apTvClTrainMethod${classifier}ImagesClassifierQB1_InXML1 PROPERTIES DEPENDS apTvClTrainMethod${classifier}ImagesClassifierQB1_OutXML1)
@@ -900,20 +911,21 @@ if(OTB_USE_OPENCV)
 endif()
 
 #------------ MultiImageSamplingRate TESTS ----------------
-otb_test_application(NAME apTvClMultiImageSamplingRate
-                     APP MultiImageSamplingRate
-                     OPTIONS -il ${INPUTDATA}/Classification/vector_stats_QB1.xml
-                                 ${INPUTDATA}/Classification/vector_stats_QB2.xml
-                                 ${INPUTDATA}/Classification/vector_stats_QB3.xml
-                             -out ${TEMP}/apTvClMultiImageSamplingRate_out.csv
-                             -strategy constant
-                             -strategy.constant.nb "300"
-                             -mim proportional
-                     VALID   --compare-n-ascii ${NOTOL} 3
-                                ${OTBAPP_BASELINE_FILES}/apTvClMultiImageSamplingRate_out_1.csv
-                                ${TEMP}/apTvClMultiImageSamplingRate_out_1.csv
-                                ${OTBAPP_BASELINE_FILES}/apTvClMultiImageSamplingRate_out_2.csv
-                                ${TEMP}/apTvClMultiImageSamplingRate_out_2.csv
-                                ${OTBAPP_BASELINE_FILES}/apTvClMultiImageSamplingRate_out_3.csv
-                                ${TEMP}/apTvClMultiImageSamplingRate_out_3.csv
-                     )
+otb_test_application(
+  NAME apTvClMultiImageSamplingRate
+  APP MultiImageSamplingRate
+  OPTIONS -il ${INPUTDATA}/Classification/vector_stats_QB1.xml
+  ${INPUTDATA}/Classification/vector_stats_QB2.xml
+  ${INPUTDATA}/Classification/vector_stats_QB3.xml
+  -out ${TEMP}/apTvClMultiImageSamplingRate_out.csv
+  -strategy constant
+  -strategy.constant.nb "300"
+  -mim proportional
+  VALID   --compare-n-ascii ${NOTOL} 3
+  ${OTBAPP_BASELINE_FILES}/apTvClMultiImageSamplingRate_out_1.csv
+  ${TEMP}/apTvClMultiImageSamplingRate_out_1.csv
+  ${OTBAPP_BASELINE_FILES}/apTvClMultiImageSamplingRate_out_2.csv
+  ${TEMP}/apTvClMultiImageSamplingRate_out_2.csv
+  ${OTBAPP_BASELINE_FILES}/apTvClMultiImageSamplingRate_out_3.csv
+  ${TEMP}/apTvClMultiImageSamplingRate_out_3.csv
+  )
diff --git a/Modules/Applications/AppDimensionalityReduction/app/otbDimensionalityReduction.cxx b/Modules/Applications/AppDimensionalityReduction/app/otbDimensionalityReduction.cxx
index 06e07d00ad394a5f89004263db84829073823cd1..2359b00bb607bffa6255433f345a1588c952e26a 100644
--- a/Modules/Applications/AppDimensionalityReduction/app/otbDimensionalityReduction.cxx
+++ b/Modules/Applications/AppDimensionalityReduction/app/otbDimensionalityReduction.cxx
@@ -169,6 +169,8 @@ private:
     SetParameterDescription("outmatrix", "Filename to store the transformation matrix (csv format)");
     MandatoryOff("outmatrix");
 
+    AddRAMParameter();
+
     // Doc example parameter settings
     SetDocExampleParameterValue("in", "cupriteSubHsi.tif");
     SetDocExampleParameterValue("out", "FilterOutput.tif");
@@ -420,7 +422,8 @@ private:
 
       m_MinMaxFilter = MinMaxFilterType::New();
       m_MinMaxFilter->SetInput(m_ForwardFilter->GetOutput());
-      m_MinMaxFilter->GetStreamer()->SetNumberOfLinesStrippedStreaming(50);
+      //m_MinMaxFilter->GetStreamer()->SetNumberOfLinesStrippedStreaming(50);
+      m_MinMaxFilter->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram"));
 
       AddProcess(m_MinMaxFilter->GetStreamer(), "Min/Max computing");
       m_MinMaxFilter->Update();
diff --git a/Modules/Applications/AppEdge/app/otbLineSegmentDetection.cxx b/Modules/Applications/AppEdge/app/otbLineSegmentDetection.cxx
index 4212104bde1e006197b27e4863b259fb07c91baf..e1f303b86848bd238a025a91b67f0214088246ce 100644
--- a/Modules/Applications/AppEdge/app/otbLineSegmentDetection.cxx
+++ b/Modules/Applications/AppEdge/app/otbLineSegmentDetection.cxx
@@ -77,6 +77,8 @@ private:
     SetParameterDescription("norescale","By default, the input image amplitude is rescaled between [0,255]. Turn on this parameter to skip rescaling");
     MandatoryOff("norescale");
 
+    AddRAMParameter();
+
     // Doc example parameter settings
     SetDocExampleParameterValue("in", "QB_Suburb.png");
     SetDocExampleParameterValue("out", "LineSegmentDetection.shp");
@@ -117,6 +119,7 @@ private:
     if ( !IsParameterEnabled("norescale") )
       {
       stats->SetInput(amplitudeConverter->GetOutput());
+      stats->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram"));
 
       AddProcess(stats->GetStreamer(), "Image statistics");
       stats->Update();
@@ -133,6 +136,7 @@ private:
     LSDFilterType::Pointer lsd
       = LSDFilterType::New();
     lsd->GetFilter()->SetInput(image);
+    lsd->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram"));
 
     AddProcess(lsd->GetStreamer(), "Running Line Segment Detector");
     lsd->Update();
diff --git a/Modules/Applications/AppHyperspectral/app/otbHyperspectralUnmixing.cxx b/Modules/Applications/AppHyperspectral/app/otbHyperspectralUnmixing.cxx
index 3894ed1484558ebe1df7314b0294b6f6f91889f0..50c8c11dcaa5b2ccf27a0d123d2db9dcb0b3c08f 100644
--- a/Modules/Applications/AppHyperspectral/app/otbHyperspectralUnmixing.cxx
+++ b/Modules/Applications/AppHyperspectral/app/otbHyperspectralUnmixing.cxx
@@ -18,7 +18,6 @@
 #include "otbWrapperApplication.h"
 #include "otbWrapperApplicationFactory.h"
 
-#include "otbStreamingStatisticsVectorImageFilter.h"
 #include "otbUnConstrainedLeastSquareImageFilter.h"
 #include "otbISRAUnmixingImageFilter.h"
 #include "otbNCLSUnmixingImageFilter.h"
@@ -30,9 +29,6 @@ namespace otb
 {
 namespace Wrapper
 {
-
-typedef otb::StreamingStatisticsVectorImageFilter<DoubleVectorImageType> StreamingStatisticsVectorImageFilterType;
-
 typedef otb::UnConstrainedLeastSquareImageFilter<DoubleVectorImageType, DoubleVectorImageType, double> UCLSUnmixingFilterType;
 typedef otb::ISRAUnmixingImageFilter<DoubleVectorImageType, DoubleVectorImageType, double>             ISRAUnmixingFilterType;
 typedef otb::NCLSUnmixingImageFilter<DoubleVectorImageType, DoubleVectorImageType, double>             NCLSUnmixingFilterType;
diff --git a/Modules/Applications/AppImageUtils/app/otbColorMapping.cxx b/Modules/Applications/AppImageUtils/app/otbColorMapping.cxx
index 72945f38f32cf933c517ae3b372f0faf2dd978d6..d4968e35a4a331bb78ef6d169c39617bb91ca0ef 100644
--- a/Modules/Applications/AppImageUtils/app/otbColorMapping.cxx
+++ b/Modules/Applications/AppImageUtils/app/otbColorMapping.cxx
@@ -293,8 +293,6 @@ private:
     SetParameterDescription("out","Output image filename");
     SetDefaultOutputPixelType("out",ImagePixelType_uint8);
 
-    AddRAMParameter();
-
     // --- OPERATION --- : Label to color / Color to label
     AddParameter(ParameterType_Choice, "op", "Operation");
     SetParameterDescription("op","Selection of the operation to execute (default is : label to color).");
@@ -384,6 +382,7 @@ private:
     SetMinimumParameterIntValue("method.image.up", 0);
     SetMaximumParameterIntValue("method.image.up", 100);
 
+    AddRAMParameter();
 
     // Doc example parameter settings
     SetDocExampleParameterValue("in", "ROI_QB_MUL_1_SVN_CLASS_MULTI.png");
@@ -611,6 +610,8 @@ private:
       m_StatisticsMapFromLabelImageFilter = StreamingStatisticsMapFromLabelImageFilterType::New();
       m_StatisticsMapFromLabelImageFilter->SetInput(GetParameterImage("method.image.in"));
       m_StatisticsMapFromLabelImageFilter->SetInputLabelImage(m_CasterToLabelImage->GetOutput());
+      m_StatisticsMapFromLabelImageFilter->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram"));
+      AddProcess(m_StatisticsMapFromLabelImageFilter->GetStreamer(), "Computing statistics on labels...");
       m_StatisticsMapFromLabelImageFilter->Update();
 
       StreamingStatisticsMapFromLabelImageFilterType::MeanValueMapType
diff --git a/Modules/Applications/AppImageUtils/app/otbCompareImages.cxx b/Modules/Applications/AppImageUtils/app/otbCompareImages.cxx
index 9aebb220747a1d0affed52b8ec4ca568a3814f41..f08ac34ae20f07aa8847b34de459cf277746e158 100644
--- a/Modules/Applications/AppImageUtils/app/otbCompareImages.cxx
+++ b/Modules/Applications/AppImageUtils/app/otbCompareImages.cxx
@@ -114,6 +114,8 @@ private:
     SetParameterDescription("count", "Nb of pixels which are different");
     SetParameterRole("count", Role_Output);
 
+    AddRAMParameter();
+
     // Doc example parameter settings
     SetDocExampleParameterValue("ref.in", "GomaApres.png");
     SetDocExampleParameterValue("ref.channel", "1");
@@ -206,6 +208,8 @@ private:
     m_CompareFilter->SetInput1(m_ExtractRefFilter->GetOutput());
     m_CompareFilter->SetInput2(m_ExtractMeasFilter->GetOutput());
     m_CompareFilter->SetPhysicalSpaceCheck(false);
+    m_CompareFilter->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram"));
+    AddProcess(m_CompareFilter->GetStreamer(), "Comparing...");
     m_CompareFilter->Update();
 
     // Show result
diff --git a/Modules/Applications/AppImageUtils/app/otbConvert.cxx b/Modules/Applications/AppImageUtils/app/otbConvert.cxx
index 7de721d7863d62698879a16c4800a58b436cb0db..7f7d5651dc67b13dba29bed9d68bb99379c7e35a 100644
--- a/Modules/Applications/AppImageUtils/app/otbConvert.cxx
+++ b/Modules/Applications/AppImageUtils/app/otbConvert.cxx
@@ -199,6 +199,7 @@ private:
       otbAppLogDEBUG( << "Shrink starts..." );
 
       shrinkFilter->SetShrinkFactor(shrinkFactor);
+      shrinkFilter->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram"));
       AddProcess(shrinkFilter->GetStreamer(), "Computing shrink Image for min/max estimation...");
 
       if ( rescaleType == "log2")
@@ -210,14 +211,12 @@ private:
 
         shrinkFilter->SetInput(m_TransferLog->GetOutput());
         rescaler->SetInput(m_TransferLog->GetOutput());
-        shrinkFilter->GetStreamer()->SetAutomaticTiledStreaming(GetParameterInt("ram"));
         shrinkFilter->Update();
         }
       else
         {
         shrinkFilter->SetInput(input);
         rescaler->SetInput(input);
-        shrinkFilter->GetStreamer()->SetAutomaticTiledStreaming(GetParameterInt("ram"));
         shrinkFilter->Update();
         }
 
@@ -226,7 +225,7 @@ private:
         {
         maskShrinkFilter->SetShrinkFactor(shrinkFactor);
         maskShrinkFilter->SetInput(mask);
-        maskShrinkFilter->GetStreamer()->SetAutomaticTiledStreaming(GetParameterInt("ram"));
+        maskShrinkFilter->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram"));
         maskShrinkFilter->Update();
         }
 
diff --git a/Modules/Applications/AppImageUtils/app/otbRescale.cxx b/Modules/Applications/AppImageUtils/app/otbRescale.cxx
index d0304e74a465fcad7c70add4e02a67c89f5d54fa..ea109547cf8cba64d6e9775436ad18aafeb4d6f3 100644
--- a/Modules/Applications/AppImageUtils/app/otbRescale.cxx
+++ b/Modules/Applications/AppImageUtils/app/otbRescale.cxx
@@ -97,7 +97,7 @@ private:
 
     m_MinMaxFilter = MinMaxFilterType::New();
     m_MinMaxFilter->SetInput( inImage );
-    m_MinMaxFilter->GetStreamer()->SetNumberOfLinesStrippedStreaming( 50 );
+    m_MinMaxFilter->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram"));
 
     AddProcess(m_MinMaxFilter->GetStreamer(), "Min/Max computing");
     m_MinMaxFilter->Update();
diff --git a/Modules/Applications/AppSegmentation/app/otbConnectedComponentSegmentation.cxx b/Modules/Applications/AppSegmentation/app/otbConnectedComponentSegmentation.cxx
index 8f014d3ecd7f8e2407c9ddfef7eef7c5535b7c28..1c4e3073a7657abcd6bc73e0f45fc773d845308d 100644
--- a/Modules/Applications/AppSegmentation/app/otbConnectedComponentSegmentation.cxx
+++ b/Modules/Applications/AppSegmentation/app/otbConnectedComponentSegmentation.cxx
@@ -108,6 +108,8 @@ private:
     // Elevation
     ElevationParametersHandler::AddElevationParameters(this, "elev");
 
+    AddRAMParameter();
+
    // Doc example parameter settings
    SetDocExampleParameterValue("in", "ROI_QB_MUL_4.tif");
    SetDocExampleParameterValue("mask", "\"((b1>80)*intensity>95)\"");
@@ -139,7 +141,8 @@ private:
     if (IsParameterEnabled("obia") && HasValue("obia"))
       m_Connected->GetFilter()->SetOBIAExpression(GetParameterString("obia"));
 
-    AddProcess(m_Connected,"Computing segmentation");
+    m_Connected->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram"));
+    AddProcess(m_Connected->GetStreamer(),"Computing segmentation");
     m_Connected->Update();
 
     /*
diff --git a/Modules/Applications/AppSegmentation/app/otbLSMSSmallRegionsMerging.cxx b/Modules/Applications/AppSegmentation/app/otbLSMSSmallRegionsMerging.cxx
index 23f33978594b6c16e37190d2e30f9b3bed16ae20..5adea92933da93767bde59b94d11a5bcd955d694 100644
--- a/Modules/Applications/AppSegmentation/app/otbLSMSSmallRegionsMerging.cxx
+++ b/Modules/Applications/AppSegmentation/app/otbLSMSSmallRegionsMerging.cxx
@@ -108,6 +108,8 @@ private:
     SetDefaultParameterInt("tilesizey", 500);
     SetMinimumParameterIntValue("tilesizey", 1);
 
+    AddRAMParameter();
+
     // Doc example parameter settings
     SetDocExampleParameterValue("in","smooth.tif");
     SetDocExampleParameterValue("inseg","segmentation.tif");
@@ -142,6 +144,8 @@ private:
 
     StatisticsImageFilterType::Pointer stats = StatisticsImageFilterType::New();
     stats->SetInput(labelIn);
+    stats->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram"));
+    AddProcess(stats->GetStreamer(), "Retrieve region count...");
     stats->Update();
     unsigned int regionCount=stats->GetMaximum();
 
diff --git a/Modules/Applications/AppSegmentation/app/otbLSMSVectorization.cxx b/Modules/Applications/AppSegmentation/app/otbLSMSVectorization.cxx
index 9a0c070e995925392b067ed4d42508694f0b2151..9238a008f50a8854024946dbb50933b38823dcb3 100644
--- a/Modules/Applications/AppSegmentation/app/otbLSMSVectorization.cxx
+++ b/Modules/Applications/AppSegmentation/app/otbLSMSVectorization.cxx
@@ -94,6 +94,8 @@ private:
     SetDefaultParameterInt("tilesizey", 500);
     SetMinimumParameterIntValue("tilesizey", 1);
 
+    AddRAMParameter();
+
     // Doc example parameter settings
     SetDocExampleParameterValue("in","avions.tif");
     SetDocExampleParameterValue("inseg","merged.tif");
@@ -129,6 +131,8 @@ private:
 
     StatisticsImageFilterType::Pointer stats = StatisticsImageFilterType::New();
     stats->SetInput(labelIn);
+    stats->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram"));
+    AddProcess(stats->GetStreamer(), "Retrieve region count...");
     stats->Update();
     unsigned int regionCount=stats->GetMaximum();
 
diff --git a/Modules/Applications/AppStereo/app/otbStereoFramework.cxx b/Modules/Applications/AppStereo/app/otbStereoFramework.cxx
index 24c60f8d28c8c4faeb6f2da2e5e2baf15abb5931..1b18dc5b89b6cece6460f3c72f7774f239cc873b 100644
--- a/Modules/Applications/AppStereo/app/otbStereoFramework.cxx
+++ b/Modules/Applications/AppStereo/app/otbStereoFramework.cxx
@@ -39,7 +39,6 @@
 
 #include "itkRescaleIntensityImageFilter.h"
 #include "otbStreamingMinMaxImageFilter.h"
-#include "otbStreamingStatisticsImageFilter.h"
 #include "otbExtractROI.h"
 #include "otbImageFileReader.h"
 #include "otbImageFileWriter.h"
@@ -183,9 +182,6 @@ public:
   typedef otb::StreamingMinMaxImageFilter
     <FloatImageType>                          MinMaxFilterType;
 
-  typedef otb::StreamingStatisticsImageFilter
-    <FloatImageType>                          StatisticsFilterType;
-
   typedef otb::ExtractROI
     <FloatPixelType,FloatPixelType>           ExtractFilterType;
 
diff --git a/Modules/Applications/AppStereo/app/otbStereoRectificationGridGenerator.cxx b/Modules/Applications/AppStereo/app/otbStereoRectificationGridGenerator.cxx
index a6f746a992a92f67447d5361345967fa720aa611..b9f6b1fdb4a0fbaf0acd6bbed9e7952155eec52b 100644
--- a/Modules/Applications/AppStereo/app/otbStereoRectificationGridGenerator.cxx
+++ b/Modules/Applications/AppStereo/app/otbStereoRectificationGridGenerator.cxx
@@ -239,7 +239,8 @@ private:
       m_DEMToImageGenerator->AboveEllipsoidOn();
 
       m_StatisticsFilter->SetInput(m_DEMToImageGenerator->GetOutput());
-      AddProcess(m_StatisticsFilter,"Computing DEM statistics ...");
+      m_StatisticsFilter->GetStreamer()->SetAutomaticAdaptativeStreaming(GetParameterInt("ram"));
+      AddProcess(m_StatisticsFilter->GetStreamer(),"Computing DEM statistics ...");
       m_StatisticsFilter->Update();
 
       otb::DEMHandler::Instance()->SetDefaultHeightAboveEllipsoid(m_StatisticsFilter->GetMean());
diff --git a/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.h b/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.h
index ba95eeaa148f39d7c3beccd505529b6d9daaf964..d09e21962c26b242c2c8bb3de2648eafadb9c4db 100644
--- a/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.h
+++ b/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.h
@@ -94,8 +94,6 @@ public:
 
   /** Train the machine learning model */
   void Train() ITK_OVERRIDE;
-  /** Predict values using the model */
-  TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality=NULL) const ITK_OVERRIDE;
 
   /** Save the model to file */
   void Save(const std::string & filename, const std::string & name="") ITK_OVERRIDE;
@@ -119,6 +117,10 @@ protected:
   /** Destructor */
   ~BoostMachineLearningModel() ITK_OVERRIDE;
 
+  /** Predict values using the model */
+  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=ITK_NULLPTR) const ITK_OVERRIDE;
+
+  
   /** PrintSelf method */
   void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE;
 
diff --git a/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.txx b/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.txx
index 8d20ca5f7f5d16068ed2b136e6e53791d59c71d8..5f7745a37aa95c2207d28426e3ec4b250f35ff42 100644
--- a/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.txx
+++ b/Modules/Learning/Supervised/include/otbBoostMachineLearningModel.txx
@@ -77,7 +77,7 @@ template <class TInputValue, class TOutputValue>
 typename BoostMachineLearningModel<TInputValue,TOutputValue>
 ::TargetSampleType
 BoostMachineLearningModel<TInputValue,TOutputValue>
-::Predict(const InputSampleType & input, ConfidenceValueType *quality) const
+::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const
 {
   //convert listsample to Mat
   cv::Mat sample;
diff --git a/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.h b/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.h
index 571bbd597a2c21a821ccd6a8d403a38718814c8f..a34417e810dba03423e85bcb853cf57d1aef741a 100644
--- a/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.h
+++ b/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.h
@@ -149,8 +149,6 @@ public:
 
   /** Train the machine learning model */
   void Train() ITK_OVERRIDE;
-  /** Predict values using the model */
-  TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality=NULL) const ITK_OVERRIDE;
 
   /** Save the model to file */
   void Save(const std::string & filename, const std::string & name="") ITK_OVERRIDE;
@@ -174,6 +172,9 @@ protected:
   /** Destructor */
   ~DecisionTreeMachineLearningModel() ITK_OVERRIDE;
 
+  /** Predict values using the model */
+  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=ITK_NULLPTR) const ITK_OVERRIDE;
+
   /** PrintSelf method */
   void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE;
 
diff --git a/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.txx b/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.txx
index 07ce3a1129c93a9225e9dae06b4c208779a6093b..ebcc7bfbef5a60d34bbd96c1eefb9c12c90fb0a4 100644
--- a/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.txx
+++ b/Modules/Learning/Supervised/include/otbDecisionTreeMachineLearningModel.txx
@@ -83,7 +83,7 @@ template <class TInputValue, class TOutputValue>
 typename DecisionTreeMachineLearningModel<TInputValue,TOutputValue>
 ::TargetSampleType
 DecisionTreeMachineLearningModel<TInputValue,TOutputValue>
-::Predict(const InputSampleType & input, ConfidenceValueType *quality) const
+::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const
 {
   //convert listsample to Mat
   cv::Mat sample;
diff --git a/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.h b/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.h
index 4221da6df8b58ba195c75347507665df8bd845f8..92f9e04781fcd19805b181954e9a7c8292e11d14 100644
--- a/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.h
+++ b/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.h
@@ -102,8 +102,6 @@ public:
 
   /** Train the machine learning model */
   void Train() ITK_OVERRIDE;
-  /** Predict values using the model */
-  TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality=NULL) const ITK_OVERRIDE;
 
   /** Save the model to file */
   void Save(const std::string & filename, const std::string & name="") ITK_OVERRIDE;
@@ -127,6 +125,10 @@ protected:
   /** Destructor */
   ~GradientBoostedTreeMachineLearningModel() ITK_OVERRIDE;
 
+    /** Predict values using the model */
+  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=ITK_NULLPTR) const ITK_OVERRIDE;
+
+  
   /** PrintSelf method */
   void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE;
 
diff --git a/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.txx b/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.txx
index 53e6931575e6f134115a21d5587fa7a006a8f173..3ab84acbf58f4ff3ad2c22e1d8f4502a0feb48b8 100644
--- a/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.txx
+++ b/Modules/Learning/Supervised/include/otbGradientBoostedTreeMachineLearningModel.txx
@@ -79,7 +79,7 @@ template <class TInputValue, class TOutputValue>
 typename GradientBoostedTreeMachineLearningModel<TInputValue,TOutputValue>
 ::TargetSampleType
 GradientBoostedTreeMachineLearningModel<TInputValue,TOutputValue>
-::Predict(const InputSampleType & input, ConfidenceValueType *quality) const
+::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const
 {
   //convert listsample to Mat
   cv::Mat sample;
diff --git a/Modules/Learning/Supervised/include/otbImageClassificationFilter.h b/Modules/Learning/Supervised/include/otbImageClassificationFilter.h
index e8ee652f0fccb863fe6ce9c819f86fd6e8bcdc5e..7d4cf8a9766bf21e8cc1a7c2e77c16150720b218 100644
--- a/Modules/Learning/Supervised/include/otbImageClassificationFilter.h
+++ b/Modules/Learning/Supervised/include/otbImageClassificationFilter.h
@@ -67,7 +67,7 @@ public:
   typedef typename OutputImageType::PixelType  LabelType;
 
   typedef MachineLearningModel<ValueType, LabelType> ModelType;
-  typedef typename ModelType::Pointer    ModelPointerType;
+  typedef typename ModelType::Pointer                ModelPointerType;
 
   typedef otb::Image<double>                    ConfidenceImageType;
   typedef typename ConfidenceImageType::Pointer ConfidenceImagePointerType;
@@ -84,6 +84,10 @@ public:
   itkSetMacro(UseConfidenceMap, bool);
   itkGetMacro(UseConfidenceMap, bool);
 
+  itkSetMacro(BatchMode, bool);
+  itkGetMacro(BatchMode, bool);
+  itkBooleanMacro(BatchMode);
+  
   /**
    * If set, only pixels within the mask will be classified.
    * All pixels with a value greater than 0 in the mask, will be classified.
@@ -110,6 +114,8 @@ protected:
 
   /** Threaded generate data */
   void ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId) ITK_OVERRIDE;
+  void ClassicThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId);
+  void BatchThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId);
   /** Before threaded generate data */
   void BeforeThreadedGenerateData() ITK_OVERRIDE;
   /**PrintSelf method */
@@ -125,6 +131,7 @@ private:
   LabelType m_DefaultLabel;
   /** Flag to produce the confidence map (if the model supports it) */
   bool m_UseConfidenceMap;
+  bool m_BatchMode;
 };
 } // End namespace otb
 #ifndef OTB_MANUAL_INSTANTIATION
diff --git a/Modules/Learning/Supervised/include/otbImageClassificationFilter.txx b/Modules/Learning/Supervised/include/otbImageClassificationFilter.txx
index 72614862a991acc87bd75ed14ff4e6d3fdc103cb..899a5a25066ddb9d0d77a8dd5d687f1bcfc5caa8 100644
--- a/Modules/Learning/Supervised/include/otbImageClassificationFilter.txx
+++ b/Modules/Learning/Supervised/include/otbImageClassificationFilter.txx
@@ -39,6 +39,7 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
   this->SetNthOutput(0,TOutputImage::New());
   this->SetNthOutput(1,ConfidenceImageType::New());
   m_UseConfidenceMap = false;
+  m_BatchMode = true;
 }
 
 template <class TInputImage, class TOutputImage, class TMaskImage>
@@ -84,12 +85,19 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
     {
     itkGenericExceptionMacro(<< "No model for classification");
     }
+  if(m_BatchMode)
+    {
+    #ifdef _OPENMP
+    // OpenMP will take care of threading
+    this->SetNumberOfThreads(1);
+    #endif
+    }
 }
 
 template <class TInputImage, class TOutputImage, class TMaskImage>
 void
 ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
-::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId)
+::ClassicThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId)
 {
   // Get the input pointers
   InputImageConstPointerType inputPtr     = this->GetInput();
@@ -165,6 +173,140 @@ ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
     progress.CompletedPixel();
     }
 
+}
+
+template <class TInputImage, class TOutputImage, class TMaskImage>
+void
+ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
+::BatchThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId)
+{
+  bool computeConfidenceMap(m_UseConfidenceMap && m_Model->HasConfidenceIndex() 
+                            && !m_Model->GetRegressionMode());
+  // Get the input pointers
+  InputImageConstPointerType inputPtr     = this->GetInput();
+  MaskImageConstPointerType  inputMaskPtr  = this->GetInputMask();
+  OutputImagePointerType     outputPtr    = this->GetOutput();
+  ConfidenceImagePointerType confidencePtr = this->GetOutputConfidence();
+    
+  // Progress reporting
+  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;
+
+  InputIteratorType inIt(inputPtr, outputRegionForThread);
+  OutputIteratorType outIt(outputPtr, outputRegionForThread);
+
+  MaskIteratorType maskIt;
+  if (inputMaskPtr)
+    {
+    maskIt = MaskIteratorType(inputMaskPtr, outputRegionForThread);
+    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;
+
+  typename InputListSampleType::Pointer samples = InputListSampleType::New();
+  unsigned int num_features = inputPtr->GetNumberOfComponentsPerPixel();
+  samples->SetMeasurementVectorSize(num_features);
+  InputSampleType sample(num_features);
+  // Fill the samples
+  bool validPoint = true;
+  for (inIt.GoToBegin(); !inIt.IsAtEnd(); ++inIt)
+    {
+    // Check pixel validity
+    if (inputMaskPtr)
+      {
+      validPoint = maskIt.Get() > 0;
+      ++maskIt;
+      }
+    if(validPoint)
+      {
+      typename InputImageType::PixelType pix = inIt.Get();
+      for(size_t feat=0; feat<num_features; ++feat)
+        {
+        sample[feat]=pix[feat];
+        }
+      samples->PushBack(sample);
+      }
+    }
+  //Make the batch prediction
+  typename TargetListSampleType::Pointer labels;
+  typename ConfidenceListSampleType::Pointer confidences;
+  if(computeConfidenceMap)
+    confidences = ConfidenceListSampleType::New();
+
+  // This call is threadsafe
+  labels = m_Model->PredictBatch(samples,confidences);
+
+  // Set the output values
+  ConfidenceMapIteratorType confidenceIt;
+  if (computeConfidenceMap)
+    {
+    confidenceIt = ConfidenceMapIteratorType(confidencePtr,outputRegionForThread);
+    confidenceIt.GoToBegin();
+    }
+
+  typename TargetListSampleType::ConstIterator labIt = labels->Begin();
+  maskIt.GoToBegin();
+  for (outIt.GoToBegin(); labIt!=labels->End() && !outIt.IsAtEnd(); 
+       ++outIt)
+    {
+    double confidenceIndex = 0.0;
+    TargetValueType labelValue(m_DefaultLabel);
+    if (inputMaskPtr)
+      {
+      validPoint = maskIt.Get() > 0;
+      ++maskIt;
+      }
+    if (validPoint)
+      {
+      labelValue = labIt.GetMeasurementVector()[0];
+
+       if(computeConfidenceMap)
+        {
+        confidenceIndex = confidences->GetMeasurementVector(labIt.GetInstanceIdentifier())[0];
+        }
+       
+      ++labIt;    
+      }
+    
+    outIt.Set(labelValue);
+
+    if(computeConfidenceMap)
+      {
+      confidenceIt.Set(confidenceIndex);
+      ++confidenceIt;
+      }
+    
+    progress.CompletedPixel();
+    }
+}
+template <class TInputImage, class TOutputImage, class TMaskImage>
+void
+ImageClassificationFilter<TInputImage, TOutputImage, TMaskImage>
+::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread, itk::ThreadIdType threadId)
+{
+  if(m_BatchMode)
+    {
+    this->BatchThreadedGenerateData(outputRegionForThread, threadId);
+    }
+  else
+    {
+    this->ClassicThreadedGenerateData(outputRegionForThread, threadId);
+    }
+
 }
 /**
  * PrintSelf Method
diff --git a/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.h b/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.h
index 2954ba4ffd9fa161563cc7facddd183eca483da4..857fa37efc6c3c6411d57d8e35e1a1776b923e04 100644
--- a/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.h
+++ b/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.h
@@ -73,8 +73,6 @@ public:
 
   /** Train the machine learning model */
   void Train() ITK_OVERRIDE;
-  /** Predict values using the model */
-  TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality=NULL) const ITK_OVERRIDE;
 
   /** Save the model to file */
   void Save(const std::string & filename, const std::string & name="") ITK_OVERRIDE;
@@ -98,6 +96,10 @@ protected:
   /** Destructor */
   ~KNearestNeighborsMachineLearningModel() ITK_OVERRIDE;
 
+  /** Predict values using the model */
+  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=ITK_NULLPTR) const ITK_OVERRIDE;
+
+  
   /** PrintSelf method */
   void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE;
 
diff --git a/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.txx b/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.txx
index 2a6705d1aa1aa5093d50201fe06731318f97ce38..040a0ea7ba8ee834267beeb53598c225a0732822 100644
--- a/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.txx
+++ b/Modules/Learning/Supervised/include/otbKNearestNeighborsMachineLearningModel.txx
@@ -85,7 +85,7 @@ template <class TInputValue, class TTargetValue>
 typename KNearestNeighborsMachineLearningModel<TInputValue,TTargetValue>
 ::TargetSampleType
 KNearestNeighborsMachineLearningModel<TInputValue,TTargetValue>
-::Predict(const InputSampleType & input, ConfidenceValueType *quality) const
+::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const
 {
   //convert listsample to Mat
   cv::Mat sample;
diff --git a/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.h b/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.h
index b398f7d640a1f3c0add82222a56e31baeabb0fac..2fb03297052bf8a2cf7015dea7b8cba04b80e159 100644
--- a/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.h
+++ b/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.h
@@ -61,8 +61,6 @@ public:
 
   /** Train the machine learning model */
   void Train() ITK_OVERRIDE;
-  /** Predict values using the model */
-  TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality=NULL) const ITK_OVERRIDE;
 
   /** Save the model to file */
   void Save(const std::string &filename, const std::string & name="") ITK_OVERRIDE;
@@ -122,6 +120,9 @@ protected:
   /** Destructor */
   ~LibSVMMachineLearningModel() ITK_OVERRIDE;
 
+  /** Predict values using the model */
+  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=ITK_NULLPTR) const ITK_OVERRIDE;
+
   /** PrintSelf method */
   void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE;
 
diff --git a/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.txx b/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.txx
index 70da67ed4ef9dea8dd124f0b6e5844f9545bcf13..bc35ad660e246796ffafe7df541fa2bd4c7cae86 100644
--- a/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.txx
+++ b/Modules/Learning/Supervised/include/otbLibSVMMachineLearningModel.txx
@@ -71,7 +71,7 @@ template <class TInputValue, class TOutputValue>
 typename LibSVMMachineLearningModel<TInputValue,TOutputValue>
 ::TargetSampleType
 LibSVMMachineLearningModel<TInputValue,TOutputValue>
-::Predict(const InputSampleType & input, ConfidenceValueType *quality) const
+::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const
 {
   TargetSampleType target;
 
diff --git a/Modules/Learning/Supervised/include/otbMachineLearningModel.h b/Modules/Learning/Supervised/include/otbMachineLearningModel.h
index 3bc693cbc459fa35cb39821fe19ceed663b210ec..2cf4850182d5b8d6f34f84695a8390e2bd153cb4 100644
--- a/Modules/Learning/Supervised/include/otbMachineLearningModel.h
+++ b/Modules/Learning/Supervised/include/otbMachineLearningModel.h
@@ -34,7 +34,8 @@ namespace otb
  * Neural Network, ...) in the generic supervised classification framework of the OTB.
  * The main generic virtual methods specifically implemented in each classifier
  * derived from the MachineLearningModel class are two learning-related methods:
- * Train() and Save(), and two classification-related methods: Load() and Predict().
+ * Train() and Save(), and three classification-related methods: Load(),
+ * DoPredict() and optionnaly DoPredictBatch().
  *
  * Thus, each classifier derived from the MachineLearningModel class
  * computes its corresponding model with Train() and exports it with
@@ -55,6 +56,7 @@ namespace otb
  * \sa GradientBoostedTreeMachineLearningModel
  * \sa NormalBayesMachineLearningModel
  * \sa NeuralNetworkMachineLearningModel
+ * \sa SharkRandomForestsMachineLearningModel
  * \sa ImageClassificationFilter
  *
  *
@@ -89,6 +91,8 @@ public:
 
   /**\name Confidence value typedef */
   typedef TConfidenceValue                              ConfidenceValueType;
+  typedef itk::FixedArray<ConfidenceValueType,1>            ConfidenceSampleType;
+  typedef itk::Statistics::ListSample<ConfidenceSampleType> ConfidenceListSampleType;
 
   /**\name Standard macros */
   //@{
@@ -99,10 +103,27 @@ public:
   /** Train the machine learning model */
   virtual void Train() =0;
 
-  /** Predict values using the model */
-  virtual TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality = ITK_NULLPTR) const = 0;
-
-  /** Classify all samples in InputListSample and fill TargetListSample with the associated label */
+  /** Predict a single sample
+    * \param input The sample
+    * \param quality A pointer to the quality variable were to store
+    * quality value, or NULL
+    * \return The predicted label
+     */
+  TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality = ITK_NULLPTR) const;
+
+
+
+  /** Predict a batch of samples (InputListSampleType)
+    * \param input The batch of sample to predict
+    * \param quality A pointer to the list were to store
+    * quality value, or NULL
+    * \return The predicted labels
+    * Note that this method will be multi-threaded if OTB is built
+    * with OpenMP.
+     */
+  typename TargetListSampleType::Pointer PredictBatch(const InputListSampleType * input, ConfidenceListSampleType * quality = ITK_NULLPTR) const;
+  
+  /** THIS METHOD IS DEPRECATED AND SHOULD NOT BE USED. */
   void PredictAll();
 
   /**\name Classification model file manipulation */
@@ -130,6 +151,7 @@ public:
   //@{
   itkSetObjectMacro(InputListSample,InputListSampleType);
   itkGetObjectMacro(InputListSample,InputListSampleType);
+  itkGetConstObjectMacro(InputListSample,InputListSampleType);
   //@}
 
   /**\name Classification output accessors */
@@ -140,6 +162,8 @@ public:
   itkGetObjectMacro(TargetListSample,TargetListSampleType);
   //@}
 
+  itkGetObjectMacro(ConfidenceListSample,ConfidenceListSampleType);
+  
   /**\name Use model in regression mode */
   //@{
   itkGetMacro(RegressionMode,bool);
@@ -152,7 +176,7 @@ protected:
 
   /** Destructor */
   ~MachineLearningModel() ITK_OVERRIDE;
-
+ 
   /** PrintSelf method */
   void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE;
 
@@ -162,6 +186,8 @@ protected:
   /** Target list sample */
   typename TargetListSampleType::Pointer m_TargetListSample;
 
+  typename ConfidenceListSampleType::Pointer m_ConfidenceListSample;
+  
   /** flag to choose between classification and regression modes */
   bool m_RegressionMode;
   
@@ -172,7 +198,36 @@ protected:
 
   /** flag that tells if the model support confidence index output */
   bool m_ConfidenceIndex;
+
+  /** Is DoPredictBatch multi-threaded ? */
+  bool m_IsDoPredictBatchMultiThreaded;
+
 private:
+  /**  Actual implementation of BatchPredicition
+    *  Default implementation will call DoPredict iteratively 
+    *  \param input The input batch
+    *  \param startIndex Index of the first sample to predict
+    *  \param size Number of samples to predict
+    *  \param target Pointer to the list of produced labels
+    *  \param quality Pointer to the list of produced confidence
+    *  values, or NULL
+    * 
+    * Override me if internal implementation allows for batch
+    * prediction.
+    * 
+    * 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 = ITK_NULLPTR) const;
+
+  /** Actual implementation of single sample prediction
+   *  \param input sample to predict
+   *  \param quality Pointer to a variable to store confidence value,
+   *  or NULL
+   *  \return The predicted label
+   */ 
+  virtual TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType * quality= ITK_NULLPTR) const = 0;  
+ 
   MachineLearningModel(const Self &); //purposely not implemented
   void operator =(const Self&); //purposely not implemented
 };
diff --git a/Modules/Learning/Supervised/include/otbMachineLearningModel.txx b/Modules/Learning/Supervised/include/otbMachineLearningModel.txx
index c3954072ccda0e90733f6299db5767540983475f..3d67a0a3a2a68000a60225d9b822a25157277f14 100644
--- a/Modules/Learning/Supervised/include/otbMachineLearningModel.txx
+++ b/Modules/Learning/Supervised/include/otbMachineLearningModel.txx
@@ -18,8 +18,14 @@
 #ifndef otbMachineLearningModel_txx
 #define otbMachineLearningModel_txx
 
+#ifdef _OPENMP
+ # include <omp.h>
+#endif
+
 #include "otbMachineLearningModel.h"
 
+#include "itkMultiThreader.h"
+
 namespace otb
 {
 
@@ -28,7 +34,8 @@ MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue>
 ::MachineLearningModel() :
   m_RegressionMode(false),
   m_IsRegressionSupported(false),
-  m_ConfidenceIndex(false)
+  m_ConfidenceIndex(false),
+  m_IsDoPredictBatchMultiThreaded(false)
 {}
 
 
@@ -58,13 +65,117 @@ void
 MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue>
 ::PredictAll()
 {
-  TargetListSampleType * targets = this->GetTargetListSample();
+  itkWarningMacro("MachineLearningModel::PredictAll() has been DEPRECATED. Use MachineLearningModel::PredictBatch() instead.");
+  
+  typename TargetListSampleType::Pointer targets = this->GetTargetListSample();
   targets->Clear();
+  
+  typename TargetListSampleType::Pointer tmpTargets = this->PredictBatch(this->GetInputListSample());
+  
+  targets->Graft(tmpTargets);
+}
+
+template <class TInputValue, class TOutputValue, class TConfidenceValue>
+typename MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue>
+::TargetSampleType
+MachineLearningModel<TInputValue,TOutputValue,TConfidenceValue>
+::Predict(const InputSampleType& input, ConfidenceValueType *quality) const
+{
+  // Call protected specialization entry point
+  return this->DoPredict(input,quality);
+}
 
-  for(typename InputListSampleType::ConstIterator sIt = this->GetInputListSample()->Begin();
-      sIt!=this->GetInputListSample()->End(); ++sIt)
+
+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
+{
+  typename TargetListSampleType::Pointer targets = TargetListSampleType::New();
+  targets->Resize(input->Size());
+  
+  if(quality!=ITK_NULLPTR)
+    {
+    quality->Clear();
+    quality->Resize(input->Size());
+    }
+  
+  if(m_IsDoPredictBatchMultiThreaded)
+    {
+    // Simply calls DoPredictBatch
+    this->DoPredictBatch(input,0,input->Size(),targets,quality);
+    return targets;
+    }
+  else
+    {
+    
+    #ifdef _OPENMP
+    // OpenMP threading here
+    unsigned int nb_threads(0), threadId(0), nb_batches(0);
+    
+    #pragma omp parallel shared(nb_threads,nb_batches) private(threadId)
+    {
+    // Get number of threads configured with ITK
+    omp_set_num_threads(itk::MultiThreader::GetGlobalDefaultNumberOfThreads());
+    nb_threads = omp_get_num_threads();
+    threadId = omp_get_thread_num();
+    nb_batches = std::min(nb_threads,(unsigned int)input->Size());
+    // Ensure that we do not spawn unncessary threads
+    if(threadId<nb_batches)
+      {
+      unsigned int batch_size = ((unsigned int)input->Size()/nb_batches);
+      unsigned int batch_start = threadId*batch_size;
+      if(threadId == nb_threads-1)
+        {
+        batch_size+=input->Size()%nb_batches;
+        }
+    
+      this->DoPredictBatch(input,batch_start,batch_size,targets,quality);
+      }
+    }
+    #else
+    this->DoPredictBatch(input,0,input->Size(),targets,quality);
+    #endif
+    return targets;
+    }
+}
+
+
+
+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
+{
+  assert(input != ITK_NULLPTR);
+  assert(targets != ITK_NULLPTR);
+  
+  assert(input->Size()==targets->Size()&&"Input sample list and target label list do not have the same size.");
+  assert(((quality==ITK_NULLPTR)||(quality->Size()==input->Size()))&&"Quality samples list is not null and does not have the same size as input samples list");
+
+  if(startIndex+size>input->Size())
+    {
+    itkExceptionMacro(<<"requested range ["<<startIndex<<", "<<startIndex+size<<"[ partially outside input sample list range.[0,"<<input->Size()<<"[");
+    }
+
+  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
     {
-    targets->PushBack(this->Predict(sIt.GetMeasurementVector()));
+    for(unsigned int id = startIndex;id<startIndex+size;++id)
+      {
+      const TargetSampleType target = this->DoPredict(input->GetMeasurementVector(id));
+      targets->SetMeasurementVector(id,target);
+      }
     }
 }
 
diff --git a/Modules/Learning/Supervised/include/otbMachineLearningModelFactory.txx b/Modules/Learning/Supervised/include/otbMachineLearningModelFactory.txx
index c5c5cea552a85b2f16b244e63d339c488d239d77..a99aa0f78e4d86f128b855299bfd4eacb340948b 100644
--- a/Modules/Learning/Supervised/include/otbMachineLearningModelFactory.txx
+++ b/Modules/Learning/Supervised/include/otbMachineLearningModelFactory.txx
@@ -35,6 +35,10 @@
 #include "otbLibSVMMachineLearningModelFactory.h"
 #endif
 
+#ifdef OTB_USE_SHARK
+#include "otbSharkRandomForestsMachineLearningModelFactory.h"
+#endif
+
 #include "itkMutexLockHolder.h"
 
 
@@ -98,6 +102,10 @@ MachineLearningModelFactory<TInputValue,TOutputValue>
   RegisterFactory(LibSVMMachineLearningModelFactory<TInputValue,TOutputValue>::New());
 #endif
 
+#ifdef OTB_USE_SHARK
+  RegisterFactory(SharkRandomForestsMachineLearningModelFactory<TInputValue,TOutputValue>::New());
+#endif
+  
 #ifdef OTB_USE_OPENCV
   RegisterFactory(RandomForestsMachineLearningModelFactory<TInputValue,TOutputValue>::New());
   RegisterFactory(SVMMachineLearningModelFactory<TInputValue,TOutputValue>::New());
@@ -107,8 +115,7 @@ MachineLearningModelFactory<TInputValue,TOutputValue>
   RegisterFactory(DecisionTreeMachineLearningModelFactory<TInputValue,TOutputValue>::New());
   RegisterFactory(GradientBoostedTreeMachineLearningModelFactory<TInputValue,TOutputValue>::New());
   RegisterFactory(KNearestNeighborsMachineLearningModelFactory<TInputValue,TOutputValue>::New());
-#endif
-
+#endif  
 }
 
 template <class TInputValue, class TOutputValue>
@@ -144,6 +151,17 @@ MachineLearningModelFactory<TInputValue,TOutputValue>
       continue;
       }
 #endif
+
+#ifdef OTB_USE_SHARK
+    SharkRandomForestsMachineLearningModelFactory<TInputValue,TOutputValue> *sharkRFFactory =
+      dynamic_cast<SharkRandomForestsMachineLearningModelFactory<TInputValue,TOutputValue> *>(*itFac);
+    if (sharkRFFactory)
+      {
+      itk::ObjectFactoryBase::UnRegisterFactory(sharkRFFactory);
+      continue;
+      }
+#endif
+
 #ifdef OTB_USE_OPENCV
     // RandomForest
     RandomForestsMachineLearningModelFactory<TInputValue,TOutputValue> *rfFactory =
@@ -209,7 +227,7 @@ MachineLearningModelFactory<TInputValue,TOutputValue>
       itk::ObjectFactoryBase::UnRegisterFactory(knnFactory);
       continue;
       }
-#endif
+#endif   
     }
 
 }
diff --git a/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.h b/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.h
index dd132b956d17a3a7a39f45d03d0a200d2b2ed3be..629f078bc5abe87973f343746521b67d89ae82c0 100644
--- a/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.h
+++ b/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.h
@@ -170,8 +170,6 @@ public:
 
   /** Train the machine learning model */
   void Train() ITK_OVERRIDE;
-  /** Predict values using the model */
-  TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality=NULL) const ITK_OVERRIDE;
 
   /** Save the model to file */
   void Save(const std::string & filename, const std::string & name="") ITK_OVERRIDE;
@@ -195,6 +193,9 @@ protected:
   /** Destructor */
   ~NeuralNetworkMachineLearningModel() ITK_OVERRIDE;
 
+  /** Predict values using the model */
+  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=ITK_NULLPTR) const ITK_OVERRIDE;
+  
   void LabelsToMat(const TargetListSampleType * listSample, cv::Mat & output);
 
   /** PrintSelf method */
diff --git a/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.txx b/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.txx
index 9e1e6bb8f507a01c8f4348d3e736db5fff3a5792..516655585ddb2063e332eef6ed4a67d1503bf3a9 100644
--- a/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.txx
+++ b/Modules/Learning/Supervised/include/otbNeuralNetworkMachineLearningModel.txx
@@ -200,7 +200,7 @@ void NeuralNetworkMachineLearningModel<TInputValue, TOutputValue>::Train()
 
 template<class TInputValue, class TOutputValue>
 typename NeuralNetworkMachineLearningModel<TInputValue, TOutputValue>::TargetSampleType NeuralNetworkMachineLearningModel<
-  TInputValue, TOutputValue>::Predict(const InputSampleType & input, ConfidenceValueType *quality) const
+  TInputValue, TOutputValue>::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const
 {
   //convert listsample to Mat
   cv::Mat sample;
diff --git a/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.h b/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.h
index f9362e970dfbfb9b5a82b87761e0e6c4b73333de..eb07312a21eaf9d0daf82bcf356e66cfda2ed505 100644
--- a/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.h
+++ b/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.h
@@ -54,8 +54,6 @@ public:
 
   /** Train the machine learning model */
   void Train() ITK_OVERRIDE;
-  /** Predict values using the model */
-  TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality=NULL) const ITK_OVERRIDE;
 
   /** Save the model to file */
   void Save(const std::string & filename, const std::string & name="") ITK_OVERRIDE;
@@ -79,6 +77,10 @@ protected:
   /** Destructor */
   ~NormalBayesMachineLearningModel() ITK_OVERRIDE;
 
+  /** Predict values using the model */
+  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=ITK_NULLPTR) const ITK_OVERRIDE;
+
+  
   /** PrintSelf method */
   void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE;
 
diff --git a/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.txx b/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.txx
index b4ef2c295546a8cc3b9ba003ea091f31a9d0d2a6..26b3f35aa19b7d87895e970bc682d821a9bf553e 100644
--- a/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.txx
+++ b/Modules/Learning/Supervised/include/otbNormalBayesMachineLearningModel.txx
@@ -61,7 +61,7 @@ template <class TInputValue, class TOutputValue>
 typename NormalBayesMachineLearningModel<TInputValue,TOutputValue>
 ::TargetSampleType
 NormalBayesMachineLearningModel<TInputValue,TOutputValue>
-::Predict(const InputSampleType & input, ConfidenceValueType *quality) const
+::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const
 {
   //convert listsample to Mat
   cv::Mat sample;
diff --git a/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.h b/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.h
index bdd265b18018bb6d955fb30ff952d8b48ddfc8dc..6ce9bf630be8d70d603ec1d12086acaf63e9b71f 100644
--- a/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.h
+++ b/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.h
@@ -62,8 +62,6 @@ public:
 
   /** Train the machine learning model */
   void Train() ITK_OVERRIDE;
-  /** Predict values using the model */
-  TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality=NULL) const ITK_OVERRIDE;
 
   /** Save the model to file */
   void Save(const std::string & filename, const std::string & name="") ITK_OVERRIDE;
@@ -136,6 +134,10 @@ protected:
   /** Destructor */
   ~RandomForestsMachineLearningModel() ITK_OVERRIDE;
 
+  /** Predict values using the model */
+  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=ITK_NULLPTR) const ITK_OVERRIDE;
+
+  
   /** PrintSelf method */
   void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE;
 
diff --git a/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.txx b/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.txx
index cb95be8e75b5edfaa0893c0f6f61050c3b339fb2..98042007b9382480a8176b910912d310a7d90a34 100644
--- a/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.txx
+++ b/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModel.txx
@@ -111,7 +111,7 @@ template <class TInputValue, class TOutputValue>
 typename RandomForestsMachineLearningModel<TInputValue,TOutputValue>
 ::TargetSampleType
 RandomForestsMachineLearningModel<TInputValue,TOutputValue>
-::Predict(const InputSampleType & value, ConfidenceValueType *quality) const
+::DoPredict(const InputSampleType & value, ConfidenceValueType *quality) const
 {
   //convert listsample to Mat
   cv::Mat sample;
@@ -204,9 +204,9 @@ RandomForestsMachineLearningModel<TInputValue,TOutputValue>
 {
   cv::Mat cvMat = m_RFModel->getVarImportance();
   VariableImportanceMatrixType itkMat(cvMat.rows,cvMat.cols);
-  for(unsigned int i =0; i<cvMat.rows; i++)
+  for(int i =0; i<cvMat.rows; i++)
     {
-    for(unsigned int j =0; j<cvMat.cols; j++)
+    for(int j =0; j<cvMat.cols; j++)
       {
       itkMat(i,j)=cvMat.at<float>(i,j);
       }
diff --git a/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModelFactory.h b/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModelFactory.h
index 02c97efe016551c0d9ed6b70546d0a3827728f02..7af7240036d2a6a6bca1f837571b692204bcc7b6 100644
--- a/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModelFactory.h
+++ b/Modules/Learning/Supervised/include/otbRandomForestsMachineLearningModelFactory.h
@@ -26,7 +26,7 @@
 namespace otb
 {
 /** \class RandomForestsMachineLearningModelFactory
- * \brief Creation d'un instance d'un objet RandomForestsMachineLearningModel utilisant les object factory.
+ * \brief Creation of an instance of a RandomForestsMachineLearningModel object using the object factory
  *
  * \ingroup OTBSupervised
  */
diff --git a/Modules/Learning/Supervised/include/otbRequiresSharkCheck.h b/Modules/Learning/Supervised/include/otbRequiresSharkCheck.h
new file mode 100644
index 0000000000000000000000000000000000000000..a358a1b6a934e2e2438bb7067bb5c4d9632b2962
--- /dev/null
+++ b/Modules/Learning/Supervised/include/otbRequiresSharkCheck.h
@@ -0,0 +1,26 @@
+/*=========================================================================
+
+  Program:   ORFEO Toolbox
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+
+  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+  See OTBCopyright.txt for details.
+
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the above copyright notices for more information.
+
+  =========================================================================*/
+#ifndef otbRequiresSharkCheck_h
+#define otbRequiresSharkCheck_h
+
+#include "otbConfigure.h"
+#ifndef OTB_USE_SHARK
+#  error "You need to enable Shark to compile this file"
+#endif
+
+#endif
diff --git a/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.h b/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.h
index 06131fe76b398260cdb970120504a8e2ba494d88..5eee69c652006382e9abd9c2a346e44ddb74b4dc 100644
--- a/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.h
+++ b/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.h
@@ -61,8 +61,6 @@ public:
 
   /** Train the machine learning model */
   void Train() ITK_OVERRIDE;
-  /** Predict values using the model */
-  TargetSampleType Predict(const InputSampleType& input, ConfidenceValueType *quality=NULL) const ITK_OVERRIDE;
 
   /** Save the model to file */
   void Save(const std::string & filename, const std::string & name="") ITK_OVERRIDE;
@@ -136,6 +134,10 @@ protected:
   /** Destructor */
   ~SVMMachineLearningModel() ITK_OVERRIDE;
 
+  /** Predict values using the model */
+  TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=ITK_NULLPTR) const ITK_OVERRIDE;
+
+  
   /** PrintSelf method */
   void PrintSelf(std::ostream& os, itk::Indent indent) const ITK_OVERRIDE;
 
diff --git a/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.txx b/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.txx
index 57006ce0d7945dcf6fdc8a38ea28d5a5e7940d19..48960bd13988910b2341cc7b65421c6bcdd555f0 100644
--- a/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.txx
+++ b/Modules/Learning/Supervised/include/otbSVMMachineLearningModel.txx
@@ -118,7 +118,7 @@ template <class TInputValue, class TOutputValue>
 typename SVMMachineLearningModel<TInputValue,TOutputValue>
 ::TargetSampleType
 SVMMachineLearningModel<TInputValue,TOutputValue>
-::Predict(const InputSampleType & input, ConfidenceValueType *quality) const
+::DoPredict(const InputSampleType & input, ConfidenceValueType *quality) const
 {
   //convert listsample to Mat
   cv::Mat sample;
diff --git a/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.h b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.h
new file mode 100644
index 0000000000000000000000000000000000000000..be45b9f4e4f32f3c74a8756190cd9cb22249ccd4
--- /dev/null
+++ b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.h
@@ -0,0 +1,172 @@
+/*=========================================================================
+
+  Program:   ORFEO Toolbox
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+
+  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+  See OTBCopyright.txt for details.
+
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef otbSharkRandomForestsMachineLearningModel_h
+#define otbSharkRandomForestsMachineLearningModel_h
+
+#include "otbRequiresSharkCheck.h"
+
+#include "itkLightObject.h"
+#include "otbMachineLearningModel.h"
+
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Woverloaded-virtual"
+#pragma GCC diagnostic ignored "-Wignored-qualifiers"
+#endif
+#include "shark/Algorithms/Trainers/RFTrainer.h"
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+
+/** \class SharkRandomForestsMachineLearningModel
+ *  \brief Shark version of Random Forests algorithm
+ *
+ *  This is a specialization of MachineLearningModel class allowing to
+ *  use Shark implementation of the Random Forests algorithm.
+ *
+ *  It is noteworthy that training step is parallel.
+ * 
+ *  For more information, see
+ *  http://image.diku.dk/shark/doxygen_pages/html/classshark_1_1_r_f_trainer.html
+ * 
+ *  \ingroup OTBSupervised
+ */
+
+namespace otb
+{
+template <class TInputValue, class TTargetValue>
+class ITK_EXPORT SharkRandomForestsMachineLearningModel
+  : public MachineLearningModel <TInputValue, TTargetValue>
+{
+public:
+  /** Standard class typedefs. */
+  typedef SharkRandomForestsMachineLearningModel               Self;
+  typedef MachineLearningModel<TInputValue, TTargetValue> Superclass;
+  typedef itk::SmartPointer<Self>                         Pointer;
+  typedef itk::SmartPointer<const Self>                   ConstPointer;
+
+  typedef typename Superclass::InputValueType             InputValueType;
+  typedef typename Superclass::InputSampleType            InputSampleType;
+  typedef typename Superclass::InputListSampleType        InputListSampleType;
+  typedef typename Superclass::TargetValueType            TargetValueType;
+  typedef typename Superclass::TargetSampleType           TargetSampleType;
+  typedef typename Superclass::TargetListSampleType       TargetListSampleType;
+  typedef typename Superclass::ConfidenceValueType        ConfidenceValueType;
+  typedef typename Superclass::ConfidenceSampleType       ConfidenceSampleType;
+  typedef typename Superclass::ConfidenceListSampleType   ConfidenceListSampleType;
+  
+  /** Run-time type information (and related methods). */
+  itkNewMacro(Self);
+  itkTypeMacro(SharkRandomForestsMachineLearningModel, MachineLearningModel);
+
+  /** Train the machine learning model */
+  virtual void Train() ITK_OVERRIDE;
+
+  /** Save the model to file */
+  virtual void Save(const std::string & filename, const std::string & name="") ITK_OVERRIDE;
+
+  /** Load the model from file */
+  virtual void Load(const std::string & filename, const std::string & name="") ITK_OVERRIDE;
+
+  /**\name Classification model file compatibility tests */
+  //@{
+  /** Is the input model file readable and compatible with the corresponding classifier ? */
+  virtual bool CanReadFile(const std::string &) ITK_OVERRIDE;
+
+  /** Is the input model file writable and compatible with the corresponding classifier ? */
+  virtual bool CanWriteFile(const std::string &) ITK_OVERRIDE;
+  //@}
+
+  /** From Shark doc: Get the number of trees to grow.*/
+  itkGetMacro(NumberOfTrees,unsigned int);
+  /** From Shark doc: Set the number of trees to grow.*/
+  itkSetMacro(NumberOfTrees,unsigned int);
+
+  /** From Shark doc: Get the number of random attributes to investigate at each node.*/
+  itkGetMacro(MTry, unsigned int);
+  /** From Shark doc: Set the number of random attributes to investigate at each node.*/
+  itkSetMacro(MTry, unsigned int);
+
+  /** From Shark doc: Controls when a node is considered pure. If set
+* to 1, a node is pure when it only consists of a single node.
+*/
+  itkGetMacro(NodeSize, unsigned int);
+    /** From Shark doc: Controls when a node is considered pure. If
+* set to 1, a node is pure when it only consists of a single node.
+ */
+  itkSetMacro(NodeSize, unsigned int);
+
+  /** From Shark doc: Get the fraction of the original training
+* dataset to use as the out of bag sample. The default value is
+* 0.66.*/
+  itkGetMacro(OobRatio, float);
+
+  /** From Shark doc: Set the fraction of the original training
+* dataset to use as the out of bag sample. The default value is 0.66.
+*/
+  itkSetMacro(OobRatio, float);
+
+  /** If true, margin confidence value will be computed */
+  itkGetMacro(ComputeMargin, bool);
+  /** If true, margin confidence value will be computed */
+  itkSetMacro(ComputeMargin, bool);
+
+protected:
+  /** Constructor */
+  SharkRandomForestsMachineLearningModel();
+
+  /** Destructor */
+  virtual ~SharkRandomForestsMachineLearningModel();
+
+  /** Predict values using the model */
+  virtual TargetSampleType DoPredict(const InputSampleType& input, ConfidenceValueType *quality=ITK_NULLPTR) const ITK_OVERRIDE;
+
+  
+  virtual void DoPredictBatch(const InputListSampleType *, const unsigned int & startIndex, const unsigned int & size, TargetListSampleType *, ConfidenceListSampleType * = ITK_NULLPTR) const ITK_OVERRIDE;
+  
+  /** PrintSelf method */
+  void PrintSelf(std::ostream& os, itk::Indent indent) const;
+
+private:
+  SharkRandomForestsMachineLearningModel(const Self &); //purposely not implemented
+  void operator =(const Self&); //purposely not implemented
+
+  shark::RFClassifier m_RFModel;
+  shark::RFTrainer m_RFTrainer;
+
+  unsigned int m_NumberOfTrees;
+  unsigned int m_MTry;
+  unsigned int m_NodeSize;
+  float m_OobRatio;
+  bool m_ComputeMargin;
+
+  /** Confidence list sample */
+  ConfidenceValueType ComputeConfidence(shark::RealVector & probas, 
+                                        bool computeMargin) const;
+
+};
+} // end namespace otb
+
+#ifndef OTB_MANUAL_INSTANTIATION
+#include "otbSharkRandomForestsMachineLearningModel.txx"
+#endif
+
+#endif
diff --git a/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.txx b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.txx
new file mode 100644
index 0000000000000000000000000000000000000000..833ab6b457e0e78a4cd073f694022d0a035331cb
--- /dev/null
+++ b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModel.txx
@@ -0,0 +1,249 @@
+/*=========================================================================
+
+  Program:   ORFEO Toolbox
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+
+  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+  See OTBCopyright.txt for details.
+
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef otbSharkRandomForestsMachineLearningModel_txx
+#define otbSharkRandomForestsMachineLearningModel_txx
+
+#include <fstream>
+#include "itkMacro.h"
+#include "otbSharkRandomForestsMachineLearningModel.h"
+
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Woverloaded-virtual"
+#pragma GCC diagnostic ignored "-Wignored-qualifiers"
+#endif
+#include <shark/Models/Converter.h>
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+
+
+#include "otbSharkUtils.h"
+#include <algorithm>
+
+namespace otb
+{
+
+template <class TInputValue, class TOutputValue>
+SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue>
+::SharkRandomForestsMachineLearningModel()
+{
+  this->m_ConfidenceIndex = true;
+  this->m_IsRegressionSupported = false;
+  this->m_IsDoPredictBatchMultiThreaded = true;
+}
+
+
+template <class TInputValue, class TOutputValue>
+SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue>
+::~SharkRandomForestsMachineLearningModel()
+{
+}
+
+/** Train the machine learning model */
+template <class TInputValue, class TOutputValue>
+void
+SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue>
+::Train()
+{
+#ifdef _OPENMP
+  omp_set_num_threads(itk::MultiThreader::GetGlobalDefaultNumberOfThreads());
+#endif
+  
+  std::vector<shark::RealVector> features;
+  std::vector<unsigned int> class_labels;
+
+  Shark::ListSampleToSharkVector(this->GetInputListSample(), features);
+  Shark::ListSampleToSharkVector(this->GetTargetListSample(), class_labels);
+  shark::ClassificationDataset TrainSamples = shark::createLabeledDataFromRange(features,class_labels);
+
+  //Set parameters
+  m_RFTrainer.setMTry(m_MTry);
+  m_RFTrainer.setNTrees(m_NumberOfTrees);
+  m_RFTrainer.setNodeSize(m_NodeSize);
+  m_RFTrainer.setOOBratio(m_OobRatio);
+  m_RFTrainer.train(m_RFModel, TrainSamples);
+
+}
+
+template <class TInputValue, class TOutputValue>
+typename SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue>
+::ConfidenceValueType
+SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue>
+::ComputeConfidence(shark::RealVector & probas, bool computeMargin) const
+{
+  assert(!probas.empty()&&"probas vector is empty");
+  assert((!computeMargin||probas.size()>1)&&"probas size should be at least 2 if computeMargin is true");
+  
+  ConfidenceValueType conf{0};
+  if(computeMargin)
+    {
+    std::nth_element(probas.begin(), probas.begin()+1, 
+                     probas.end(), std::greater<double>());
+    conf = static_cast<ConfidenceValueType>(probas[0]-probas[1]);
+    }
+  else
+    {
+    auto max_proba = *(std::max_element(probas.begin(), 
+                                        probas.end()));
+    conf = static_cast<ConfidenceValueType>(max_proba);
+    }
+  return conf;
+}
+
+template <class TInputValue, class TOutputValue>
+typename SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue>
+::TargetSampleType
+SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue>
+::DoPredict(const InputSampleType & value, ConfidenceValueType *quality) const
+{
+  shark::RealVector samples(value.Size());
+  for(size_t i = 0; i < value.Size();i++)
+    {
+    samples.push_back(value[i]);
+    }
+  if (quality != ITK_NULLPTR)
+    {
+    shark::RealVector probas = m_RFModel(samples);
+    (*quality) = ComputeConfidence(probas, m_ComputeMargin);
+    }
+  shark::ArgMaxConverter<shark::RFClassifier> amc;
+  amc.decisionFunction() = m_RFModel;
+  unsigned int res;
+  amc.eval(samples, res);
+  TargetSampleType target;
+  target[0] = static_cast<TOutputValue>(res);
+  return target;
+}
+
+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
+{
+  assert(input != ITK_NULLPTR);
+  assert(targets != ITK_NULLPTR);
+
+  assert(input->Size()==targets->Size()&&"Input sample list and target label list do not have the same size.");
+  assert(((quality==ITK_NULLPTR)||(quality->Size()==input->Size()))&&"Quality samples list is not null and does not have the same size as input samples list");
+  
+  if(startIndex+size>input->Size())
+    {
+    itkExceptionMacro(<<"requested range ["<<startIndex<<", "<<startIndex+size<<"[ partially outside input sample list range.[0,"<<input->Size()<<"[");
+    }
+  
+  std::vector<shark::RealVector> features;
+  Shark::ListSampleRangeToSharkVector(input, features,startIndex,size);
+  shark::Data<shark::RealVector> inputSamples = shark::createDataFromRange(features);
+
+  #ifdef _OPENMP
+  omp_set_num_threads(itk::MultiThreader::GetGlobalDefaultNumberOfThreads());
+  #endif
+  
+  shark::Data<shark::RealVector> probas = m_RFModel(inputSamples);
+
+  if(quality != ITK_NULLPTR)
+    {
+    unsigned int id = startIndex;
+    for(shark::RealVector && p : probas.elements())
+      {
+      ConfidenceSampleType confidence;
+      auto conf = ComputeConfidence(p, m_ComputeMargin);
+      confidence[0] = static_cast<ConfidenceValueType>(conf);
+      quality->SetMeasurementVector(id,confidence);
+      ++id;
+      }
+    }
+    
+  shark::ArgMaxConverter<shark::RFClassifier> amc;
+  amc.decisionFunction() = m_RFModel;
+  auto prediction = amc(inputSamples);
+  unsigned int id = startIndex;
+  for(const auto& p : prediction.elements())
+    {
+    TargetSampleType target;
+    target[0] = static_cast<TOutputValue>(p);
+    targets->SetMeasurementVector(id,target);
+    ++id;
+    }
+}
+
+template <class TInputValue, class TOutputValue>
+void
+SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue>
+::Save(const std::string & filename, const std::string & itkNotUsed(name))
+{
+  std::ofstream ofs(filename.c_str());
+  if(!ofs)
+    {
+    itkExceptionMacro(<< "Error opening " << filename.c_str() );
+    }
+  shark::TextOutArchive oa(ofs);
+  m_RFModel.save(oa,0);
+}
+
+template <class TInputValue, class TOutputValue>
+void
+SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue>
+::Load(const std::string & filename, const std::string & itkNotUsed(name))
+{
+  std::ifstream ifs(filename.c_str());
+  shark::TextInArchive ia(ifs);
+  m_RFModel.load(ia,0);
+}
+
+template <class TInputValue, class TOutputValue>
+bool
+SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue>
+::CanReadFile(const std::string & file)
+{
+  try
+    {
+    this->Load(file);
+    m_RFModel.name();
+    }
+  catch(...)
+    {
+    return false;
+    }
+  return true;
+}
+
+template <class TInputValue, class TOutputValue>
+bool
+SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue>
+::CanWriteFile(const std::string & itkNotUsed(file))
+{
+  return true;
+}
+
+template <class TInputValue, class TOutputValue>
+void
+SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue>
+::PrintSelf(std::ostream& os, itk::Indent indent) const
+{
+  // Call superclass implementation
+  Superclass::PrintSelf(os,indent);
+}
+
+} //end namespace otb
+
+#endif
diff --git a/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModelFactory.h b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModelFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..242eeb7aa7494cc6a1c705d03c76fa365db8412f
--- /dev/null
+++ b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModelFactory.h
@@ -0,0 +1,74 @@
+/*=========================================================================
+
+  Program:   ORFEO Toolbox
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+
+  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+  See OTBCopyright.txt for details.
+
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef otbSharkRandomForestsMachineLearningModelFactory_h
+#define otbSharkRandomForestsMachineLearningModelFactory_h
+
+#include "itkObjectFactoryBase.h"
+#include "itkImageIOBase.h"
+
+namespace otb
+{
+/** \class SharkRandomForestsMachineLearningModelFactory
+ * \brief Creation of an instance of a SharkRandomForestsMachineLearningModel object using the object factory
+ *
+ * \ingroup OTBSupervised
+ */
+template <class TInputValue, class TTargetValue>
+class ITK_EXPORT SharkRandomForestsMachineLearningModelFactory : public itk::ObjectFactoryBase
+{
+public:
+  /** Standard class typedefs. */
+  typedef SharkRandomForestsMachineLearningModelFactory             Self;
+  typedef itk::ObjectFactoryBase        Superclass;
+  typedef itk::SmartPointer<Self>       Pointer;
+  typedef itk::SmartPointer<const Self> ConstPointer;
+
+  /** Class methods used to interface with the registered factories. */
+  virtual const char* GetITKSourceVersion(void) const;
+  virtual const char* GetDescription(void) const;
+
+  /** Method for class instantiation. */
+  itkFactorylessNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(SharkRandomForestsMachineLearningModelFactory, itk::ObjectFactoryBase);
+
+  /** Register one factory of this type  */
+  static void RegisterOneFactory(void)
+  {
+    Pointer RFFactory = SharkRandomForestsMachineLearningModelFactory::New();
+    itk::ObjectFactoryBase::RegisterFactory(RFFactory);
+  }
+
+protected:
+  SharkRandomForestsMachineLearningModelFactory();
+  virtual ~SharkRandomForestsMachineLearningModelFactory();
+
+private:
+  SharkRandomForestsMachineLearningModelFactory(const Self &); //purposely not implemented
+  void operator =(const Self&); //purposely not implemented
+
+};
+
+} // end namespace otb
+
+#ifndef OTB_MANUAL_INSTANTIATION
+#include "otbSharkRandomForestsMachineLearningModelFactory.txx"
+#endif
+
+#endif
diff --git a/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModelFactory.txx b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModelFactory.txx
new file mode 100644
index 0000000000000000000000000000000000000000..9bd3c5217e79ede101a72ecca0d2b65b879afb01
--- /dev/null
+++ b/Modules/Learning/Supervised/include/otbSharkRandomForestsMachineLearningModelFactory.txx
@@ -0,0 +1,70 @@
+/*=========================================================================
+
+  Program:   ORFEO Toolbox
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+
+  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+  See OTBCopyright.txt for details.
+
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+#ifndef otbSharkRandomForestsMachineLearningModelFactory_txx
+#define otbSharkRandomForestsMachineLearningModelFactory_txx
+
+
+#include "otbSharkRandomForestsMachineLearningModelFactory.h"
+
+#include "itkCreateObjectFunction.h"
+#include "otbSharkRandomForestsMachineLearningModel.h"
+#include "itkVersion.h"
+
+namespace otb
+{
+
+template <class TInputValue, class TOutputValue>
+SharkRandomForestsMachineLearningModelFactory<TInputValue,TOutputValue>
+::SharkRandomForestsMachineLearningModelFactory()
+{
+
+  std::string classOverride = std::string("otbMachineLearningModel");
+  std::string subclass = std::string("otbSharkRandomForestsMachineLearningModel");
+
+  this->RegisterOverride(classOverride.c_str(),
+                         subclass.c_str(),
+                         "Shark RF ML Model",
+                         1,
+                         itk::CreateObjectFunction<SharkRandomForestsMachineLearningModel<TInputValue,TOutputValue> >::New());
+}
+
+template <class TInputValue, class TOutputValue>
+SharkRandomForestsMachineLearningModelFactory<TInputValue,TOutputValue>
+::~SharkRandomForestsMachineLearningModelFactory()
+{
+}
+
+template <class TInputValue, class TOutputValue>
+const char*
+SharkRandomForestsMachineLearningModelFactory<TInputValue,TOutputValue>
+::GetITKSourceVersion(void) const
+{
+  return ITK_SOURCE_VERSION;
+}
+
+template <class TInputValue, class TOutputValue>
+const char*
+SharkRandomForestsMachineLearningModelFactory<TInputValue,TOutputValue>
+::GetDescription() const
+{
+  return "Shark Random Forest machine learning model factory";
+}
+
+} // end namespace otb
+
+#endif
diff --git a/Modules/Learning/Supervised/include/otbSharkUtils.h b/Modules/Learning/Supervised/include/otbSharkUtils.h
new file mode 100644
index 0000000000000000000000000000000000000000..ed70f03fca36f5a0498512012eba3315ea5c76bd
--- /dev/null
+++ b/Modules/Learning/Supervised/include/otbSharkUtils.h
@@ -0,0 +1,124 @@
+/*=========================================================================
+
+  Program:   ORFEO Toolbox
+  Language:  C++
+  Date:      $Date$
+  Version:   $Revision$
+
+
+  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+  See OTBCopyright.txt for details.
+
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the above copyright notices for more information.
+
+  =========================================================================*/
+#ifndef otbSharkUtils_h
+#define otbSharkUtils_h
+
+#include "otbRequiresSharkCheck.h"
+
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wshadow"
+#endif
+#include <shark/Data/Dataset.h>
+#if defined(__GNUC__) || defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+
+namespace otb
+{
+namespace Shark
+{
+template <class T> void ListSampleRangeToSharkVector(const T * listSample, std::vector<shark::RealVector> & output, unsigned int start, unsigned int size)
+{
+  assert(listSample != ITK_NULLPTR);
+
+  if(start+size>listSample->Size())
+    {
+    itkGenericExceptionMacro(<<"Requested range ["<<start<<", "<<start+size<<"[ is out of bound for input list sample (range [0, "<<listSample->Size()<<"[");
+    }
+  
+  output.clear();
+      
+  // Sample index
+  unsigned int sampleIdx = start;
+    
+  //Check for valid listSample
+  if(listSample->Size()>0)
+    {
+    // Retrieve samples size alike
+    const unsigned int sampleSize = listSample->GetMeasurementVectorSize();
+
+    // Fill the output vector
+
+    for (auto const endOfRange = start+size ; sampleIdx < endOfRange ; ++sampleIdx)
+      {
+      // Retrieve sample
+      typename T::MeasurementVectorType const & sample = listSample->GetMeasurementVector(sampleIdx);
+	   
+      // // Define a shark::RealVector
+      // shark::RealVector rv(sampleSize);
+      // // Loop on sample size
+      // for(unsigned int i = 0; i < sampleSize; ++i)
+      //   {
+      //   rv[i] = sample[i];
+      //   }
+      // using std::move;
+      // output.emplace_back(move(rv));
+
+      output.emplace_back(&sample[0], &sample[0]+sampleSize);
+      }
+    }
+}
+
+template <class T> void ListSampleRangeToSharkVector(const T * listSample, std::vector<unsigned int> & output, unsigned int start, unsigned int size)
+{
+  assert(listSample != ITK_NULLPTR);
+
+  if(start+size>listSample->Size())
+    {
+    itkGenericExceptionMacro(<<"Requested range ["<<start<<", "<<start+size<<"[ is out of bound for input list sample (range [0, "<<listSample->Size()<<"[");
+    }
+
+  output.clear();
+  
+  // Sample index
+  unsigned int sampleIdx = start;
+    
+  //Check for valid listSample
+  if(listSample->Size()>0)
+    {
+    // Fill the output vector
+    while(sampleIdx<start+size)
+      {
+      // Retrieve sample
+      typename T::MeasurementVectorType const & sample = listSample->GetMeasurementVector(sampleIdx);
+	   
+      // Define a shark::RealVector
+      output.push_back(sample[0]);
+      ++sampleIdx;
+      }
+    } 
+}
+
+template <class T> void ListSampleToSharkVector(const T * listSample, std::vector<shark::RealVector> & output)
+{
+  assert(listSample != ITK_NULLPTR);
+  ListSampleRangeToSharkVector(listSample,output,0U,static_cast<unsigned int>(listSample->Size()));
+}
+
+template <class T> void ListSampleToSharkVector(const T * listSample, std::vector<unsigned int> & output)
+{
+  assert(listSample != ITK_NULLPTR);
+  ListSampleRangeToSharkVector(listSample,output,0, static_cast<unsigned int>(listSample->Size()));
+}
+  
+}
+}
+
+#endif
+
diff --git a/Modules/Learning/Supervised/otb-module.cmake b/Modules/Learning/Supervised/otb-module.cmake
index cce5b946c6e6e0d7aed1919ce8049b107a7fe01c..ebce0f334e6156c859dbb8d715c6287896e3b7ca 100644
--- a/Modules/Learning/Supervised/otb-module.cmake
+++ b/Modules/Learning/Supervised/otb-module.cmake
@@ -13,7 +13,8 @@ ENABLE_SHARED
   OPTIONAL_DEPENDS
     OTBOpenCV
     OTBSVMLearning
-
+    OTBShark
+    
   TEST_DEPENDS
     OTBTestKernel
     OTBImageIO
diff --git a/Modules/Learning/Supervised/src/CMakeLists.txt b/Modules/Learning/Supervised/src/CMakeLists.txt
index b99187d2eab62b67dbe59892d38baddca4663016..015e24e74c3ec0e450cb01d267ab46c3935576fb 100644
--- a/Modules/Learning/Supervised/src/CMakeLists.txt
+++ b/Modules/Learning/Supervised/src/CMakeLists.txt
@@ -11,6 +11,7 @@ target_link_libraries(OTBSupervised
   ${OTBCommon_LIBRARIES}
   ${OTBSVMLearning_LIBRARIES}
   ${OTBOpenCV_LIBRARIES}
+  ${SHARK_LIBRARIES}
   )
 
 otb_module_target(OTBSupervised)
diff --git a/Modules/Learning/Supervised/test/CMakeLists.txt b/Modules/Learning/Supervised/test/CMakeLists.txt
index abca168f4f7794ea1a9133370c65555593b9bf19..d6824242efe74f33d16fc55d2ae906d1dacd3546 100644
--- a/Modules/Learning/Supervised/test/CMakeLists.txt
+++ b/Modules/Learning/Supervised/test/CMakeLists.txt
@@ -1,5 +1,4 @@
 otb_module_test()
-
 set(OTBSupervisedTests
 otbSupervisedTestDriver.cxx
 otbConfusionMatrixCalculatorTest.cxx
@@ -10,6 +9,10 @@ otbImageClassificationFilter.cxx
 otbMachineLearningRegressionTests.cxx
 )
 
+if(OTB_USE_SHARK)
+set(OTBSupervisedTests ${OTBSupervisedTests} otbSharkImageClassificationFilter.cxx)
+endif()
+
 add_executable(otbSupervisedTestDriver ${OTBSupervisedTests})
 target_link_libraries(otbSupervisedTestDriver ${OTBSupervised-Test_LIBRARIES})
 otb_module_target_label(otbSupervisedTestDriver)
@@ -54,3 +57,7 @@ endif()
 if(OTB_USE_OPENCV)
   include(tests-opencv.cmake)
 endif()
+
+if(OTB_USE_SHARK)
+  include(tests-shark.cmake)
+endif()
diff --git a/Modules/Learning/Supervised/test/otbImageClassificationFilter.cxx b/Modules/Learning/Supervised/test/otbImageClassificationFilter.cxx
index 760a4fdb870f0e53d6783ae2a6385bc2a8dca40d..c2337665d60aa67093e6beea33e2396e8f89b365 100644
--- a/Modules/Learning/Supervised/test/otbImageClassificationFilter.cxx
+++ b/Modules/Learning/Supervised/test/otbImageClassificationFilter.cxx
@@ -42,6 +42,32 @@ int otbImageClassificationFilterNew(int itkNotUsed(argc), char * itkNotUsed(argv
   return EXIT_SUCCESS;
 }
 
+int otbImageClassificationFilterLoadModel(int itkNotUsed(argc), char * argv[])
+{
+  const char * infname = argv[1];
+  const char * modelfname = argv[2];
+
+  // Instantiating object
+  ClassificationFilterType::Pointer filter = ClassificationFilterType::New();
+
+  ReaderType::Pointer reader = ReaderType::New();
+  reader->SetFileName(infname);
+
+  ModelType::Pointer model;
+
+  model = MachineLearningModelFactoryType::CreateMachineLearningModel(modelfname,
+                                                                      MachineLearningModelFactoryType::ReadMode);
+
+  if (model.IsNull())
+    {
+    std::cerr << "Unable to create a model from " << modelfname << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  model->Load(modelfname);
+  return EXIT_SUCCESS;
+}
+
 int otbImageClassificationFilter(int itkNotUsed(argc), char * argv[])
 {
   const char * infname = argv[1];
diff --git a/Modules/Learning/Supervised/test/otbMachineLearningModelCanRead.cxx b/Modules/Learning/Supervised/test/otbMachineLearningModelCanRead.cxx
index 4749acfa32f5265d2112f116317abe194c40c4ae..b302542e812e50a90aa2359db5eca5068ff06c9e 100644
--- a/Modules/Learning/Supervised/test/otbMachineLearningModelCanRead.cxx
+++ b/Modules/Learning/Supervised/test/otbMachineLearningModelCanRead.cxx
@@ -18,22 +18,9 @@
 
 #include <iostream>
 
+#include <otbConfigure.h>
 #include <otbMachineLearningModel.h>
 
-#ifdef OTB_USE_LIBSVM
-#include "otbLibSVMMachineLearningModel.h"
-#endif
-#ifdef OTB_USE_OPENCV
-#include "otbSVMMachineLearningModel.h"
-#include "otbRandomForestsMachineLearningModel.h"
-#include "otbBoostMachineLearningModel.h"
-#include "otbNeuralNetworkMachineLearningModel.h"
-#include "otbNormalBayesMachineLearningModel.h"
-#include "otbDecisionTreeMachineLearningModel.h"
-#include "otbGradientBoostedTreeMachineLearningModel.h"
-#include "otbKNearestNeighborsMachineLearningModel.h"
-#endif
-
 typedef otb::MachineLearningModel<float,short>         MachineLearningModelType;
 typedef MachineLearningModelType::InputValueType       InputValueType;
 typedef MachineLearningModelType::InputSampleType      InputSampleType;
@@ -42,6 +29,10 @@ typedef MachineLearningModelType::TargetValueType      TargetValueType;
 typedef MachineLearningModelType::TargetSampleType     TargetSampleType;
 typedef MachineLearningModelType::TargetListSampleType TargetListSampleType;
 
+
+#ifdef OTB_USE_LIBSVM
+#include "otbLibSVMMachineLearningModel.h"
+
 int otbLibSVMMachineLearningModelCanRead(int argc, char* argv[])
 {
   if (argc != 2)
@@ -57,7 +48,6 @@ int otbLibSVMMachineLearningModelCanRead(int argc, char* argv[])
     }
   std::string filename(argv[1]);
   
-  #ifdef OTB_USE_LIBSVM
   typedef otb::LibSVMMachineLearningModel<InputValueType, TargetValueType> SVMType;
   SVMType::Pointer classifier = SVMType::New();
   bool lCanRead = classifier->CanReadFile(filename);
@@ -66,10 +56,21 @@ int otbLibSVMMachineLearningModelCanRead(int argc, char* argv[])
     std::cerr << "Erreur otb::LibSVMMachineLearningModel : impossible to open the file " << filename << "." << std::endl;
     return EXIT_FAILURE;
     }
-  #endif
-
+  
   return EXIT_SUCCESS;
 }
+#endif
+
+
+#ifdef OTB_USE_OPENCV
+#include "otbSVMMachineLearningModel.h"
+#include "otbRandomForestsMachineLearningModel.h"
+#include "otbBoostMachineLearningModel.h"
+#include "otbNeuralNetworkMachineLearningModel.h"
+#include "otbNormalBayesMachineLearningModel.h"
+#include "otbDecisionTreeMachineLearningModel.h"
+#include "otbGradientBoostedTreeMachineLearningModel.h"
+#include "otbKNearestNeighborsMachineLearningModel.h"
 
 int otbSVMMachineLearningModelCanRead(int argc, char* argv[])
 {
@@ -86,7 +87,6 @@ int otbSVMMachineLearningModelCanRead(int argc, char* argv[])
     }
   std::string filename(argv[1]);
   
-  #ifdef OTB_USE_OPENCV
   typedef otb::SVMMachineLearningModel<InputValueType, TargetValueType> SVMType;
   SVMType::Pointer classifier = SVMType::New();
   bool lCanRead = classifier->CanReadFile(filename);
@@ -95,7 +95,6 @@ int otbSVMMachineLearningModelCanRead(int argc, char* argv[])
     std::cerr << "Erreur otb::SVMMachineLearningModel : impossible to open the file " << filename << "." << std::endl;
     return EXIT_FAILURE;
     }
-  #endif
 
   return EXIT_SUCCESS;
 }
@@ -115,7 +114,6 @@ int otbRandomForestsMachineLearningModelCanRead(int argc, char* argv[])
     }
   std::string filename(argv[1]);
   
-  #ifdef OTB_USE_OPENCV
   typedef otb::RandomForestsMachineLearningModel<InputValueType, TargetValueType> RFType;
   RFType::Pointer classifier = RFType::New();
   bool lCanRead = classifier->CanReadFile(filename);
@@ -124,7 +122,6 @@ int otbRandomForestsMachineLearningModelCanRead(int argc, char* argv[])
     std::cerr << "Erreur otb::RandomForestsMachineLearningModel : impossible to open the file " << filename << "." << std::endl;
     return EXIT_FAILURE;
     }
-  #endif
 
   return EXIT_SUCCESS;
 }
@@ -144,7 +141,6 @@ int otbBoostMachineLearningModelCanRead(int argc, char* argv[])
     }
   std::string filename(argv[1]);
   
-  #ifdef OTB_USE_OPENCV
   typedef otb::BoostMachineLearningModel<InputValueType, TargetValueType> BoostType;
   BoostType::Pointer classifier = BoostType::New();
   bool lCanRead = classifier->CanReadFile(filename);
@@ -153,7 +149,6 @@ int otbBoostMachineLearningModelCanRead(int argc, char* argv[])
     std::cerr << "Erreur otb::BoostMachineLearningModel : impossible to open the file " << filename << "." << std::endl;
     return EXIT_FAILURE;
     }
-  #endif
 
   return EXIT_SUCCESS;
 }
@@ -173,7 +168,6 @@ int otbNeuralNetworkMachineLearningModelCanRead(int argc, char* argv[])
     }
   std::string filename(argv[1]);
   
-  #ifdef OTB_USE_OPENCV
   typedef otb::NeuralNetworkMachineLearningModel<InputValueType, TargetValueType> ANNType;
   ANNType::Pointer classifier = ANNType::New();
   bool lCanRead = classifier->CanReadFile(filename);
@@ -182,7 +176,6 @@ int otbNeuralNetworkMachineLearningModelCanRead(int argc, char* argv[])
     std::cerr << "Erreur otb::NeuralNetworkMachineLearningModel : impossible to open the file " << filename << "." << std::endl;
     return EXIT_FAILURE;
     }
-  #endif
 
   return EXIT_SUCCESS;
 }
@@ -202,7 +195,6 @@ int otbNormalBayesMachineLearningModelCanRead(int argc, char* argv[])
     }
   std::string filename(argv[1]);
   
-  #ifdef OTB_USE_OPENCV
   typedef otb::NormalBayesMachineLearningModel<InputValueType, TargetValueType> NormalBayesType;
   NormalBayesType::Pointer classifier = NormalBayesType::New();
   bool lCanRead = classifier->CanReadFile(filename);
@@ -211,7 +203,6 @@ int otbNormalBayesMachineLearningModelCanRead(int argc, char* argv[])
     std::cerr << "Erreur otb::NormalBayesMachineLearningModel : impossible to open the file " << filename << "." << std::endl;
     return EXIT_FAILURE;
     }
-  #endif
 
   return EXIT_SUCCESS;
 }
@@ -231,7 +222,6 @@ int otbDecisionTreeMachineLearningModelCanRead(int argc, char* argv[])
     }
   std::string filename(argv[1]);
   
-  #ifdef OTB_USE_OPENCV
   typedef otb::DecisionTreeMachineLearningModel<InputValueType, TargetValueType> DecisionTreeType;
   DecisionTreeType::Pointer classifier = DecisionTreeType::New();
   bool lCanRead = classifier->CanReadFile(filename);
@@ -240,7 +230,6 @@ int otbDecisionTreeMachineLearningModelCanRead(int argc, char* argv[])
     std::cerr << "Erreur otb::DecisionTreeMachineLearningModel : impossible to open the file " << filename << "." << std::endl;
     return EXIT_FAILURE;
     }
-  #endif
 
   return EXIT_SUCCESS;
 }
@@ -260,7 +249,6 @@ int otbGradientBoostedTreeMachineLearningModelCanRead(int argc, char* argv[])
     }
   std::string filename(argv[1]);
   
-  #ifdef OTB_USE_OPENCV
   typedef otb::GradientBoostedTreeMachineLearningModel<InputValueType, TargetValueType> GBTreeType;
   GBTreeType::Pointer classifier = GBTreeType::New();
   bool lCanRead = classifier->CanReadFile(filename);
@@ -269,7 +257,6 @@ int otbGradientBoostedTreeMachineLearningModelCanRead(int argc, char* argv[])
     std::cerr << "Erreur otb::GradientBoostedTreeMachineLearningModel : impossible to open the file " << filename << "." << std::endl;
     return EXIT_FAILURE;
     }
-  #endif
 
   return EXIT_SUCCESS;
 }
@@ -289,7 +276,6 @@ int otbKNNMachineLearningModelCanRead(int argc, char* argv[])
     }
   std::string filename(argv[1]);
   
-  #ifdef OTB_USE_OPENCV
   typedef otb::KNearestNeighborsMachineLearningModel<InputValueType, TargetValueType> KNNType;
   KNNType::Pointer classifier = KNNType::New();
   bool lCanRead = classifier->CanReadFile(filename);
@@ -298,8 +284,39 @@ int otbKNNMachineLearningModelCanRead(int argc, char* argv[])
     std::cerr << "Erreur otb::KNearestNeighborsMachineLearningModel : impossible to open the file " << filename << "." << std::endl;
     return EXIT_FAILURE;
     }
-  #endif
 
   return EXIT_SUCCESS;
 }
+#endif
+
 
+#ifdef OTB_USE_SHARK
+#include "otbSharkRandomForestsMachineLearningModel.h"
+
+int otbSharkRFMachineLearningModelCanRead(int argc, char* argv[])
+{
+  if (argc != 2)
+    {
+    std::cerr << "Usage: " << argv[0]
+              << "<model>" << std::endl;
+    std::cerr << "Called here with " << argc << " arguments\n";
+    for (int i = 1; i < argc; ++i)
+      {
+      std::cerr << " - " << argv[i] << "\n";
+      }
+    return EXIT_FAILURE;
+    }
+  std::string filename(argv[1]);
+  typedef otb::SharkRandomForestsMachineLearningModel<InputValueType, TargetValueType> RFType;
+  RFType::Pointer classifier = RFType::New();
+  bool lCanRead = classifier->CanReadFile(filename);
+  if (lCanRead == false)
+    {
+    std::cerr << "Error otb::SharkRandomForestsMachineLearningModel : impossible to open the file " << filename << "." << std::endl;
+    return EXIT_FAILURE;
+    }
+
+  return EXIT_SUCCESS;
+}
+
+#endif
diff --git a/Modules/Learning/Supervised/test/otbMachineLearningRegressionTests.cxx b/Modules/Learning/Supervised/test/otbMachineLearningRegressionTests.cxx
index 2b0554d4372acc37f6754f394d2775498168ef53..efb46f39a76d06c50dd79d9c5f37e8bfc159d9e7 100644
--- a/Modules/Learning/Supervised/test/otbMachineLearningRegressionTests.cxx
+++ b/Modules/Learning/Supervised/test/otbMachineLearningRegressionTests.cxx
@@ -24,6 +24,8 @@
 const double otb_epsilon_01 = 0.1;
 #endif
 
+#include "otbMachineLearningModel.h"
+
 #ifdef OTB_USE_OPENCV
 #include "otbNeuralNetworkMachineLearningModel.h"
 #include "otbSVMMachineLearningModel.h"
diff --git a/Modules/Learning/Supervised/test/otbSharkImageClassificationFilter.cxx b/Modules/Learning/Supervised/test/otbSharkImageClassificationFilter.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..6553f2970fa32650d5579743b10ebcd3730a84cd
--- /dev/null
+++ b/Modules/Learning/Supervised/test/otbSharkImageClassificationFilter.cxx
@@ -0,0 +1,162 @@
+/*=========================================================================
+
+ Program:   ORFEO Toolbox
+ Language:  C++
+ Date:      $Date$
+ Version:   $Revision$
+
+
+ Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+ See OTBCopyright.txt for details.
+
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE.  See the above copyright notices for more information.
+
+ =========================================================================*/
+#include "otbImageClassificationFilter.h"
+#include "otbVectorImage.h"
+#include "otbImage.h"
+#include "otbImageFileReader.h"
+#include "otbImageFileWriter.h"
+#include "otbSharkRandomForestsMachineLearningModelFactory.h"
+#include <random>
+#include <chrono>
+
+const unsigned int Dimension = 2;
+typedef float PixelType;
+typedef unsigned short LabeledPixelType;
+
+typedef otb::VectorImage<PixelType, Dimension> ImageType;
+typedef otb::Image<LabeledPixelType, Dimension> LabeledImageType;
+typedef otb::ImageClassificationFilter<ImageType, LabeledImageType> ClassificationFilterType;
+typedef ClassificationFilterType::ModelType ModelType;
+typedef ClassificationFilterType::ValueType ValueType;
+typedef ClassificationFilterType::LabelType LabelType;
+typedef otb::SharkRandomForestsMachineLearningModelFactory<ValueType, LabelType> MachineLearningModelFactoryType;
+typedef otb::ImageFileReader<ImageType> ReaderType;
+typedef otb::ImageFileReader<LabeledImageType> MaskReaderType;
+typedef otb::ImageFileWriter<LabeledImageType> WriterType;
+
+typedef otb::SharkRandomForestsMachineLearningModel<PixelType,short unsigned int>         MachineLearningModelType;
+typedef MachineLearningModelType::InputValueType       LocalInputValueType;
+typedef MachineLearningModelType::InputSampleType      LocalInputSampleType;
+typedef MachineLearningModelType::InputListSampleType  LocalInputListSampleType;
+typedef MachineLearningModelType::TargetValueType      LocalTargetValueType;
+typedef MachineLearningModelType::TargetSampleType     LocalTargetSampleType;
+typedef MachineLearningModelType::TargetListSampleType LocalTargetListSampleType;
+
+void generateSamples(unsigned int num_classes, unsigned int num_samples,
+                     unsigned int num_features,
+                     LocalInputListSampleType * samples, 
+                     LocalTargetListSampleType * labels)
+{
+  std::default_random_engine generator;
+  std::uniform_int_distribution<int> label_distribution(1,num_classes);
+  std::uniform_int_distribution<int> feat_distribution(0,256);
+  for(size_t scount=0; scount<num_samples; ++scount)
+    {
+    LabeledPixelType label = label_distribution(generator);
+    LocalInputSampleType sample(num_features);
+    for(unsigned int i=0; i<num_features; ++i)
+      sample[i]= feat_distribution(generator);
+    samples->SetMeasurementVectorSize(num_features);
+    samples->PushBack(sample); 
+    labels->PushBack(label);
+    }
+}
+
+void buildModel(unsigned int num_classes, unsigned int num_samples,
+                unsigned int num_features, std::string modelfname)
+{
+  LocalInputListSampleType::Pointer samples = LocalInputListSampleType::New();
+  LocalTargetListSampleType::Pointer labels = LocalTargetListSampleType::New();
+
+  std::cout << "Sample generation\n";
+  generateSamples(num_classes, num_samples, num_features, samples, labels);
+
+  MachineLearningModelType::Pointer classifier = MachineLearningModelType::New();
+  classifier->SetInputListSample(samples);
+  classifier->SetTargetListSample(labels);
+  classifier->SetRegressionMode(false);
+  classifier->SetNumberOfTrees(100);
+  classifier->SetMTry(0);
+  classifier->SetNodeSize(25);
+  classifier->SetOobRatio(0.3);
+  std::cout << "Training\n";
+  using TimeT = std::chrono::milliseconds;
+  auto start = std::chrono::system_clock::now();
+  classifier->Train();
+  auto duration = std::chrono::duration_cast< TimeT> 
+    (std::chrono::system_clock::now() - start);
+  auto elapsed = duration.count();
+  std::cout << "Training took " << elapsed << " ms\n";
+  classifier->Save(modelfname);
+}
+
+int otbSharkImageClassificationFilter(int argc, char * argv[])
+{
+  if(argc<5 || argc>7)
+    {
+    std::cout << "Usage: input_image output_image output_confidence 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 modelfname = "/tmp/rf_model.txt";
+  std::string maskfname{};
+
+  MaskReaderType::Pointer mask_reader = MaskReaderType::New();
+  ReaderType::Pointer reader = ReaderType::New();
+  reader->SetFileName(imfname);
+  reader->UpdateOutputInformation();
+
+  auto num_features = reader->GetOutput()->GetNumberOfComponentsPerPixel();
+
+  std::cout << "Image has " << num_features << " bands\n";
+    
+  if(argc>5)
+    {
+    modelfname = argv[5];
+    }
+  else
+    {
+    buildModel(3, 1000, num_features, modelfname);
+    }
+
+  ClassificationFilterType::Pointer filter = ClassificationFilterType::New();
+
+  MachineLearningModelType::Pointer model = MachineLearningModelType::New();
+  model->Load(modelfname);
+  filter->SetModel(model);
+  filter->SetInput(reader->GetOutput());
+  if(argc==7)
+    {
+    maskfname = argv[6];
+    mask_reader->SetFileName(maskfname);
+    filter->SetInputMask(mask_reader->GetOutput());
+    }
+
+  WriterType::Pointer writer = WriterType::New();
+  writer->SetInput(filter->GetOutput());
+  writer->SetFileName(outfname);
+  std::cout << "Classification\n";
+  filter->SetBatchMode(batch);
+  filter->SetUseConfidenceMap(true);
+  using TimeT = std::chrono::milliseconds;
+  auto start = std::chrono::system_clock::now();
+  writer->Update();
+  auto duration = std::chrono::duration_cast< TimeT> 
+    (std::chrono::system_clock::now() - start);
+  auto elapsed = duration.count();
+  std::cout << "Classification took " << elapsed << " ms\n";
+
+  auto confWriter = otb::ImageFileWriter<ClassificationFilterType::ConfidenceImageType>::New();
+  confWriter->SetInput(filter->GetOutputConfidence());
+  confWriter->SetFileName(conffname);
+  confWriter->Update();
+
+  return EXIT_SUCCESS;
+}
diff --git a/Modules/Learning/Supervised/test/otbSupervisedTestDriver.cxx b/Modules/Learning/Supervised/test/otbSupervisedTestDriver.cxx
index 2bf373c87f9f0579df333951b83ae818739d25c2..9bc337bf9d6e450ac07864cee6b8ce559f10ad3f 100644
--- a/Modules/Learning/Supervised/test/otbSupervisedTestDriver.cxx
+++ b/Modules/Learning/Supervised/test/otbSupervisedTestDriver.cxx
@@ -55,8 +55,15 @@ void RegisterTests()
   REGISTER_TEST(otbGradientBoostedTreeRegressionTests);
   REGISTER_TEST(otbKNearestNeighborsRegressionTests);
   REGISTER_TEST(otbRandomForestsRegressionTests);
+#endif  
+
+#ifdef OTB_USE_SHARK
+  REGISTER_TEST(otbSharkRFMachineLearningModelNew);
+  REGISTER_TEST(otbSharkRFMachineLearningModel);
+  REGISTER_TEST(otbSharkRFMachineLearningModelCanRead);
+  REGISTER_TEST(otbSharkImageClassificationFilter);
 #endif
   
-    REGISTER_TEST(otbImageClassificationFilterNew);
+  REGISTER_TEST(otbImageClassificationFilterNew);
   REGISTER_TEST(otbImageClassificationFilter);
 }
diff --git a/Modules/Learning/Supervised/test/otbTrainMachineLearningModel.cxx b/Modules/Learning/Supervised/test/otbTrainMachineLearningModel.cxx
index cb71ebab690d00ba219bad6b0c753691451ebe35..518a301e4e46a92b34f602e4c997f2e618f8b5d9 100644
--- a/Modules/Learning/Supervised/test/otbTrainMachineLearningModel.cxx
+++ b/Modules/Learning/Supervised/test/otbTrainMachineLearningModel.cxx
@@ -1035,3 +1035,255 @@ int otbGradientBoostedTreeMachineLearningModel(int argc, char * argv[])
     }
 }
 #endif
+
+#ifdef OTB_USE_SHARK
+#include <chrono> // If shark is on, then we are using c++11
+
+bool SharkReadDataFile(const std::string & infname, InputListSampleType * samples, TargetListSampleType * labels)
+{
+  std::ifstream ifs(infname.c_str());
+
+  if(!ifs)
+    {
+    std::cout<<"Could not read file "<<infname<<std::endl;
+    return false;
+    }
+
+  unsigned int nbfeatures = 0;
+
+  std::string line;
+  while (std::getline(ifs, line))
+    {
+    boost::algorithm::trim(line);
+
+    if(nbfeatures == 0)
+      {
+      nbfeatures = std::count(line.begin(),line.end(),' ');
+      }
+
+    if(line.size()>1)
+      {
+      InputSampleType sample(nbfeatures);
+      sample.Fill(0);
+
+      std::string::size_type pos = line.find_first_of(" ", 0);
+
+      // Parse label
+      TargetSampleType label;
+      label[0] = std::stoi(line.substr(0, pos).c_str());
+
+      bool endOfLine = false;
+      unsigned int id = 0;
+
+      while(!endOfLine)
+        {
+        std::string::size_type nextpos = line.find_first_of(" ", pos+1);
+
+        if(pos == std::string::npos)
+          {
+          endOfLine = true;
+          nextpos = line.size()-1;
+          }
+        else
+          {
+          std::string feature = line.substr(pos,nextpos-pos);
+          std::string::size_type semicolonpos = feature.find_first_of(":");
+          id = std::stoi(feature.substr(0,semicolonpos).c_str());
+          sample[id - 1] = atof(feature.substr(semicolonpos+1,feature.size()-semicolonpos).c_str());
+          pos = nextpos;
+          }
+
+        }
+      samples->SetMeasurementVectorSize(itk::NumericTraits<InputSampleType>::GetLength(sample));
+      samples->PushBack(sample);
+      labels->PushBack(label);
+      }
+    }
+
+  //std::cout<<"Retrieved "<<samples->Size()<<" samples"<<std::endl;
+  ifs.close();
+  return true;
+}
+
+bool SharkReadDataRegressionFile(const std::string & infname, InputListSampleRegressionType * samples, TargetListSampleRegressionType * labels)
+{
+  std::ifstream ifs(infname.c_str());
+  if(!ifs)
+    {
+    std::cout<<"Could not read file "<<infname<<std::endl;
+    return false;
+    }
+
+  unsigned int nbfeatures = 0;
+
+  while (!ifs.eof())
+    {
+    std::string line;
+    std::getline(ifs, line);
+
+    if(nbfeatures == 0)
+      {
+      nbfeatures = std::count(line.begin(),line.end(),' ')-1;
+      //std::cout<<"Found "<<nbfeatures<<" features per samples"<<std::endl;
+      }
+
+    if(line.size()>1)
+      {
+      InputSampleRegressionType sample(nbfeatures);
+      sample.Fill(0);
+
+      std::string::size_type pos = line.find_first_of(" ", 0);
+
+      // Parse label
+      TargetSampleRegressionType label;
+      label[0] = atof(line.substr(0, pos).c_str());
+
+      bool endOfLine = false;
+      unsigned int id = 0;
+
+      while(!endOfLine)
+        {
+        std::string::size_type nextpos = line.find_first_of(" ", pos+1);
+
+        if(nextpos == std::string::npos)
+          {
+          endOfLine = true;
+          nextpos = line.size()-1;
+          }
+        else
+          {
+          std::string feature = line.substr(pos,nextpos-pos);
+          std::string::size_type semicolonpos = feature.find_first_of(":");
+          id = std::stoi(feature.substr(0,semicolonpos).c_str());
+          sample[id - 1] = atof(feature.substr(semicolonpos+1,feature.size()-semicolonpos).c_str());
+          pos = nextpos;
+          }
+
+        }
+      samples->SetMeasurementVectorSize(itk::NumericTraits<InputSampleRegressionType>::GetLength(sample));
+      samples->PushBack(sample);
+      labels->PushBack(label);
+      }
+    }
+
+  //std::cout<<"Retrieved "<<samples->Size()<<" samples"<<std::endl;
+  ifs.close();
+  return true;
+}
+
+
+#include "otbSharkRandomForestsMachineLearningModel.h"
+int otbSharkRFMachineLearningModelNew(int itkNotUsed(argc), char * itkNotUsed(argv) [])
+{
+  typedef otb::SharkRandomForestsMachineLearningModel<InputValueType,TargetValueType> SharkRFType;
+  SharkRFType::Pointer classifier = SharkRFType::New();
+  return EXIT_SUCCESS;
+}
+
+int otbSharkRFMachineLearningModel(int argc, char * argv[])
+{
+  if (argc != 3 )
+    {
+    std::cout<<"Wrong number of arguments "<<std::endl;
+    std::cout<<"Usage : sample file, output file "<<std::endl;
+    return EXIT_FAILURE;
+    }
+
+  typedef otb::SharkRandomForestsMachineLearningModel<InputValueType,TargetValueType> RandomForestType;
+  InputListSampleType::Pointer samples = InputListSampleType::New();
+  TargetListSampleType::Pointer labels = TargetListSampleType::New();
+  TargetListSampleType::Pointer predicted = TargetListSampleType::New();
+
+  if(!SharkReadDataFile(argv[1],samples,labels))
+    {
+    std::cout<<"Failed to read samples file "<<argv[1]<<std::endl;
+    return EXIT_FAILURE;
+    }
+
+
+  RandomForestType::Pointer classifier = RandomForestType::New();
+  classifier->SetInputListSample(samples);
+  classifier->SetTargetListSample(labels);
+  classifier->SetRegressionMode(false);
+  classifier->SetNumberOfTrees(100);
+  classifier->SetMTry(0);
+  classifier->SetNodeSize(25);
+  classifier->SetOobRatio(0.3);
+  std::cout << "Train\n";
+  classifier->Train();
+  std::cout << "Save\n";
+  classifier->Save(argv[2]); 
+  
+  std::cout << "Predict\n";
+  classifier->SetTargetListSample(predicted);
+  classifier->PredictAll();
+
+  ConfusionMatrixCalculatorType::Pointer cmCalculator = ConfusionMatrixCalculatorType::New();
+
+  cmCalculator->SetProducedLabels(predicted);
+  cmCalculator->SetReferenceLabels(labels);
+  cmCalculator->Compute();
+
+  std::cout<<"Confusion matrix: "<<std::endl;
+  std::cout<<cmCalculator->GetConfusionMatrix()<<std::endl;
+  const float kappaIdx = cmCalculator->GetKappaIndex();
+  std::cout<<"Kappa: "<<kappaIdx<<std::endl;
+  std::cout<<"Overall Accuracy: "<<cmCalculator->GetOverallAccuracy()<<std::endl;
+  
+  // //Predict single samples. Written for benchmarking purposes, but
+  // too long for regression testing
+  // std::cout << "Predict single samples\n";
+  // auto sIt = samples->Begin();
+  // auto lIt = labels->Begin();
+  // auto start = std::chrono::system_clock::now();
+  // for(; sIt != samples->End(); ++sIt, ++lIt)
+  //   {
+  //   classifier->Predict(sIt.GetMeasurementVector())[0];
+  //   }
+  // auto duration = std::chrono::duration_cast< TimeT> 
+  //   (std::chrono::system_clock::now() - start);
+  // auto elapsed = duration.count();
+  // std::cout << "Predict took " << elapsed << " ms\n";
+  //  std::cout << "Single sample OA = " << oa << '\n';
+//Load Model to new RF
+  TargetListSampleType::Pointer predictedLoad = TargetListSampleType::New();
+  RandomForestType::Pointer classifierLoad = RandomForestType::New();
+
+  std::cout << "Load\n";
+  classifierLoad->Load(argv[2]);
+  auto start = std::chrono::system_clock::now();
+  classifierLoad->SetInputListSample(samples);
+  classifierLoad->SetTargetListSample(predictedLoad);
+  std::cout << "Predict loaded\n";
+  classifierLoad->PredictAll();
+  using TimeT = std::chrono::milliseconds;
+  auto duration = std::chrono::duration_cast< TimeT> 
+    (std::chrono::system_clock::now() - start);
+  auto elapsed = duration.count();
+  std::cout << "PredictAll took " << elapsed << " ms\n";
+  ConfusionMatrixCalculatorType::Pointer cmCalculatorLoad = ConfusionMatrixCalculatorType::New();
+
+   cmCalculatorLoad->SetProducedLabels(predictedLoad);
+   cmCalculatorLoad->SetReferenceLabels(labels);
+   cmCalculatorLoad->Compute();
+
+   std::cout<<"Confusion matrix: "<<std::endl;
+   std::cout<<cmCalculatorLoad->GetConfusionMatrix()<<std::endl;
+   const float kappaIdxLoad = cmCalculatorLoad->GetKappaIndex();
+   std::cout<<"Kappa: "<<kappaIdxLoad<<std::endl;
+   std::cout<<"Overall Accuracy: "<<cmCalculatorLoad->GetOverallAccuracy()<<std::endl;
+
+
+   if ( vcl_abs(kappaIdxLoad - kappaIdx) < 0.00000001)
+     {
+     return EXIT_SUCCESS;
+     }
+   else
+     {
+     return EXIT_FAILURE;
+     }
+  
+   return EXIT_SUCCESS;
+}
+
+#endif
diff --git a/Modules/Learning/Supervised/test/tests-shark.cmake b/Modules/Learning/Supervised/test/tests-shark.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..bd4ffdf056395c61e629d6545592108d8a517877
--- /dev/null
+++ b/Modules/Learning/Supervised/test/tests-shark.cmake
@@ -0,0 +1,61 @@
+otb_add_test(NAME leTuSharkRFMachineLearningModelNew COMMAND otbSupervisedTestDriver
+  otbSharkRFMachineLearningModelNew)
+
+otb_add_test(NAME leTvSharkRFMachineLearningModel COMMAND otbSupervisedTestDriver
+  otbSharkRFMachineLearningModel
+  ${INPUTDATA}/letter.scale
+  ${TEMP}/shark_rf_model.txt
+  )
+
+otb_add_test(NAME leTuSharkRFMachineLearningModelCanRead COMMAND otbSupervisedTestDriver
+  otbSharkRFMachineLearningModelCanRead
+  ${INPUTDATA}/Classification/otbSharkImageClassificationFilter_RFmodel.txt
+  )
+
+otb_add_test(NAME leTuSharkRFMachineLearningModelCanReadFail COMMAND otbSupervisedTestDriver
+  otbSharkRFMachineLearningModelCanRead
+  ${INPUTDATA}/ROI_QB_MUL_4_svmModel.txt
+  )
+set_property(TEST leTuSharkRFMachineLearningModelCanReadFail PROPERTY WILL_FAIL true)
+
+
+otb_add_test(NAME leTvImageClassificationFilterSharkFast COMMAND  otbSupervisedTestDriver
+  --compare-n-images ${NOTOL} 2 
+  ${BASELINE}/leSharkImageClassificationFilterOutput.tif
+  ${TEMP}/leSharkImageClassificationFilterOutput.tif
+  ${BASELINE}/leSharkImageClassificationFilterConfidence.tif
+  ${TEMP}/leSharkImageClassificationFilterConfidence.tif   
+  otbSharkImageClassificationFilter
+  ${INPUTDATA}/Classification/QB_1_ortho.tif
+  ${TEMP}/leSharkImageClassificationFilterOutput.tif
+  ${TEMP}/leSharkImageClassificationFilterConfidence.tif
+  1
+  ${INPUTDATA}/Classification/otbSharkImageClassificationFilter_RFmodel.txt
+  )
+
+# This test has been added for benchmarking purposes. However, it is
+# far too long to be part of regression testing
+
+# otb_add_test(NAME leTvImageClassificationFilterSharkClassic COMMAND  otbSupervisedTestDriver
+#   otbSharkImageClassificationFilter
+#   ${INPUTDATA}/Classification/QB_1_ortho.tif
+#   ${TEMP}/leSharkImageClassificationFilterOutput.tif
+#   ${TEMP}/leSharkImageClassificationFilterConfidence.tif
+#   0
+#   ${INPUTDATA}/Classification/otbSharkImageClassificationFilter_RFmodel.txt
+#   )
+
+otb_add_test(NAME leTvImageClassificationFilterSharkFastMask COMMAND  otbSupervisedTestDriver
+  --compare-n-images ${NOTOL} 2 
+  ${BASELINE}/leSharkImageClassificationFilterWithMaskOutput.tif
+  ${TEMP}/leSharkImageClassificationFilterWithMaskOutput.tif
+  ${BASELINE}/leSharkImageClassificationFilterWithMaskConfidence.tif
+  ${TEMP}/leSharkImageClassificationFilterWithMaskConfidence.tif   
+  otbSharkImageClassificationFilter
+  ${INPUTDATA}/Classification/QB_1_ortho.tif
+  ${TEMP}/leSharkImageClassificationFilterWithMaskOutput.tif
+  ${TEMP}/leSharkImageClassificationFilterWithMaskConfidence.tif
+  1
+  ${INPUTDATA}/Classification/otbSharkImageClassificationFilter_RFmodel.txt
+  ${INPUTDATA}/Classification/QB_1_ortho_mask.tif
+  )
diff --git a/Modules/Radiometry/OpticalCalibration/test/CMakeLists.txt b/Modules/Radiometry/OpticalCalibration/test/CMakeLists.txt
index 37a1086bfd7f901d84e534de1b189b07aaedc160..366591f3a37f5bbf86af585042919e527350b382 100644
--- a/Modules/Radiometry/OpticalCalibration/test/CMakeLists.txt
+++ b/Modules/Radiometry/OpticalCalibration/test/CMakeLists.txt
@@ -43,6 +43,15 @@ add_executable(otbOpticalCalibrationTestDriver ${OTBOpticalCalibrationTests})
 target_link_libraries(otbOpticalCalibrationTestDriver ${OTBOpticalCalibration-Test_LIBRARIES})
 otb_module_target_label(otbOpticalCalibrationTestDriver)
 
+# Since CMake 2.8.11, the size of the stack is not modified by CMake on
+# windows platform, it uses the default size: with visual compiler it is 1Mbyte
+# which is to lower for us (thanks to 6S code).
+if(MSVC)
+  set_target_properties(otbOpticalCalibrationTestDriver PROPERTIES LINK_FLAGS "/STACK:10000000")
+elseif(MINGW)
+  set_target_properties(otbOpticalCalibrationTestDriver PROPERTIES LINK_FLAGS "-Wl,--stack,10000000")
+endif()
+
 # Tests Declaration
 
 otb_add_test(NAME raTuSpectralSensitivityReaderNew COMMAND otbOpticalCalibrationTestDriver
diff --git a/Modules/ThirdParty/Shark/CMakeLists.txt b/Modules/ThirdParty/Shark/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c6e4bcb6178cee28ceaebe781979d79506159656
--- /dev/null
+++ b/Modules/ThirdParty/Shark/CMakeLists.txt
@@ -0,0 +1,6 @@
+project(OTBShark)
+
+set(OTBShark_SYSTEM_INCLUDE_DIRS ${SHARK_INCLUDE_DIRS})
+set(OTBShark_LIBRARIES "${SHARK_LIBRARY_DIRS}/libshark.so" "-lboost_serialization")
+
+otb_module_impl()
diff --git a/Modules/ThirdParty/Shark/otb-module-init.cmake b/Modules/ThirdParty/Shark/otb-module-init.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..ae75820b19b4ddc483115f56f14972b8d8998bd0
--- /dev/null
+++ b/Modules/ThirdParty/Shark/otb-module-init.cmake
@@ -0,0 +1,3 @@
+find_package ( Shark REQUIRED )
+
+mark_as_advanced( Shark_DIR )
diff --git a/Modules/ThirdParty/Shark/otb-module.cmake b/Modules/ThirdParty/Shark/otb-module.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..5e01d966b45efd3e57381f4bae065560b0b10ba9
--- /dev/null
+++ b/Modules/ThirdParty/Shark/otb-module.cmake
@@ -0,0 +1,16 @@
+set(DOCUMENTATION "This module imports SHARK to the build system")
+
+otb_module(OTBShark
+  DEPENDS
+    
+  TEST_DEPENDS
+    
+  DESCRIPTION
+    "${DOCUMENTATION}"
+  )
+
+otb_module_activation_option("Enable SHARK dependent modules" OFF)
+
+if( OTB_USE_SHARK )
+  otb_module_requires_cxx11()
+endif()
diff --git a/SuperBuild/CMake/External_otb.cmake b/SuperBuild/CMake/External_otb.cmake
index 80876e74daadce0fb7f5aecc285860cf366fd725..b460bac4ac0e5054b65bf0b756de8fde967ade7b 100644
--- a/SuperBuild/CMake/External_otb.cmake
+++ b/SuperBuild/CMake/External_otb.cmake
@@ -42,6 +42,10 @@ if(OTB_USE_OPENCV)
   ADD_SUPERBUILD_CMAKE_VAR(OTB OpenCV_DIR)
 endif()
 
+if(OTB_USE_SHARK)
+  ADDTO_DEPENDENCIES_IF_NOT_SYSTEM(OTB SHARK)
+endif()
+
 if(OTB_USE_LIBSVM)
   ADDTO_DEPENDENCIES_IF_NOT_SYSTEM(OTB LIBSVM)
   ADD_SUPERBUILD_CMAKE_VAR(OTB LIBSVM_INCLUDE_DIR)
@@ -113,6 +117,26 @@ ADD_SUPERBUILD_CMAKE_VAR(OTB TINYXML_LIBRARY)
 ADD_SUPERBUILD_CMAKE_VAR(OTB Boost_INCLUDE_DIR)
 ADD_SUPERBUILD_CMAKE_VAR(OTB Boost_LIBRARY_DIR)
 
+ADD_SUPERBUILD_CMAKE_VAR(OTB LIBKML_INCLUDE_DIR)
+ADD_SUPERBUILD_CMAKE_VAR(OTB LIBKML_BASE_LIBRARY)
+ADD_SUPERBUILD_CMAKE_VAR(OTB LIBKML_CONVENIENCE_LIBRARY)
+ADD_SUPERBUILD_CMAKE_VAR(OTB LIBKML_DOM_LIBRARY)
+ADD_SUPERBUILD_CMAKE_VAR(OTB LIBKML_ENGINE_LIBRARY)
+ADD_SUPERBUILD_CMAKE_VAR(OTB LIBKML_REGIONATOR_LIBRARY)
+ADD_SUPERBUILD_CMAKE_VAR(OTB LIBKML_XSD_LIBRARY)
+ADD_SUPERBUILD_CMAKE_VAR(OTB LIBKML_MINIZIP_LIBRARY)
+
+ADD_SUPERBUILD_CMAKE_VAR(OTB OpenCV_DIR)
+ADD_SUPERBUILD_CMAKE_VAR(OTB Shark_DIR)
+
+ADD_SUPERBUILD_CMAKE_VAR(OTB LIBSVM_INCLUDE_DIR)
+ADD_SUPERBUILD_CMAKE_VAR(OTB LIBSVM_LIBRARY)
+
+if(OTB_USE_CURL)
+ADD_SUPERBUILD_CMAKE_VAR(OTB CURL_INCLUDE_DIR)
+ADD_SUPERBUILD_CMAKE_VAR(OTB CURL_LIBRARY)
+endif()
+
 if(MSVC)
   ADD_SUPERBUILD_CMAKE_VAR(OTB JPEG_LIBRARY)
 endif()
@@ -163,6 +187,7 @@ ExternalProject_Add(OTB
   -DOTB_USE_MUPARSER:BOOL=${OTB_USE_MUPARSER}
   -DOTB_USE_MUPARSERX:BOOL=${OTB_USE_MUPARSERX}
   -DOTB_USE_OPENCV:BOOL=${OTB_USE_OPENCV}
+  -DOTB_USE_SHARK:BOOL=${OTB_USE_SHARK}
   -DOTB_USE_OPENJPEG:BOOL=OFF
   -DOTB_USE_QT4:BOOL=${OTB_USE_QT4}
   -DOTB_USE_SIFTFAST:BOOL=${OTB_USE_SIFTFAST}
@@ -173,14 +198,15 @@ ExternalProject_Add(OTB
   -DOTB_USE_QWT:BOOL=${OTB_USE_QWT}
   -DOTB_WRAP_PYTHON:BOOL=${OTB_WRAP_PYTHON}
   -DOTB_WRAP_JAVA:BOOL=${OTB_WRAP_JAVA}
-  ${OTB_SB_CONFIG}
-  ${OTB_SB_LARGEINPUT_CONFIG}
   -DGENERATE_PACKAGE:BOOL=OFF
   -DGENERATE_XDK:BOOL=OFF
+  ${OTB_SB_CONFIG}
+  ${OTB_SB_LARGEINPUT_CONFIG}
   ${OTB_ADDITIONAL_CACHE}
   CMAKE_COMMAND ${SB_CMAKE_COMMAND}
   )
 
+
 ExternalProject_Add_Step(OTB install_copyright
   COMMAND ${CMAKE_COMMAND} -E copy_directory ${OTB_SB_SRC}/Copyright ${CMAKE_INSTALL_PREFIX}/share/copyright
   COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/Copyright ${CMAKE_INSTALL_PREFIX}/share/copyright
diff --git a/SuperBuild/CMake/External_shark.cmake b/SuperBuild/CMake/External_shark.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..a360f876af4b1d73d629b73fa9f664c4b5311523
--- /dev/null
+++ b/SuperBuild/CMake/External_shark.cmake
@@ -0,0 +1,38 @@
+if(NOT __EXTERNAL_SHARK__)
+set(__EXTERNAL_SHARK__ 1)
+
+if(USE_SYSTEM_SHARK)
+  message(STATUS "  Using SHARK system version")
+else()
+  SETUP_SUPERBUILD(PROJECT SHARK)
+  cmake_minimum_required(VERSION 3.1)
+  message(STATUS "  Using SHARK SuperBuild version")
+
+  # declare dependencies
+  ADDTO_DEPENDENCIES_IF_NOT_SYSTEM(SHARK BOOST)
+
+  ADD_SUPERBUILD_CMAKE_VAR(SHARK Boost_INCLUDE_DIR)
+  ADD_SUPERBUILD_CMAKE_VAR(SHARK Boost_LIBRARY_DIR)
+
+  ExternalProject_Add(SHARK
+    PREFIX SHARK
+    GIT_REPOSITORY "https://github.com/Shark-ML/Shark/"
+    GIT_TAG "master"
+    SOURCE_DIR ${SHARK_SB_SRC}
+    BINARY_DIR ${SHARK_SB_BUILD_DIR}
+    INSTALL_DIR ${SB_INSTALL_PREFIX}
+    DOWNLOAD_DIR ${DOWNLOAD_LOCATION}
+    CMAKE_CACHE_ARGS
+      -DCMAKE_INSTALL_PREFIX:STRING=${SB_INSTALL_PREFIX}
+      -DCMAKE_PREFIX_PATH:STRING=${SB_INSTALL_PREFIX};${CMAKE_PREFIX_PATH}
+      -DCMAKE_BUILD_TYPE:STRING=Release
+      -DBUILD_SHARED_LIBS:BOOL=ON
+      -DBUILD_DOCS:BOOL=OFF
+      -DBUILD_EXAMPLES:BOOL=OFF
+      -DBUILD_TESTING:BOOL=OFF
+      -DENABLE_HDF5:BOOL=OFF
+      CMAKE_COMMAND ${SB_CMAKE_COMMAND}
+    )
+  set(_SB_SHARK_DIR ${SB_INSTALL_PREFIX}/share/SHARK)
+endif()
+endif()
diff --git a/SuperBuild/CMakeLists.txt b/SuperBuild/CMakeLists.txt
index 7056f8763d46d65639d2411f21770ad27e8ea25b..2f0955c16f3630b3bc88f539415a43cb33921030 100644
--- a/SuperBuild/CMakeLists.txt
+++ b/SuperBuild/CMakeLists.txt
@@ -232,6 +232,8 @@ option(USE_SYSTEM_GLEW  "Use a system build of GLEW" OFF)
 option(USE_SYSTEM_GLFW  "Use a system build of glfw" OFF)
 option(USE_SYSTEM_GLUT  "Use a system build of glut" OFF)
 option(USE_SYSTEM_FREETYPE "Use a system build of freetype" OFF)
+option(USE_SYSTEM_SHARK "Use a system build of Shark" OFF)
+
 
 # Call OTB
 option(OTB_USE_6S "Enable module 6S in OTB" ON)
@@ -253,6 +255,7 @@ option(OTB_USE_OPENGL "Enable module OpenGL in OTB" OFF)
 option(OTB_USE_GLEW "Enable module GLEW in OTB" OFF)
 option(OTB_USE_GLFW "Enable module GLFW in OTB" OFF)
 option(OTB_USE_GLUT "Enable module GLUT in OTB" OFF)
+option(OTB_USE_SHARK "Enable module Shark in OTB" OFF)
 option(OTB_USE_QWT "Enable module QWT in OTB" OFF)
 
 #Problem: below cmake setting will fail!
@@ -320,4 +323,5 @@ if(FROM_SUPERBUILD_LIST)
 endif()
 
 message(STATUS "SuperBuild will be installed to ${CMAKE_INSTALL_PREFIX}")
-message(STATUS "To install to a different directory, re-run cmake -DCMAKE_INSTALL_PREFIX=/your/preferred/path")
\ No newline at end of file
+message(STATUS "To install to a different directory, re-run cmake -DCMAKE_INSTALL_PREFIX=/your/preferred/path")
+
diff --git a/SuperBuild/patches/SHARK/shark-1-disable-hdf5-linux.diff b/SuperBuild/patches/SHARK/shark-1-disable-hdf5-linux.diff
new file mode 100644
index 0000000000000000000000000000000000000000..d0b3df4d7f8355a0da6f4a26ff4d0c4187bca1df
--- /dev/null
+++ b/SuperBuild/patches/SHARK/shark-1-disable-hdf5-linux.diff
@@ -0,0 +1,258 @@
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index df8be65..c6c3020 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -191,29 +191,32 @@ endif()
+ #####################################################################
+ #           HDF5 configuration
+ #####################################################################
+-find_package(HDF5 COMPONENTS C CXX HL QUIET)
+-mark_as_advanced(HDF5_DIR)
+-if(HDF5_FOUND)
+-	if(HDF5_C_COMPILER_EXECUTABLE AND HDF5_CXX_COMPILER_EXECUTABLE)
+-		message(STATUS "Checking HDF5 installation: HDF5 installation seems ok.")
+-		include_directories( ${HDF5_INCLUDE_DIR} )
+-		link_directories( ${HDF5_LIBRARY_DIR} )
+-		list(APPEND LINK_LIBRARIES ${HDF5_LIBRARIES})
+-	else()
+-		message(STATUS "Checking HDF5 installation:HDF5 package might be broken.")
+-		if(NOT( HDF5_C_COMPILER_EXECUTABLE))
+-			message(STATUS "  C Compiler Extension not found.")
+-		endif()
+-		if(NOT( HDF5_CXX_COMPILER_EXECUTABLE))
+-			message(STATUS "  CXX Compiler Extension not found.")
+-		endif()
+-			message(STATUS "Disabling HDF5.")
+-		unset( HDF5_FOUND )
+-	endif()
+-else()
+-	message(STATUS "HDF5 not found, skip")
++option(ENABLE_HDF5 "Use HDF5" ON)
++
++if(ENABLE_HDF5)
++  find_package(HDF5 COMPONENTS C CXX HL QUIET)
++  mark_as_advanced(HDF5_DIR)
++  if(HDF5_FOUND)
++    if(HDF5_C_COMPILER_EXECUTABLE AND HDF5_CXX_COMPILER_EXECUTABLE)
++      message(STATUS "Checking HDF5 installation: HDF5 installation seems ok.")
++      include_directories( ${HDF5_INCLUDE_DIR} )
++      link_directories( ${HDF5_LIBRARY_DIR} )
++      list(APPEND LINK_LIBRARIES ${HDF5_LIBRARIES})
++    else()
++      message(STATUS "Checking HDF5 installation:HDF5 package might be broken.")
++      if(NOT( HDF5_C_COMPILER_EXECUTABLE))
++        message(STATUS "  C Compiler Extension not found.")
++      endif()
++      if(NOT( HDF5_CXX_COMPILER_EXECUTABLE))
++        message(STATUS "  CXX Compiler Extension not found.")
++      endif()
++      message(STATUS "Disabling HDF5.")
++      unset( HDF5_FOUND )
++    endif()
++  else()
++    message(STATUS "HDF5 not found, skip")
++  endif()
+ endif()
+-
+ #####################################################################
+ #           ATLAS configuration
+ #####################################################################
+@@ -222,104 +225,104 @@ endif()
+ option( ENABLE_CBLAS "Use Installed Linear Algebra Library" ON )
+ 
+ if( ENABLE_CBLAS )
+-	set(CBLAS_VENDOR FALSE)
+-	if( APPLE )
+-		set(CBLAS_VENDOR "Accelerate")
+-		set(CBLAS_INCLUDES "")
+-		set(CBLAS_LIBRARIES "-framework Accelerate" )
+-	else()
+-		#todo: do a propper vendor check
+-		find_library(OPENBLAS_LIBRARY openblas
+-			HINTS ${CBLAS_ROOT}/lib /opt/local/lib
+-		)
+-		find_library(CBLAS_LIBRARY cblas
+-			HINTS ${ATLAS_ROOT}/lib ${CBLAS_ROOT}/lib /opt/local/lib /usr/lib64/atlas/
+-		)
+-		find_library(CLAPACK_LIBRARY lapack
+-			HINTS ${ATLAS_ROOT}/lib ${CBLAS_ROOT}/lib /opt/local/lib /usr/lib64/atlas/
+-		)
+-		find_library(ATLAS_LIBRARY atlas
+-			HINTS ${ATLAS_ROOT}/lib ${CBLAS_ROOT}/lib /opt/local/lib /usr/lib64/atlas/
+-		)
+-		mark_as_advanced(
+-			OPENBLAS_LIBRARY
+-			CBLAS_LIBRARY
+-			CLAPACK_LIBRARY
+-			ATLAS_LIBRARY
+-		)
+-		#find the cblas.h include path
+-		if(CBLAS_LIBRARY )
+-			get_filename_component(CBLAS_LIB_PATH ${CBLAS_LIBRARY} PATH )
+-		elseif( OPENBLAS_LIBRARY)	
+-			get_filename_component(CBLAS_LIB_PATH ${OPENBLAS_LIBRARY} PATH )
+-		endif()
+-		if(CBLAS_LIB_PATH)
+-			find_file(CBLAS_INCLUDES cblas.h 
+-				PATHS ${CBLAS_LIB_PATH} ${CBLAS_LIB_PATH}/../include
+-			)
+-			get_filename_component(CBLAS_INCLUDES ${CBLAS_INCLUDES} PATH )
+-		endif()
+-		if(ATLAS_LIBRARY)
+-			get_filename_component(ATLAS_LIBRARY_PATH ${ATLAS_LIBRARY} PATH )
+-			find_file(CLAPACK_INCLUDES clapack.h 
+-				PATHS
+-				${ATLAS_LIBRARY_PATH} 
+-				${ATLAS_LIBRARY_PATH}/../include
+-				${ATLAS_LIBRARY_PATH}/../include/atlas
+-				${ATLAS_LIBRARY_PATH}/../../include/atlas
+-			)
+-			get_filename_component(CLAPACK_INCLUDES ${CLAPACK_INCLUDES} PATH )
+-			set(CBLAS_INCLUDES ${CBLAS_INCLUDES} ${CLAPACK_INCLUDES})
+-		endif()
+-
+-		if( OPENBLAS_LIBRARY AND CBLAS_INCLUDES)
+-			set(CBLAS_VENDOR "OpenBLAS")
+-			set(CBLAS_LIBRARIES ${OPENBLAS_LIBRARY})
+-		elseif( CBLAS_LIBRARY AND CLAPACK_LIBRARY AND ATLAS_LIBRARY AND CBLAS_INCLUDES)
+-			set(CBLAS_VENDOR "ATLAS")
+-			set(CBLAS_LIBRARIES ${CLAPACK_LIBRARY} ${CBLAS_LIBRARY} ${ATLAS_LIBRARY})
+-		elseif( CBLAS_LIBRARY AND CBLAS_INCLUDES)
+-			#check that we can compile a basic program with the libraries we have found
+-			#vendor versions might come with additional libraries which would be bad.
+-			try_compile(CBLAS_COMPILE 
+-				"${PROJECT_BINARY_DIR}/cBlasCheck"
+-				"${CMAKE_SOURCE_DIR}/cBlasCheck.cpp"
+-				CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${CBLAS_INCLUDES}"
+-				LINK_LIBRARIES ${CBLAS_LIBRARY}
+-			)
+-			if(CBLAS_COMPILE)
+-				set(CBLAS_VENDOR "GENERIC")
+-				set(CBLAS_LIBRARIES ${CBLAS_LIBRARY})
+-			else()
+-				message(WARNING "Unknown CBLAS. Can not use it")
+-			endif()
+-		endif()
+-	endif()
++  set(CBLAS_VENDOR FALSE)
++  if( APPLE )
++    set(CBLAS_VENDOR "Accelerate")
++    set(CBLAS_INCLUDES "")
++    set(CBLAS_LIBRARIES "-framework Accelerate" )
++  else()
++    #todo: do a propper vendor check
++    find_library(OPENBLAS_LIBRARY openblas
++      HINTS ${CBLAS_ROOT}/lib /opt/local/lib
++      )
++    find_library(CBLAS_LIBRARY cblas
++      HINTS ${ATLAS_ROOT}/lib ${CBLAS_ROOT}/lib /opt/local/lib /usr/lib64/atlas/
++      )
++    find_library(CLAPACK_LIBRARY lapack
++      HINTS ${ATLAS_ROOT}/lib ${CBLAS_ROOT}/lib /opt/local/lib /usr/lib64/atlas/
++      )
++    find_library(ATLAS_LIBRARY atlas
++      HINTS ${ATLAS_ROOT}/lib ${CBLAS_ROOT}/lib /opt/local/lib /usr/lib64/atlas/
++      )
++    mark_as_advanced(
++      OPENBLAS_LIBRARY
++      CBLAS_LIBRARY
++      CLAPACK_LIBRARY
++      ATLAS_LIBRARY
++      )
++    #find the cblas.h include path
++    if(CBLAS_LIBRARY )
++      get_filename_component(CBLAS_LIB_PATH ${CBLAS_LIBRARY} PATH )
++    elseif( OPENBLAS_LIBRARY)	
++      get_filename_component(CBLAS_LIB_PATH ${OPENBLAS_LIBRARY} PATH )
++    endif()
++    if(CBLAS_LIB_PATH)
++      find_file(CBLAS_INCLUDES cblas.h 
++	PATHS ${CBLAS_LIB_PATH} ${CBLAS_LIB_PATH}/../include
++	)
++      get_filename_component(CBLAS_INCLUDES ${CBLAS_INCLUDES} PATH )
++    endif()
++    if(ATLAS_LIBRARY)
++      get_filename_component(ATLAS_LIBRARY_PATH ${ATLAS_LIBRARY} PATH )
++      find_file(CLAPACK_INCLUDES clapack.h 
++	PATHS
++	${ATLAS_LIBRARY_PATH} 
++	${ATLAS_LIBRARY_PATH}/../include
++	${ATLAS_LIBRARY_PATH}/../include/atlas
++	${ATLAS_LIBRARY_PATH}/../../include/atlas
++	)
++      get_filename_component(CLAPACK_INCLUDES ${CLAPACK_INCLUDES} PATH )
++      set(CBLAS_INCLUDES ${CBLAS_INCLUDES} ${CLAPACK_INCLUDES})
++    endif()
++
++    if( OPENBLAS_LIBRARY AND CBLAS_INCLUDES)
++      set(CBLAS_VENDOR "OpenBLAS")
++      set(CBLAS_LIBRARIES ${OPENBLAS_LIBRARY})
++    elseif( CBLAS_LIBRARY AND CLAPACK_LIBRARY AND ATLAS_LIBRARY AND CBLAS_INCLUDES)
++      set(CBLAS_VENDOR "ATLAS")
++      set(CBLAS_LIBRARIES ${CLAPACK_LIBRARY} ${CBLAS_LIBRARY} ${ATLAS_LIBRARY})
++    elseif( CBLAS_LIBRARY AND CBLAS_INCLUDES)
++      #check that we can compile a basic program with the libraries we have found
++      #vendor versions might come with additional libraries which would be bad.
++      try_compile(CBLAS_COMPILE 
++	"${PROJECT_BINARY_DIR}/cBlasCheck"
++	"${CMAKE_SOURCE_DIR}/cBlasCheck.cpp"
++	CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${CBLAS_INCLUDES}"
++	LINK_LIBRARIES ${CBLAS_LIBRARY}
++	)
++      if(CBLAS_COMPILE)
++	set(CBLAS_VENDOR "GENERIC")
++	set(CBLAS_LIBRARIES ${CBLAS_LIBRARY})
++      else()
++	message(WARNING "Unknown CBLAS. Can not use it")
++      endif()
++    endif()
++  endif()
+ 	
+-	if(CBLAS_VENDOR)
+-		message(STATUS "CBLAS FOUND: " ${CBLAS_VENDOR} " with include directory " ${CBLAS_INCLUDES} )
+-		set(SHARK_USE_CBLAS 1)
+-		list(APPEND EXTRA_INCLUDE_DIRECTORIES ${CBLAS_INCLUDES} )
+-		list(APPEND LINK_LIBRARIES ${CBLAS_LIBRARIES})
+-		include_directories ( ${CBLAS_INCLUDES} )
+-	else()
+-		message(STATUS "No usable CBLAS Library found. No fast linear Algebra used.")
+-	endif()
++  if(CBLAS_VENDOR)
++    message(STATUS "CBLAS FOUND: " ${CBLAS_VENDOR} " with include directory " ${CBLAS_INCLUDES} )
++    set(SHARK_USE_CBLAS 1)
++    list(APPEND EXTRA_INCLUDE_DIRECTORIES ${CBLAS_INCLUDES} )
++    list(APPEND LINK_LIBRARIES ${CBLAS_LIBRARIES})
++    include_directories ( ${CBLAS_INCLUDES} )
++  else()
++    message(STATUS "No usable CBLAS Library found. No fast linear Algebra used.")
++  endif()
+ 	
+-	#Special setup for ATLAS
+-	if( CBLAS_VENDOR MATCHES "ATLAS" )
+-		set( SHARK_USE_ATLAS_LAPACK 1) # ATLAS always contains some LAPACK methods that we can use
++  #Special setup for ATLAS
++  if( CBLAS_VENDOR MATCHES "ATLAS" )
++    set( SHARK_USE_ATLAS_LAPACK 1) # ATLAS always contains some LAPACK methods that we can use
+ 		
+-		#check for full lapack
+-		set(CMAKE_REQUIRE_QUIET 1)
+-		set(CMAKE_REQUIRED_LIBRARIES ${CBLAS_LIBRARIES})
+-		check_function_exists(dsyev_ ATLAS_FULL_LAPACK)
++    #check for full lapack
++    set(CMAKE_REQUIRE_QUIET 1)
++    set(CMAKE_REQUIRED_LIBRARIES ${CBLAS_LIBRARIES})
++    check_function_exists(dsyev_ ATLAS_FULL_LAPACK)
+ 		
+-		if( ATLAS_FULL_LAPACK )
+-			set( SHARK_USE_LAPACK 1)
+-			message(STATUS "Detected ATLAS with full LAPACK package. Using it!")
+-		endif()
+-	endif()
++    if( ATLAS_FULL_LAPACK )
++      set( SHARK_USE_LAPACK 1)
++      message(STATUS "Detected ATLAS with full LAPACK package. Using it!")
++    endif()
++  endif()
+ endif()
+ #####################################################################
+ #                       Static Code Analysis
diff --git a/Utilities/Maintenance/fix_typos.sh b/Utilities/Maintenance/fix_typos.sh
index 0a4ebc4e7bc9cb2537b071a0776c5295cb410a0a..7e427029e156b8dba8c11d1671fa850a6d3485f6 100755
--- a/Utilities/Maintenance/fix_typos.sh
+++ b/Utilities/Maintenance/fix_typos.sh
@@ -73,6 +73,6 @@ WORDS_WHITE_LIST="$WORDS_WHITE_LIST,dum"
 # for pary variable
 WORDS_WHITE_LIST="$WORDS_WHITE_LIST,pary"
 
-python3 fix_typos/codespell/codespell.py codespell.py -w -i 3 -q 2 -S $EXCLUDED_FILES \
+python3 fix_typos/codespell/codespell.py -w -i 3 -q 2 -S $EXCLUDED_FILES \
         --words-white-list=$WORDS_WHITE_LIST \
         -D fix_typos/otb_dict.txt  ../..