diff --git a/app/otbLSGRM.cxx b/app/otbLSGRM.cxx
index b5dd444238db0afd5ef90225fc164f9688a86894..20e93301c98be2288df2a8468a477a00808fac88 100644
--- a/app/otbLSGRM.cxx
+++ b/app/otbLSGRM.cxx
@@ -17,6 +17,10 @@
 #include "lsgrmFullLambdaScheduleSegmenter.h"
 #include "lsgrmController.h"
 
+// Graph to label image (streaming version)
+#include "otbStreamingGraphToImageFilter.h"
+#include "otbStreamingImageVirtualWriter.h"
+
 // system tools
 #include <itksys/SystemTools.hxx>
 
@@ -65,6 +69,7 @@ private:
 
   void DoInit()
   {
+
     SetName("GenericRegionMerging");
     SetDescription("This application allows to use the Large Scale Generic Region Merging library "
         "(LSGRM) and provides currently 3 homogeneity criteria: Euclidean Distance, "
@@ -107,6 +112,7 @@ private:
     AddChoice("tiling.none", "No tiling layout");
 
     AddParameter(ParameterType_Int, "memory", "Restrict memory use (mb)");
+
     MandatoryOff("memory");
   }
 
@@ -128,28 +134,28 @@ private:
     std::string tmpdir;
     if (HasValue("tmpdir"))
       {
-      tmpdir= GetParameterAsString("tmpdir");
+        tmpdir= GetParameterAsString("tmpdir");
       }
     else
       {
-      tmpdir = itksys::SystemTools::GetFilenamePath(outfname);
+        tmpdir = itksys::SystemTools::GetFilenamePath(outfname);
       }
 
     if (!tmpdir.empty())
       {
-      // A temporary directory is specified: we check that it ends with a POSIX separator
-      if (tmpdir[tmpdir.size()-1] != '/')
-        {
-        // If not, we add the separator
-        tmpdir.append("/");
-        }
-
-      // Check that the directory exists
-      if (!itksys::SystemTools::FileExists(tmpdir.c_str(),false))
-        {
-        otbAppLogFATAL("The directory " << tmpdir << " does not exist.");
-        }
-      otbAppLogINFO("Using temporary directory " << tmpdir);
+        // A temporary directory is specified: we check that it ends with a POSIX separator
+        if (tmpdir[tmpdir.size()-1] != '/')
+          {
+            // If not, we add the separator
+            tmpdir.append("/");
+          }
+
+        // Check that the directory exists
+        if (!itksys::SystemTools::FileExists(tmpdir.c_str(),false))
+          {
+            otbAppLogFATAL("The directory " << tmpdir << " does not exist.");
+          }
+        otbAppLogINFO("Using temporary directory " << tmpdir);
       }
 
 
@@ -162,17 +168,20 @@ private:
    * This function sets the generic parameters of a controller and runs the segmentation
    */
   template<class TSegmenter>
-  UInt32ImageType::Pointer SetGenericParametersAndRunSegmentation(const typename TSegmenter::ParamType params){
+  void
+  SetGenericParametersAndRunSegmentation(const typename TSegmenter::ParamType params){
 
     // Instantiate the controller
     typedef typename lsgrm::Controller<TSegmenter> ControlerType;
     typename ControlerType::Pointer controller = ControlerType::New();
+    using GraphType = typename ControlerType::GraphType;
 
     // Set specific parameters
     controller->SetSpecificParameters(params);
 
     // Set input image
-    controller->SetInputImage(GetParameterFloatVectorImage("in"));
+    ImageType::Pointer inputImage = GetParameterFloatVectorImage("in");
+    controller->SetInputImage(inputImage);
 
     // Set threshold
     float thres = GetParameterFloat("threshold");
@@ -188,86 +197,92 @@ private:
     int inputTilingMode = GetParameterInt("tiling");
     if (inputTilingMode == TILING_AUTO)
       {
-      // Automatic mode
-      controller->SetTilingModeAuto();
+        // Automatic mode
+        controller->SetTilingModeAuto();
       }
     else if (inputTilingMode == TILING_USER)
       {
-      // User mode
-      controller->SetTilingModeUser();
-      controller->SetTileWidth(GetParameterInt("tiling.user.sizex"));
-      controller->SetTileHeight(GetParameterInt("tiling.user.sizey"));
-      controller->SetNumberOfFirstIterations(GetParameterInt("tiling.user.nfirstiter"));
+        // User mode
+        controller->SetTilingModeUser();
+        controller->SetTileWidth(GetParameterInt("tiling.user.sizex"));
+        controller->SetTileHeight(GetParameterInt("tiling.user.sizey"));
+        controller->SetNumberOfFirstIterations(GetParameterInt("tiling.user.nfirstiter"));
       }
     else if (inputTilingMode == TILING_NONE)
       {
-      // None mode
-      controller->SetTilingModeNone();
+        // None mode
+        controller->SetTilingModeNone();
       }
     else
       {
-      otbAppLogFATAL("Unknown tiling mode!");
+        otbAppLogFATAL("Unknown tiling mode!");
       }
 
     // Input RAM value?
     if (HasValue("memory"))
       {
-      otbAppLogINFO("Setting maximum memory to " << GetParameterInt("memory") << " MBytes");
-      controller->SetInternalMemoryAvailable(GetParameterInt("memory"));
+        otbAppLogINFO("Setting maximum memory to " << GetParameterInt("memory") << " MBytes");
+        controller->SetInternalMemoryAvailable(GetParameterInt("memory"));
       }
 
     // Run the segmentation
     controller->RunSegmentation();
 
+    // Prepare the label image source
+    typedef lsgrm::StreamingGraphToImageFilter<GraphType, UInt32ImageType> LabelImageSourceType;
+    typename LabelImageSourceType::Pointer labelImageSource = LabelImageSourceType::New();
+    labelImageSource->SetGraph(controller->GetOutputGraph());
+    labelImageSource->SetOutputSize(inputImage->GetLargestPossibleRegion().GetSize());
+    labelImageSource->SetOutputOrigin(inputImage->GetOrigin());
+    labelImageSource->SetOutputSpacing(inputImage->GetSpacing());
+    labelImageSource->SetOutputProjectionRef(inputImage->GetProjectionRef());
+    labelImageSource->GenerateOutputInformation();
+
+    m_LabelImageSource = static_cast<itk::ImageSource<UInt32ImageType>*>(labelImageSource);
+
+    SetParameterOutputImage<UInt32ImageType>("out", m_LabelImageSource->GetOutput());
+
+    // TODO: find an intelligent value of RAM
+    if (dynamic_cast<OutputImageParameter*>(GetParameterByKey("out")))
+      {
+      OutputImageParameter* paramDown = dynamic_cast<OutputImageParameter*>(GetParameterByKey("out"));
+      paramDown->SetRAMValue(256);
+      }
+
     // Get temporary files list
     m_TemporaryFilesList = controller->GetTemporaryFilesList();
 
-    // Return the label image
-    return controller->GetLabeledClusteredOutput();
   }
 
   void DoExecute()
   {
-    /*
-        TODO: the output directory in case the global graph cannot fit in memory (lsgrmController.txx)
-     */
 
-    // Input image
     ImageType::Pointer inputImage = GetParameterFloatVectorImage("in");
 
-    // Output image
-    UInt32ImageType::Pointer labelImage = UInt32ImageType::New();
-
     // Switch criterion
     int inputCriterion = GetParameterInt("criterion");
     if (inputCriterion == CRITERION_BAATZ)
       {
-      grm::BaatzParam params;
-      params.m_SpectralWeight = GetParameterFloat("criterion.bs.cw");
-      params.m_ShapeWeight = GetParameterFloat("criterion.bs.sw");
-      labelImage = SetGenericParametersAndRunSegmentation<BaatzSegmenterType>(params);
+        grm::BaatzParam params;
+        params.m_SpectralWeight = GetParameterFloat("criterion.bs.cw");
+        params.m_ShapeWeight = GetParameterFloat("criterion.bs.sw");
+        SetGenericParametersAndRunSegmentation<BaatzSegmenterType>(params);
       }
     else if (inputCriterion == CRITERION_SPRING)
       {
-      grm::SpringParam params;
-      labelImage = SetGenericParametersAndRunSegmentation<SpringSegmenterType>(params);
+        grm::SpringParam params;
+        SetGenericParametersAndRunSegmentation<SpringSegmenterType>(params);
       }
     else if (inputCriterion == CRITERION_FLS)
       {
-      grm::FLSParam params;
-      labelImage = SetGenericParametersAndRunSegmentation<FLSSegmenterType>(params);
+        grm::FLSParam params;
+        SetGenericParametersAndRunSegmentation<FLSSegmenterType>(params);
       }
     else
       {
-      otbAppLogFATAL("Unknow criterion!")
+        otbAppLogFATAL("Unknow criterion!")
       }
 
-    // Set output image projection, origin and spacing for labelImage
-    labelImage->SetProjectionRef(inputImage->GetProjectionRef());
-    labelImage->SetOrigin(inputImage->GetOrigin());
-    labelImage->SetSpacing(inputImage->GetSpacing());
-    SetParameterOutputImage<UInt32ImageType>("out", labelImage);
-
   }
 
   void AfterExecuteAndWriteOutputs()
@@ -282,15 +297,16 @@ private:
     // Delete temporary files
     for (unsigned int i = 0 ; i < m_TemporaryFilesList.size() ; i++)
       {
-      if( remove(m_TemporaryFilesList.at(i).c_str() ) != 0  )
-        {
-        otbAppLogWARNING( "Error deleting file " << m_TemporaryFilesList.at(i) );
-        }
+        if( remove(m_TemporaryFilesList.at(i).c_str() ) != 0  )
+          {
+            otbAppLogWARNING( "Error deleting file " << m_TemporaryFilesList.at(i) );
+          }
       }
   }
 
 private:
   std::vector<std::string> m_TemporaryFilesList;
+  itk::ImageSource<UInt32ImageType>::Pointer m_LabelImageSource;
 
 }; // app class
 } // end of namespace wrapper
