diff --git a/include/otbCacheLessLabelImageToVectorData.h b/include/otbCacheLessLabelImageToVectorData.h
new file mode 100644
index 0000000000000000000000000000000000000000..d8fc339ed965780ce08cf6746025dc39aacca5c2
--- /dev/null
+++ b/include/otbCacheLessLabelImageToVectorData.h
@@ -0,0 +1,195 @@
+/*=========================================================================
+
+  Copyright (c) Remi Cresson (IRSTEA). All rights reserved.
+
+
+     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 MODULES_REMOTE_SIMPLEEXTRACTIONTOOLS_INCLUDE_OTBCACHELESSLABELIMAGETOVECTORDATA_H_
+#define MODULES_REMOTE_SIMPLEEXTRACTIONTOOLS_INCLUDE_OTBCACHELESSLABELIMAGETOVECTORDATA_H_
+
+#include "otbImage.h"
+#include "itkImageRegionIterator.h"
+#include "itkImageRegionConstIterator.h"
+#include "itkProcessObject.h"
+#include "otbStreamingManager.h"
+#include "otbLabelImageToVectorDataFilter.h"
+
+namespace otb
+{
+
+/** \class CacheLessLabelImageToVectorData
+ * \brief Produce a VectorData from an input pipeline. The pipeline is executed with
+ * explicit streaming and the resulting image is stored in the internal cache of the filter.
+ * This ensure that only the output image is cached, rather than all pipeline buffers.
+ *
+ * \ingroup SimpleExtractionTools
+ */
+template <class TInputImagePixel>
+class ITK_EXPORT CacheLessLabelImageToVectorData :
+    public VectorDataSource< otb::VectorData<double> >
+{
+public:
+  /** Standard class typedefs. */
+  typedef CacheLessLabelImageToVectorData                   Self;
+  typedef VectorDataSource< VectorData<double> >            Superclass;
+  typedef itk::SmartPointer<Self>                           Pointer;
+  typedef itk::SmartPointer<const Self>                     ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(CacheLessLabelImageToVectorData, VectorDataSource);
+
+  /** Some typedefs for the input. */
+  typedef typename otb::Image<TInputImagePixel, 2>        InputImageType;
+  typedef typename InputImageType::Pointer       InputImagePointer;
+  typedef typename InputImageType::RegionType    InputImageRegionType;
+  typedef typename InputImageType::PixelType     InputImagePixelType;
+  typedef typename InputImageType::IndexType     InputIndexType;
+  typedef itk::ImageRegionConstIterator<InputImageType> ConstIteratorType;
+  typedef itk::ImageRegionIterator<InputImageType>      IteratorType;
+
+  /** Definition of the output vector data. */
+  typedef VectorData<double>                     VectorDataType;
+  typedef typename VectorDataType::Pointer       VectorDataPointerType;
+
+  typedef LabelImageToVectorDataFilter<InputImageType, double> LabelImageToVectorDataFilterType;
+
+  /** Dimension of input image. */
+  itkStaticConstMacro(InputImageDimension, unsigned int,
+                      InputImageType::ImageDimension);
+
+  /** Streaming manager base class pointer */
+  typedef StreamingManager<InputImageType>       StreamingManagerType;
+  typedef typename StreamingManagerType::Pointer StreamingManagerPointerType;
+
+  /**  Return the StreamingManager object responsible for dividing
+   *   the region to write */
+  StreamingManagerType* GetStreamingManager(void)
+    {
+    return m_StreamingManager;
+    }
+
+  /**  Set a user-specified implementation of StreamingManager
+   *   used to divide the largest possible region in several divisions */
+  void SetStreamingManager(StreamingManagerType* streamingManager)
+    {
+    m_StreamingManager = streamingManager;
+    }
+
+  /**  Set the streaming mode to 'stripped' and configure the number of strips
+   *   which will be used to stream the image */
+  void SetNumberOfDivisionsStrippedStreaming(unsigned int nbDivisions);
+
+  /**  Set the streaming mode to 'tiled' and configure the number of tiles
+   *   which will be used to stream the image */
+  void SetNumberOfDivisionsTiledStreaming(unsigned int nbDivisions);
+
+  /**  Set the streaming mode to 'stripped' and configure the number of strips
+   *   which will be used to stream the image with respect to a number of line
+   *   per strip */
+  void SetNumberOfLinesStrippedStreaming(unsigned int nbLinesPerStrip);
+
+  /**  Set the streaming mode to 'stripped' and configure the number of MB
+   *   available. The actual number of divisions is computed automatically
+   *   by estimating the memory consumption of the pipeline.
+   *   Setting the availableRAM parameter to 0 means that the available RAM
+   *   is set from the CMake configuration option.
+   *   The bias parameter is a multiplier applied on the estimated memory size
+   *   of the pipeline and can be used to fine tune the potential gap between
+   *   estimated memory and actual memory used, which can happen because of
+   *   composite filters for example */
+  void SetAutomaticStrippedStreaming(unsigned int availableRAM = 0, double bias = 1.0);
+
+  /**  Set the streaming mode to 'tiled' and configure the dimension of the tiles
+   *   in pixels for each dimension (square tiles will be generated) */
+  void SetTileDimensionTiledStreaming(unsigned int tileDimension);
+
+  /**  Set the streaming mode to 'tiled' and configure the number of MB
+   *   available. The actual number of divisions is computed automatically
+   *   by estimating the memory consumption of the pipeline.
+   *   Tiles will be square.
+   *   Setting the availableRAM parameter to 0 means that the available RAM
+   *   is set from the CMake configuration option
+   *   The bias parameter is a multiplier applied on the estimated memory size
+   *   of the pipeline and can be used to fine tune the potential gap between
+   *   estimated memory and actual memory used, which can happen because of
+   *   composite filters for example */
+  void SetAutomaticTiledStreaming(unsigned int availableRAM = 0, double bias = 1.0);
+
+  /**  Set the streaming mode to 'adaptative' and configure the number of MB
+   *   available. The actual number of divisions is computed automatically
+   *   by estimating the memory consumption of the pipeline.
+   *   Tiles will try to match the input file tile scheme.
+   *   Setting the availableRAM parameter to 0 means that the available RAM
+   *   is set from the CMake configuration option */
+  void SetAutomaticAdaptativeStreaming(unsigned int availableRAM = 0, double bias = 1.0);
+
+  /** Set the only input of the writer */
+  using Superclass::SetInput;
+  virtual void SetInput(const InputImageType *input);
+
+  /** Get writer only input */
+  const InputImageType* GetInput();
+
+  /** Override Update() from ProcessObject because this filter
+   *  has no output. */
+  void Update() ITK_OVERRIDE;
+
+  void GenerateInputRequestedRegion() {};
+
+protected:
+  CacheLessLabelImageToVectorData();
+  ~CacheLessLabelImageToVectorData() ITK_OVERRIDE;
+
+private:
+  CacheLessLabelImageToVectorData(const CacheLessLabelImageToVectorData &); //purposely not implemented
+  void operator =(const CacheLessLabelImageToVectorData&); //purposely not implemented
+
+  void ObserveSourceFilterProgress(itk::Object* object, const itk::EventObject & event )
+  {
+    if (typeid(event) != typeid(itk::ProgressEvent))
+      {
+      return;
+      }
+
+    itk::ProcessObject* processObject = dynamic_cast<itk::ProcessObject*>(object);
+    if (processObject)
+      {
+      m_DivisionProgress = processObject->GetProgress();
+      }
+
+    this->UpdateFilterProgress();
+  }
+
+  void UpdateFilterProgress()
+  {
+    this->UpdateProgress( (m_DivisionProgress + m_CurrentDivision) / m_NumberOfDivisions );
+  }
+
+  unsigned int m_NumberOfDivisions;
+  unsigned int m_CurrentDivision;
+  float m_DivisionProgress;
+
+  StreamingManagerPointerType m_StreamingManager;
+
+  bool          m_IsObserving;
+  unsigned long m_ObserverID;
+
+  typename InputImageType::Pointer  bufferedInputImage;
+  typename LabelImageToVectorDataFilterType::Pointer vectorizeFilter;
+};
+
+} // end namespace otb
+
+#ifndef OTB_MANUAL_INSTANTIATION
+#include "otbCacheLessLabelImageToVectorData.txx"
+#endif
+
+#endif /* MODULES_REMOTE_SIMPLEEXTRACTIONTOOLS_INCLUDE_OTBCACHELESSLABELIMAGETOVECTORDATA_H_ */
diff --git a/include/otbCacheLessLabelImageToVectorData.txx b/include/otbCacheLessLabelImageToVectorData.txx
new file mode 100644
index 0000000000000000000000000000000000000000..1f95319cc8b1e635b603b8731d523873f43842c3
--- /dev/null
+++ b/include/otbCacheLessLabelImageToVectorData.txx
@@ -0,0 +1,307 @@
+/*=========================================================================
+
+  Copyright (c) Remi Cresson (IRSTEA). All rights reserved.
+
+
+     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 MODULES_REMOTE_SIMPLEEXTRACTIONTOOLS_INCLUDE_OTBCACHELESSLABELIMAGETOVECTORDATA_txx_
+#define MODULES_REMOTE_SIMPLEEXTRACTIONTOOLS_INCLUDE_OTBCACHELESSLABELIMAGETOVECTORDATA_txx_
+
+#include "otbCacheLessLabelImageToVectorData.h"
+
+#include "itkObjectFactoryBase.h"
+
+#include "itkImageRegionMultidimensionalSplitter.h"
+
+#include "itkImageRegionIterator.h"
+
+#include "otbNumberOfDivisionsStrippedStreamingManager.h"
+#include "otbNumberOfDivisionsTiledStreamingManager.h"
+#include "otbNumberOfLinesStrippedStreamingManager.h"
+#include "otbRAMDrivenStrippedStreamingManager.h"
+#include "otbTileDimensionTiledStreamingManager.h"
+#include "otbRAMDrivenTiledStreamingManager.h"
+#include "otbRAMDrivenAdaptativeStreamingManager.h"
+
+namespace otb
+{
+
+/**
+ *
+ */
+template <class TInputImagePixel>
+CacheLessLabelImageToVectorData<TInputImagePixel>
+::CacheLessLabelImageToVectorData()
+ : m_NumberOfDivisions(0),
+   m_CurrentDivision(0),
+   m_DivisionProgress(0.0),
+   m_IsObserving(true),
+   m_ObserverID(0)
+   {
+
+  // By default, we use tiled streaming, with automatic tile size
+  // We don't set any parameter, so the memory size is retrieved from the OTB configuration options
+  this->SetAutomaticAdaptativeStreaming();
+   }
+
+/**
+ *
+ */
+template <class TInputImagePixel>
+CacheLessLabelImageToVectorData<TInputImagePixel>
+::~CacheLessLabelImageToVectorData()
+{
+}
+
+template <class TInputImagePixel>
+void
+CacheLessLabelImageToVectorData<TInputImagePixel>
+::SetNumberOfDivisionsStrippedStreaming(unsigned int nbDivisions)
+ {
+  typedef NumberOfDivisionsStrippedStreamingManager<InputImageType> NumberOfDivisionsStrippedStreamingManagerType;
+  typename NumberOfDivisionsStrippedStreamingManagerType::Pointer streamingManager = NumberOfDivisionsStrippedStreamingManagerType::New();
+  streamingManager->SetNumberOfDivisions(nbDivisions);
+
+  m_StreamingManager = streamingManager;
+ }
+
+template <class TInputImagePixel>
+void
+CacheLessLabelImageToVectorData<TInputImagePixel>
+::SetNumberOfDivisionsTiledStreaming(unsigned int nbDivisions)
+ {
+  typedef NumberOfDivisionsTiledStreamingManager<InputImageType> NumberOfDivisionsTiledStreamingManagerType;
+  typename NumberOfDivisionsTiledStreamingManagerType::Pointer streamingManager = NumberOfDivisionsTiledStreamingManagerType::New();
+  streamingManager->SetNumberOfDivisions(nbDivisions);
+
+  m_StreamingManager = streamingManager;
+ }
+
+template <class TInputImagePixel>
+void
+CacheLessLabelImageToVectorData<TInputImagePixel>
+::SetNumberOfLinesStrippedStreaming(unsigned int nbLinesPerStrip)
+ {
+  typedef NumberOfLinesStrippedStreamingManager<InputImageType> NumberOfLinesStrippedStreamingManagerType;
+  typename NumberOfLinesStrippedStreamingManagerType::Pointer streamingManager = NumberOfLinesStrippedStreamingManagerType::New();
+  streamingManager->SetNumberOfLinesPerStrip(nbLinesPerStrip);
+
+  m_StreamingManager = streamingManager;
+ }
+
+template <class TInputImagePixel>
+void
+CacheLessLabelImageToVectorData<TInputImagePixel>
+::SetAutomaticStrippedStreaming(unsigned int availableRAM, double bias)
+ {
+  typedef RAMDrivenStrippedStreamingManager<InputImageType> RAMDrivenStrippedStreamingManagerType;
+  typename RAMDrivenStrippedStreamingManagerType::Pointer streamingManager = RAMDrivenStrippedStreamingManagerType::New();
+  streamingManager->SetAvailableRAMInMB(availableRAM);
+  streamingManager->SetBias(bias);
+
+  m_StreamingManager = streamingManager;
+ }
+
+template <class TInputImagePixel>
+void
+CacheLessLabelImageToVectorData<TInputImagePixel>
+::SetTileDimensionTiledStreaming(unsigned int tileDimension)
+ {
+  typedef TileDimensionTiledStreamingManager<InputImageType> TileDimensionTiledStreamingManagerType;
+  typename TileDimensionTiledStreamingManagerType::Pointer streamingManager = TileDimensionTiledStreamingManagerType::New();
+  streamingManager->SetTileDimension(tileDimension);
+
+  m_StreamingManager = streamingManager;
+ }
+
+template <class TInputImagePixel>
+void
+CacheLessLabelImageToVectorData<TInputImagePixel>
+::SetAutomaticTiledStreaming(unsigned int availableRAM, double bias)
+ {
+  typedef RAMDrivenTiledStreamingManager<InputImageType> RAMDrivenTiledStreamingManagerType;
+  typename RAMDrivenTiledStreamingManagerType::Pointer streamingManager = RAMDrivenTiledStreamingManagerType::New();
+  streamingManager->SetAvailableRAMInMB(availableRAM);
+  streamingManager->SetBias(bias);
+  m_StreamingManager = streamingManager;
+ }
+
+template <class TInputImagePixel>
+void
+CacheLessLabelImageToVectorData<TInputImagePixel>
+::SetAutomaticAdaptativeStreaming(unsigned int availableRAM, double bias)
+ {
+  typedef RAMDrivenAdaptativeStreamingManager<InputImageType> RAMDrivenAdaptativeStreamingManagerType;
+  typename RAMDrivenAdaptativeStreamingManagerType::Pointer streamingManager = RAMDrivenAdaptativeStreamingManagerType::New();
+  streamingManager->SetAvailableRAMInMB(availableRAM);
+  streamingManager->SetBias(bias);
+  m_StreamingManager = streamingManager;
+ }
+
+template<class TInputImagePixel>
+void
+CacheLessLabelImageToVectorData<TInputImagePixel>
+::SetInput(const InputImageType* input)
+ {
+  this->ProcessObject::SetNthInput(0,const_cast<InputImageType*>(input));
+ }
+
+template<class TInputImagePixel>
+const typename CacheLessLabelImageToVectorData<TInputImagePixel>::InputImageType*
+CacheLessLabelImageToVectorData<TInputImagePixel>
+::GetInput()
+ {
+  if (this->GetNumberOfInputs() < 1)
+    {
+      return ITK_NULLPTR;
+    }
+
+  return static_cast<const InputImageType*>(this->ProcessObject::GetInput(0));
+ }
+
+/**
+ * Update method : update output information of input and write to file
+ */
+template<class TInputImagePixel>
+void
+CacheLessLabelImageToVectorData<TInputImagePixel>
+::Update()
+ {
+  // Update output information on input image
+  InputImagePointer inputPtr =
+      const_cast<InputImageType *>(this->GetInput());
+
+  // Make sure input is available
+  if ( inputPtr.IsNull() )
+    {
+      itkExceptionMacro(<< "No input to writer");
+    }
+
+  this->SetAbortGenerateData(0);
+  this->SetProgress(0.0);
+
+  /**
+   * Tell all Observers that the filter is starting
+   */
+  this->InvokeEvent(itk::StartEvent());
+
+  /**
+   * Grab the input
+   */
+  inputPtr->UpdateOutputInformation();
+  InputImageRegionType inputRegion = inputPtr->GetLargestPossibleRegion();
+
+  // Allocate the buffer image
+  bufferedInputImage = InputImageType::New();
+  bufferedInputImage->SetRegions(inputRegion);
+  bufferedInputImage->Allocate();
+  bufferedInputImage->SetMetaDataDictionary(inputPtr->GetMetaDataDictionary());
+  bufferedInputImage->SetSpacing(inputPtr->GetSpacing());
+  bufferedInputImage->SetOrigin (inputPtr->GetOrigin() );
+
+
+  /** Compare the buffered region  with the inputRegion which is the largest
+   * possible region or a user defined region through extended filename
+   * Not sure that if this modification is needed  */
+  if (inputPtr->GetBufferedRegion() == inputRegion)
+    {
+      otbMsgDevMacro(<< "Buffered region is the largest possible region, there is no need for streaming.");
+      this->SetNumberOfDivisionsStrippedStreaming(1);
+    }
+  m_StreamingManager->PrepareStreaming(inputPtr, inputRegion);
+  m_NumberOfDivisions = m_StreamingManager->GetNumberOfSplits();
+  otbMsgDebugMacro(<< "Number Of Stream Divisions : " << m_NumberOfDivisions);
+
+  /**
+   * Loop over the number of pieces, execute the upstream pipeline on each
+   * piece, and copy the results into the output image.
+   */
+  InputImageRegionType streamRegion;
+
+  this->UpdateProgress(0);
+  m_CurrentDivision = 0;
+  m_DivisionProgress = 0;
+
+  // Get the source process object
+  itk::ProcessObject* source = inputPtr->GetSource();
+  m_IsObserving = false;
+  m_ObserverID = 0;
+
+  // Check if source exists
+  if(source)
+    {
+      typedef itk::MemberCommand<Self>      CommandType;
+      typedef typename CommandType::Pointer CommandPointerType;
+
+      CommandPointerType command = CommandType::New();
+      command->SetCallbackFunction(this, &Self::ObserveSourceFilterProgress);
+
+      m_ObserverID = source->AddObserver(itk::ProgressEvent(), command);
+      m_IsObserving = true;
+    }
+  else
+    {
+      itkWarningMacro(<< "Could not get the source process object. Progress report might be buggy");
+    }
+
+  for (m_CurrentDivision = 0;
+      m_CurrentDivision < m_NumberOfDivisions && !this->GetAbortGenerateData();
+      m_CurrentDivision++, m_DivisionProgress = 0, this->UpdateFilterProgress())
+    {
+      streamRegion = m_StreamingManager->GetSplit(m_CurrentDivision);
+
+      inputPtr->SetRequestedRegion(streamRegion);
+      inputPtr->PropagateRequestedRegion();
+      inputPtr->UpdateOutputData();
+
+      // Copy output in buffer
+      ConstIteratorType inIt(inputPtr, streamRegion);
+      IteratorType outIt(bufferedInputImage, streamRegion);
+      for (inIt.GoToBegin(), outIt.GoToBegin(); !inIt.IsAtEnd(); ++outIt, ++inIt)
+        {
+          outIt.Set(inIt.Get());
+        }
+
+    }
+
+  // Vectorize the buffered image
+  vectorizeFilter = LabelImageToVectorDataFilterType::New();
+  vectorizeFilter->SetInput(bufferedInputImage);
+  vectorizeFilter->SetInputMask(bufferedInputImage);
+  vectorizeFilter->Update();
+  this->GraftOutput( vectorizeFilter->GetOutput() );
+
+  /**
+   * If we ended due to aborting, push the progress up to 1.0 (since
+   * it probably didn't end there)
+   */
+  if (!this->GetAbortGenerateData())
+    {
+      this->UpdateProgress(1.0);
+    }
+
+  // Notify end event observers
+  this->InvokeEvent(itk::EndEvent());
+
+  if (m_IsObserving)
+    {
+      m_IsObserving = false;
+      source->RemoveObserver(m_ObserverID);
+    }
+
+  /**
+   * Release any inputs if marked for release
+   */
+  this->ReleaseInputs();
+
+ }
+
+
+} // end namespace otb
+
+#endif