diff --git a/include/lsgrmController.h b/include/lsgrmController.h
index 9550c3261064b90335e37c7484de2b948b900c39..e538cbe9a596e2fc20c6075db87077d1453b2da9 100644
--- a/include/lsgrmController.h
+++ b/include/lsgrmController.h
@@ -6,6 +6,7 @@
 #include "itkObject.h"
 #include "itkMacro.h"
 
+
 namespace lsgrm
 {
 template<class TSegmenter>
@@ -30,6 +31,7 @@ public:
   using ImageType = typename SegmenterType::ImageType;
   using LabelImageType = typename SegmenterType::LabelImageType;
   using SegmentationParameterType = typename SegmenterType::ParamType;
+  using GraphType = typename SegmenterType::GraphType;
 
   /* Default constructor and destructor. */
   Controller();
@@ -48,7 +50,6 @@ public:
   void SetTilingModeUser(){m_TilingMode = LSGRM_TILING_USER; Modified();};
   void SetTilingModeAuto(){m_TilingMode = LSGRM_TILING_AUTO; Modified();};
 
-  typename LabelImageType::Pointer GetLabeledClusteredOutput();
   std::vector<std::string> GetTemporaryFilesList();
 
   itkGetMacro(Margin, unsigned int);
@@ -77,6 +78,8 @@ public:
   itkGetMacro(TileHeight, unsigned int);
   itkSetMacro(TileHeight, unsigned int);
 
+  itkGetMacro(OutputGraph, GraphType);
+
 private:
 
   /** Enum for tiling mode */
@@ -91,7 +94,7 @@ private:
   void ComputeMaximumStabilityMargin(unsigned int width, unsigned int height, unsigned int &iter, unsigned int &margin);
   void CheckMemorySize();
   unsigned int GetNodeMemory();
-  long unsigned int GetMaximumNumberOfNodesInMemory();
+  std::size_t GetMaximumNumberOfNodesInMemory();
 
   /* Parameters given by the user */
   std::string m_TemporaryFilesPrefix;    // Path used to store intermediate files during the process.
@@ -116,7 +119,8 @@ private:
   LSGRMTilingMode                    m_TilingMode;         // tiling mode (none/user/auto)
   unsigned int                       m_Margin;             // stability margin related to m_NumberOfFirstIterations
   std::vector<ProcessingTile>        m_Tiles;              // list of tiles
-  typename LabelImageType::Pointer   m_LabelImage;         // output label image
+  GraphType                          m_OutputGraph;        // Output graph
+
 };
 } // end of namespace lsgrm
 
diff --git a/include/lsgrmController.txx b/include/lsgrmController.txx
index 2d2ee411556b605d29a765d013234d3ed41fdb23..6e072f0f9e7d803caa72777bf85ba09b42b10bdc 100644
--- a/include/lsgrmController.txx
+++ b/include/lsgrmController.txx
@@ -18,6 +18,7 @@ Controller<TSegmenter>::Controller()
   m_NbTilesY = 0;
   m_Threshold = 75;
   m_Memory = 0;
+
 }
 
 template<class TSegmenter>
@@ -87,6 +88,7 @@ void Controller<TSegmenter>::RunSegmentation()
 
     // Run first partial segmentation
     boost::timer t; t.restart();
+	
     auto accumulatedMemory = RunFirstPartialSegmentation<TSegmenter>(
         m_InputImage,
         m_SpecificParameters,
@@ -139,7 +141,7 @@ void Controller<TSegmenter>::RunSegmentation()
         numberOfIterationsRemaining -= numberOfIterationsForPartialSegmentations;
         }
       }
-
+	
 #ifdef OTB_USE_MPI
     // Only the master process is doing the next part
     // TODO: Use the MPI process wich has the largest amount of memory
@@ -150,7 +152,7 @@ void Controller<TSegmenter>::RunSegmentation()
     if(accumulatedMemory <= m_Memory)
       {
       // Merge all the graphs
-      m_LabelImage = MergeAllGraphsAndAchieveSegmentation<TSegmenter>(
+        m_OutputGraph = MergeAllGraphsAndAchieveSegmentation<TSegmenter>(
           m_SpecificParameters,
           m_Threshold,
           m_Tiles,
@@ -195,14 +197,15 @@ void Controller<TSegmenter>::RunSegmentation()
     segmenter.SetInput(m_InputImage);
     segmenter.Update();
 
-    // Get label image
-    m_LabelImage = segmenter.GetLabeledClusteredOutput();
+    m_OutputGraph = segmenter.m_Graph;
     }
   else
     {
     itkExceptionMacro(<<"Unknow tiling mode!");
     }
 
+  // TODO: [MPI] broadcast the graph to other nodes
+
 }
 
 /*
@@ -264,7 +267,7 @@ void Controller<TSegmenter>::CheckMemorySize()
  * Compute the maximum number of nodes which can fit in the memory
  */
 template<class TSegmenter>
-long unsigned int Controller<TSegmenter>::GetMaximumNumberOfNodesInMemory()
+std::size_t Controller<TSegmenter>::GetMaximumNumberOfNodesInMemory()
 {
   itkDebugMacro(<< "Computing maximum number of nodes in memory");
 
@@ -433,16 +436,16 @@ void Controller<TSegmenter>::SetSpecificParameters(const SegmentationParameterTy
   m_SpecificParameters = params;
 }
 
-template<class TSegmenter>
-typename Controller<TSegmenter>::LabelImageType::Pointer
-Controller<TSegmenter>::GetLabeledClusteredOutput()
-{
-#ifdef OTB_USE_MPI
-  // Get the label image from the master process (the one which achieves segmentation)
-  BroadcastImage<typename TSegmenter::LabelImageType>(m_LabelImage);
-#endif
-  return m_LabelImage;
-}
+//template<class TSegmenter>
+//typename Controller<TSegmenter>::LabelImageType::Pointer
+//Controller<TSegmenter>::GetLabeledClusteredOutput()
+//{
+//#ifdef OTB_USE_MPI
+//  // Get the label image from the master process (the one which achieves segmentation)
+//  BroadcastImage<typename TSegmenter::LabelImageType>(m_LabelImage);
+//#endif
+//  return m_LabelImage;
+//}
 
 template <class TSegmenter>
 std::vector<std::string> Controller<TSegmenter>::GetTemporaryFilesList()
diff --git a/include/lsgrmGraphOperations.h b/include/lsgrmGraphOperations.h
index ea975fbe1126e6a65e0b782cdf63dda561a484d6..3ce66f2d87d3ce5589f312e41a1ceb68fa43926f 100644
--- a/include/lsgrmGraphOperations.h
+++ b/include/lsgrmGraphOperations.h
@@ -5,7 +5,6 @@
 #include "grmGraphOperations.h"
 #include "otbVectorImage.h"
 #include "otbMultiChannelExtractROI.h"
-#include "itkGrayscaleFillholeImageFilter.h"
 
 namespace lsgrm
 {
@@ -32,7 +31,7 @@ typename TSegmenter::ImageType::Pointer ReadImageRegion(
     typename TSegmenter::ImageType::RegionType region);
 
 template<class TSegmenter>
-typename TSegmenter::LabelImageType::Pointer
+typename TSegmenter::GraphType
 MergeAllGraphsAndAchieveSegmentation(
     const typename TSegmenter::ParamType& params,
     const float& threshold,
@@ -79,13 +78,13 @@ void RemoveUselessNodes(ProcessingTile& tile,
 
 
 template<class TSegmenter>
-void UpdateNeighborsOfNoneDuplicatedNodes(std::unordered_map<long unsigned int,
+void UpdateNeighborsOfNoneDuplicatedNodes(std::unordered_map<std::size_t,
     std::vector<typename TSegmenter::NodePointerType> >& borderPixelMap,
     const unsigned int imageWidth,
     const unsigned int imageHeight);
 
 template<class TSegmenter>
-void RemoveDuplicatedNodes(std::unordered_map<long unsigned int,
+void RemoveDuplicatedNodes(std::unordered_map<std::size_t,
     std::vector<typename TSegmenter::NodePointerType> >& borderPixelMap,
     typename TSegmenter::GraphType& graph,
     const unsigned int imageWidth);
@@ -97,9 +96,10 @@ void BuildBorderPixelMap(typename TSegmenter::GraphType& graph,
     const unsigned int colTile,
     const unsigned int nbTilesX,
     const unsigned int nbTilesY,
-    std::unordered_map<long unsigned int,
+    std::unordered_map<std::size_t,
     std::vector<typename TSegmenter::NodePointerType> >& borderPixelMap,
-    const unsigned int imageWidth);
+    const unsigned int imageWidth,
+	bool merging = false);
 
 template<class TSegmenter>
 void InsertNodesFromTile(typename TSegmenter::GraphType& graph,
diff --git a/include/lsgrmGraphOperations.txx b/include/lsgrmGraphOperations.txx
index 930b8b32754bf16e5855bf43f11b296e347e16a7..d2094771191aa3a9c7811ea4cbb7979b59c2a7fc 100644
--- a/include/lsgrmGraphOperations.txx
+++ b/include/lsgrmGraphOperations.txx
@@ -25,7 +25,7 @@ typename TSegmenter::ImageType::Pointer ReadImageRegion(
 }
 
 template<class TSegmenter>
-typename TSegmenter::LabelImageType::Pointer
+typename TSegmenter::GraphType
 MergeAllGraphsAndAchieveSegmentation(
     const typename TSegmenter::ParamType& params,
     const float& threshold,
@@ -63,13 +63,13 @@ MergeAllGraphsAndAchieveSegmentation(
       {
       std::cout << "Cleaning nodes of tile " << (row*nbTilesX + col) << " / " << (nbTilesX*nbTilesY) << std::endl;
 
-      std::unordered_map<long unsigned int,
+      std::unordered_map<std::size_t,
       std::vector<typename TSegmenter::NodePointerType> > borderPixelMap;
 
       std::cout << "\tBuildBorderPixelMap..." << std::endl;
 
       BuildBorderPixelMap<TSegmenter>(segmenter.m_Graph, tiles[row*nbTilesX + col], row, col,
-          nbTilesX, nbTilesY, borderPixelMap, imageWidth);
+          nbTilesX, nbTilesY, borderPixelMap, imageWidth, true);
 
       std::cout << "\tRemoveDuplicatedNodes..." << std::endl;
 
@@ -91,69 +91,42 @@ MergeAllGraphsAndAchieveSegmentation(
   segmenter.SetThreshold(threshold);
   segmenter.SetDoFastSegmentation(false); // was true
   segmenter.SetNumberOfIterations(numberOfIterations);
-
   grm::GraphOperations<TSegmenter>::PerfomAllIterationsWithLMBFAndConstThreshold(segmenter);
 
-  //  // Write output graph to the output graph directory
-  //  WriteGraph<TSegmenter>(segmenter.m_Graph, tmpDir, 0, 0);
-
-  // Generate the label image
-  typename TSegmenter::LabelImageType::IndexType index;
-  index.Fill(0);
-  typename TSegmenter::LabelImageType::SizeType size;
-  size[0] = imageWidth;
-  size[1] = imageHeight;
-  typename TSegmenter::LabelImageType::RegionType region(index, size);
-  const typename TSegmenter::LabelImageType::InternalPixelType noDataLabel = 0;
-  typename TSegmenter::LabelImageType::Pointer labelImage = TSegmenter::LabelImageType::New();
-  labelImage->SetRegions(region);
-  labelImage->Allocate();
-  labelImage->FillBuffer(noDataLabel);
-
-  using LabelImageIterator = itk::ImageRegionIterator<typename TSegmenter::LabelImageType>;
-  LabelImageIterator it(labelImage, labelImage->GetLargestPossibleRegion());
-
-  // Start at 1 (value 0 can be used for invalid pixels)
-  unsigned int label = 1;
-  for(auto& node : segmenter.m_Graph.m_Nodes)
-    {
-    lp::CellLists borderPixels;
-    lp::ContourOperations::GenerateBorderCells(borderPixels, node->m_Contour, node->m_Id, imageWidth);
-
-    for (auto& pix: borderPixels)
-      {
-      index[0] = pix % imageWidth;
-      index[1] = pix / imageWidth;
-      labelImage->SetPixel(index, label);
-      }
-    ++label;
-    }
-
-  // Re-order nodes labels (left->right to top->bottom)
-  vnl_vector<typename TSegmenter::LabelImageType::InternalPixelType> lut(label,noDataLabel);
-  label = 1;
-  for(it.GoToBegin();!it.IsAtEnd(); ++it)
-    {
-    unsigned int inputLabel = it.Get();
-    if (lut[ inputLabel ] == noDataLabel && inputLabel != noDataLabel)
-      {
-      lut[ inputLabel ] = label;
-      label++;
-      }
-    }
-
-  // Apply LUT
-  for(it.GoToBegin();!it.IsAtEnd(); ++it)
-    it.Set(lut[it.Get()]);
-
-  // Fill holes
-  typedef itk::GrayscaleFillholeImageFilter<typename TSegmenter::LabelImageType,
-      typename TSegmenter::LabelImageType> FillholeFilterType;
-  typename FillholeFilterType::Pointer fillFilter = FillholeFilterType::New();
-  fillFilter->SetInput(labelImage);
-  fillFilter->Update();
-
-  return fillFilter->GetOutput();}
+  // patch raf (sort using node id directly --> seems ok)
+  // Sort the nodes top-->down and left-->right
+  /*
+  std::sort(segmenter.m_Graph.m_Nodes.begin(), segmenter.m_Graph.m_Nodes.end(),
+      [imageWidth](const auto & a, const auto & b) -> bool
+  {
+    lp::CellLists borderPixelsA, borderPixelsB;
+    lp::ContourOperations::GenerateBorderCells(borderPixelsA, a->m_Contour, a->m_Id, imageWidth);
+    lp::ContourOperations::GenerateBorderCells(borderPixelsB, b->m_Contour, b->m_Id, imageWidth);
+
+	// patch raf (were unsigned int)
+    std::size_t offA = 0;
+    std::size_t offB = 0;
+	// end patch
+    for (auto& pix: borderPixelsA)
+      if (pix>offA)
+        offA=pix;
+
+    for (auto& pix: borderPixelsB)
+      if (pix>offB)
+        offB=pix;
+
+      return offA > offB;
+  });
+  */
+  std::sort(segmenter.m_Graph.m_Nodes.begin(), segmenter.m_Graph.m_Nodes.end(),
+      [](const auto & a, const auto & b) -> bool
+  {
+      return a->m_Id < b->m_Id;
+  });
+  // end patch
+
+  return segmenter.m_Graph;
+}
 
 template<class TSegmenter>
 long long unsigned int RunPartialSegmentation(const typename TSegmenter::ParamType& params,
@@ -198,7 +171,7 @@ long long unsigned int RunPartialSegmentation(const typename TSegmenter::ParamTy
               row, col, nbTilesX, nbTilesY);
 
           std::cout << "\tBuild border pixel map..." << std::endl;
-          std::unordered_map<long unsigned int, std::vector<typename TSegmenter::NodePointerType> > borderPixelMap;
+          std::unordered_map<std::size_t, std::vector<typename TSegmenter::NodePointerType> > borderPixelMap;
           BuildBorderPixelMap<TSegmenter>(segmenter.m_Graph, currentTile, row, col,
               nbTilesX, nbTilesY, borderPixelMap, imageWidth);
 
@@ -366,7 +339,7 @@ void RemoveUselessNodes(ProcessingTile& tile,
 }
 
 template<class TSegmenter>
-void UpdateNeighborsOfNoneDuplicatedNodes(std::unordered_map<long unsigned int,
+void UpdateNeighborsOfNoneDuplicatedNodes(std::unordered_map<std::size_t,
     std::vector<typename TSegmenter::NodePointerType> >& borderPixelMap,
     const unsigned int imageWidth,
     const unsigned int imageHeight)
@@ -376,7 +349,7 @@ void UpdateNeighborsOfNoneDuplicatedNodes(std::unordered_map<long unsigned int,
 
   for(auto& pn : borderPixelMap)
     {
-    long int neighborhood[4];
+    NeighIDType neighborhood[4];
     grm::FOURNeighborhood(neighborhood, pn.first, imageWidth, imageHeight);
 
     for(short j = 0; j < 4; ++j)
@@ -404,7 +377,7 @@ void UpdateNeighborsOfNoneDuplicatedNodes(std::unordered_map<long unsigned int,
                 {
                 if(borderPixelMap.find(pix) != borderPixelMap.end())
                   {
-                  long int pixNeighborhood[4];
+                  NeighIDType pixNeighborhood[4];
                   grm::FOURNeighborhood(pixNeighborhood, pix, imageWidth, imageHeight);
 
                   for(short k = 0; k < 4; k++)
@@ -431,7 +404,7 @@ void UpdateNeighborsOfNoneDuplicatedNodes(std::unordered_map<long unsigned int,
 }
 
 template<class TSegmenter>
-void RemoveDuplicatedNodes(std::unordered_map<long unsigned int,
+void RemoveDuplicatedNodes(std::unordered_map<std::size_t,
     std::vector<typename TSegmenter::NodePointerType> >& borderPixelMap,
     typename TSegmenter::GraphType& graph,
     const unsigned int imageWidth)
@@ -502,9 +475,10 @@ void BuildBorderPixelMap(typename TSegmenter::GraphType& graph,
     const unsigned int colTile,
     const unsigned int nbTilesX,
     const unsigned int nbTilesY,
-    std::unordered_map<long unsigned int,
+    std::unordered_map<std::size_t,
     std::vector<typename TSegmenter::NodePointerType> >& borderPixelMap,
-    const unsigned int imageWidth)
+    const unsigned int imageWidth,
+	bool merging)
 {
   unsigned int rowPixel, colPixel;
   unsigned int rowMin = (tile.rows[0] > 0) ? tile.rows[0] - 1 : tile.rows[0];
@@ -521,6 +495,15 @@ void BuildBorderPixelMap(typename TSegmenter::GraphType& graph,
       {
       continue;
       }
+	// patch raf (exclude nodes all outside tiles - on merging stage only)
+	else if(merging && (node->m_Bbox.m_UX > tile.columns[1] ||
+        node->m_Bbox.m_UY > tile.rows[1] ||
+        node->m_Bbox.m_UX + node->m_Bbox.m_W - 1 < tile.columns[0] ||
+        node->m_Bbox.m_UY + node->m_Bbox.m_H - 1 < tile.rows[0]))
+      {
+      continue;
+      }  
+	// end patch
     else
       {
       lp::CellLists borderPixels;
@@ -683,7 +666,7 @@ long long unsigned int RunFirstPartialSegmentation(
         segmenter.SetNumberOfIterations(niter);
         segmenter.SetInput(imageTile);
         segmenter.Update();
-
+		
         if(segmenter.GetComplete() == false)
           isFusion = true;
 
@@ -696,7 +679,7 @@ long long unsigned int RunFirstPartialSegmentation(
             tileWidth,
             tileHeight,
             imageWidth);
-
+			
         // Remove unstable segments
         std::cout << "\tRemoving unstable segments..." << std::endl;
         RemoveUnstableSegments<TSegmenter>(segmenter.m_Graph, currentTile, imageWidth);
@@ -1029,7 +1012,7 @@ void RescaleGraph(typename TSegmenter::GraphType& graph,
     // Start pixel index of the node (in the image)
     rowNodeImg = rowTile * tileHeight + rowNodeTile - tile.margin[0];
     colNodeImg = colTile * tileWidth + colNodeTile - tile.margin[3];
-    node->m_Id = rowNodeImg * imageWidth + colNodeImg;
+    node->m_Id = (std::size_t)rowNodeImg * (std::size_t)imageWidth + (std::size_t)colNodeImg;
 
     // Change also its bounding box
     node->m_Bbox.m_UX = colTile * tileWidth + node->m_Bbox.m_UX - tile.margin[3];
diff --git a/include/lsgrmSegmenter.h b/include/lsgrmSegmenter.h
index 7eed1430eef0d46a877c17887f95528f55ec0931..995722d70f7c0aa8860153a5cf2a118d6a5baca5 100644
--- a/include/lsgrmSegmenter.h
+++ b/include/lsgrmSegmenter.h
@@ -106,7 +106,7 @@ public:
   void ReadGraph(FILE * nodeStream, FILE * edgeStream)
   {
 
-    std::unordered_map<long unsigned int, NodePointerType> nodeMap;
+    std::unordered_map<std::size_t, NodePointerType> nodeMap;
 
     // Read the size of the graph
     {
@@ -151,7 +151,7 @@ public:
 
     for(auto& node: this->m_Graph.m_Nodes)
       {
-      long unsigned int nodeId;
+      std::size_t nodeId;
       fread(&(nodeId), sizeof(nodeId), 1, edgeStream);
       assert(nodeId == node->m_Id);
 
@@ -160,7 +160,7 @@ public:
       node->m_Edges.reserve(edgeSize);
       for(unsigned int b = 0; b < edgeSize; b++)
         {
-        long unsigned int targetId;
+        std::size_t targetId;
         unsigned int boundary;
         fread(&(targetId), sizeof(targetId), 1, edgeStream);
         fread(&(boundary), sizeof(boundary), 1, edgeStream);
diff --git a/include/otbStreamingGraphToImageFilter.h b/include/otbStreamingGraphToImageFilter.h
new file mode 100644
index 0000000000000000000000000000000000000000..1bd3bb4ee32d36ca6fe22bad082569eb8baa23b8
--- /dev/null
+++ b/include/otbStreamingGraphToImageFilter.h
@@ -0,0 +1,102 @@
+/*
+ * otbStreamingGraphToImageFilter.h
+ *
+ *  Created on: 6 nov. 2017
+ *      Author: cresson
+ */
+
+#ifndef MODULES_REMOTE_LSGRM_INCLUDE_OTBSTREAMINGGRAPHTOIMAGEFILTER_H_
+#define MODULES_REMOTE_LSGRM_INCLUDE_OTBSTREAMINGGRAPHTOIMAGEFILTER_H_
+
+#include "itkImageSource.h"
+#include "itkExceptionObject.h"
+#include "itkImageRegion.h"
+#include "itkGrayscaleFillholeImageFilter.h"
+
+#include "grmGraphOperations.h"
+
+// Boost R-Tree
+#include <boost/geometry.hpp>
+#include <boost/geometry/geometries/point.hpp>
+#include <boost/geometry/geometries/box.hpp>
+
+#include <boost/geometry/index/rtree.hpp>
+
+// to store queries results
+#include <vector>
+
+// just for output
+#include <iostream>
+#include <boost/foreach.hpp>
+
+namespace bg = boost::geometry;
+namespace bgi = boost::geometry::index;
+
+namespace lsgrm
+{
+
+template <class TGraph, class TLabelImage>
+class ITK_EXPORT StreamingGraphToImageFilter : public itk::ImageSource<TLabelImage>
+{
+public:
+  /** Standard class typedefs. */
+  typedef StreamingGraphToImageFilter                   Self;
+  typedef itk::ImageSource<TLabelImage>                 Superclass;
+  typedef itk::SmartPointer<Self>                       Pointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(StreamingGraphToImageFilter, ImageSource);
+
+  /** Typedefs for processing */
+  typedef typename TLabelImage::RegionType              RegionType;
+  typedef typename TLabelImage::IndexType               IndexType;
+  typedef typename TLabelImage::SizeType                SizeType;
+  typedef typename TLabelImage::SpacingType             SpacingType;
+  typedef typename TLabelImage::PointType               PointType;
+  typedef typename TGraph::NodePointerType              NodePointerType;
+  typedef itk::GrayscaleFillholeImageFilter<TLabelImage,TLabelImage> FillholeFilterType;
+  typedef bg::model::point<float, 2, bg::cs::cartesian> point;
+  typedef bg::model::box<point> box;
+  typedef std::pair<box, unsigned> value;
+
+  /** Set the input graph and build the R-Tree */
+  void SetGraph(const TGraph graph);
+
+  /** Prepare image allocation at the first call of the pipeline processing */
+  virtual void GenerateOutputInformation(void);
+
+  /** Does the real work. */
+  virtual void GenerateData();
+
+  itkSetMacro(OutputSize, SizeType);
+  itkSetMacro(OutputOrigin, PointType);
+  itkSetMacro(OutputSpacing, SpacingType);
+  itkSetMacro(OutputProjectionRef, std::string);
+
+protected:
+  StreamingGraphToImageFilter(){};
+  virtual ~StreamingGraphToImageFilter(){};
+
+private:
+
+  StreamingGraphToImageFilter(const Self &); //purposely not implemented
+  void operator =(const Self&); //purposely not implemented
+
+  TGraph       m_Graph;
+  bgi::rtree< value, bgi::quadratic<16> > rtree;
+  SizeType     m_OutputSize;
+  SpacingType  m_OutputSpacing;
+  PointType    m_OutputOrigin;
+  std::string  m_OutputProjectionRef;
+};
+
+} /* namespace lsgrm */
+
+#ifndef OTB_MANUAL_INSTANTIATION
+#include <otbStreamingGraphToImageFilter.txx>
+#endif
+
+#endif /* MODULES_REMOTE_LSGRM_INCLUDE_OTBSTREAMINGGRAPHTOIMAGEFILTER_H_ */
diff --git a/include/otbStreamingGraphToImageFilter.txx b/include/otbStreamingGraphToImageFilter.txx
new file mode 100644
index 0000000000000000000000000000000000000000..0332f547bf63ae56813caca4989eb8f0da2d955c
--- /dev/null
+++ b/include/otbStreamingGraphToImageFilter.txx
@@ -0,0 +1,168 @@
+/*
+ * otbStreamingGraphToImageFilter.txx
+ *
+ *  Created on: 6 nov. 2017
+ *      Author: cresson
+ */
+
+#ifndef MODULES_REMOTE_LSGRM_INCLUDE_OTBSTREAMINGGRAPHTOIMAGEFILTER_TXX_
+#define MODULES_REMOTE_LSGRM_INCLUDE_OTBSTREAMINGGRAPHTOIMAGEFILTER_TXX_
+
+#include <otbStreamingGraphToImageFilter.h>
+
+namespace lsgrm
+{
+
+template <class TGraph, class TLabelImage>
+void
+StreamingGraphToImageFilter<TGraph, TLabelImage>
+::SetGraph(const TGraph graph)
+ {
+  m_Graph = graph;
+
+  // Build a R-Tree
+  itkDebugMacro( << "Building R-Tree" );
+
+  rtree.clear();
+  unsigned int count = 0;
+  for(auto& node : m_Graph.m_Nodes)
+    {
+      // create a box
+      box b(
+          point(
+              node->m_Bbox.m_UX,
+              node->m_Bbox.m_UY),
+          point(
+              node->m_Bbox.m_UX + node->m_Bbox.m_W,
+              node->m_Bbox.m_UY + node->m_Bbox.m_H));
+
+      // insert new value
+      rtree.insert(std::make_pair(b, count));
+      count++;
+    }
+
+  itkDebugMacro( << "Building R-Tree finished" );
+
+ }
+
+template <class TGraph, class TLabelImage>
+void
+StreamingGraphToImageFilter<TGraph, TLabelImage>
+::GenerateOutputInformation()
+ {
+  itkDebugMacro( << "Entering GenerateOutputInformation()" );
+
+  // Output Largest Possible Region
+  IndexType index;
+  index.Fill(0);
+  RegionType outputRegion(index, m_OutputSize);
+
+  // Set output informations
+  TLabelImage * outputPtr = this->GetOutput();
+  outputPtr->SetOrigin ( m_OutputOrigin );
+  outputPtr->SetSpacing ( m_OutputSpacing );
+  outputPtr->SetLargestPossibleRegion( outputRegion );
+  outputPtr->SetProjectionRef(m_OutputProjectionRef);
+
+ }
+
+
+template <class TGraph, class TLabelImage>
+void
+StreamingGraphToImageFilter<TGraph, TLabelImage>
+::GenerateData()
+ {
+  itkDebugMacro( << "Entering GenerateData()" );
+
+  // Allocate the output buffer
+  TLabelImage * outputPtr = this->GetOutput();
+  RegionType outReqRegion = outputPtr->GetRequestedRegion();
+  outputPtr->SetBufferedRegion(outputPtr->GetRequestedRegion());
+  outputPtr->Allocate();
+
+  // Find nodes intersecting find the output requested region
+  box query_box(
+      point(
+          outReqRegion.GetIndex(0),
+          outReqRegion.GetIndex(1)),
+      point(
+          outReqRegion.GetIndex(0)+outReqRegion.GetSize(0),
+          outReqRegion.GetIndex(1)+outReqRegion.GetSize(1)));
+  std::vector<value> result_s;
+  itkDebugMacro( << "R-Tree query on output requested region " << outReqRegion );
+  rtree.query(bgi::intersects(query_box), std::back_inserter(result_s));
+  itkDebugMacro( << "R-Tree query done. Number of nodes: " << result_s.size() );
+
+  // Retrieve the bounding box of the intersecting nodes (a kind of "Input requested region")
+  box realBBox(query_box);
+  for(auto& res : result_s)
+    {
+      boost::geometry::expand(realBBox, res.first);
+    }
+  IndexType index;
+  index[0] = realBBox.min_corner().get<0>();
+  index[1] = realBBox.min_corner().get<1>();
+  SizeType size;
+  size[0] = realBBox.max_corner().get<0>() - realBBox.min_corner().get<0>();
+  size[1] = realBBox.max_corner().get<1>() - realBBox.min_corner().get<1>();
+  RegionType inputRequestedRegion(index, size);
+  itkDebugMacro( << "Input Requested region: " << inputRequestedRegion );
+
+  // Generate the label image
+  itkDebugMacro( << "Allocate buffered region ");
+  const typename TLabelImage::InternalPixelType noDataLabel = 0;
+  typename TLabelImage::Pointer labelImage = TLabelImage::New();
+  labelImage->SetRegions(inputRequestedRegion);
+  labelImage->Allocate();
+  labelImage->FillBuffer(noDataLabel);
+  itkDebugMacro( << "Allocate buffered region ok" );
+
+  using LabelImageIterator = itk::ImageRegionIterator<TLabelImage>;
+  LabelImageIterator it(labelImage, inputRequestedRegion);
+
+  // Burn boundaries
+  itkDebugMacro( << "Burning boundaries " );
+  for(auto& res : result_s)
+    {
+      NodePointerType node = m_Graph.m_Nodes[res.second];
+
+      lp::CellLists borderPixels;
+      lp::ContourOperations::GenerateBorderCells(borderPixels, node->m_Contour, node->m_Id, m_OutputSize[0]);
+
+      for (auto& pix: borderPixels)
+        {
+		  // patch raf (catch exception if position of pixel to set is not correct)
+		  try {
+          index[0] = (unsigned int)(pix % (std::size_t)(m_OutputSize[0]));
+          index[1] = (unsigned int)(pix / (std::size_t)(m_OutputSize[0]));
+          labelImage->SetPixel(index, res.second);
+		  } catch (std::exception e) {
+			  std::cout << "Pixel ID: " << pix << std::endl;
+			  std::cout << "Derived index: " << index[0] << "," << index[1] << std::endl;
+			  std::cout << "Node position in list: " << res.second << std::endl;
+		  }
+		  // end patch
+        }
+    }
+  itkDebugMacro( << "Burning boundaries ok ");
+
+  // Fill holes
+  itkDebugMacro( << "fill Hole filter" );
+  typename FillholeFilterType::Pointer fillFilter = FillholeFilterType::New();
+  fillFilter->SetInput(labelImage);
+  fillFilter->Update();
+  itkDebugMacro( << "Fill Hole filter OutputLargestPossibleRegion:" << fillFilter->GetOutput()->GetLargestPossibleRegion() );
+  itkDebugMacro( << "fill Hole filter ok" );
+
+  // Extract the stable region
+  LabelImageIterator outIt(outputPtr, outReqRegion);
+  LabelImageIterator inIt (fillFilter->GetOutput(), outReqRegion);
+  for (inIt.GoToBegin(), outIt.GoToBegin(); !outIt.IsAtEnd(); ++outIt, ++inIt)
+    outIt.Set(inIt.Get());
+ }
+
+
+
+} /* namespace lsgrm */
+
+#endif