Commit 84788f22453a1caf79a2d08bf874282db0ac6222

Authored by Pierre Lassalle
1 parent ff8510c6
Exists in master

Add the GRM Remote Module

CMakeLists.txt 0 → 100644
... ... @@ -0,0 +1,32 @@
  1 +# Check compiler version
  2 +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
  3 + # require at least gcc 4.8
  4 + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8)
  5 + message(FATAL_ERROR "GCC version must be at least 4.8!")
  6 + endif()
  7 +elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
  8 + # require at least clang 3.2
  9 + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.2)
  10 + message(FATAL_ERROR "Clang version must be at least 3.2!")
  11 + endif()
  12 +else()
  13 + message(WARNING "You are using an unsupported compiler! Compilation has only been tested with Clang and GCC.")
  14 +endif()
  15 +
  16 +include(CheckCXXCompilerFlag)
  17 +CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
  18 +if(COMPILER_SUPPORTS_CXX11)
  19 + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fpermissive")
  20 +else()
  21 + message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
  22 +endif()
  23 +
  24 +set(GRM_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/)
  25 +
  26 +include_directories(${GRM_INCLUDE_DIR})
  27 +
  28 +project(GRM)
  29 +
  30 +set(GRM_LIBRARIES GRM)
  31 +
  32 +otb_module_impl()
... ...
GRMSegmenterTemplate.h 0 → 100644
... ... @@ -0,0 +1,62 @@
  1 +/*=========================================================================
  2 +
  3 + Program: Generic Region Merging Library
  4 + Language: C++
  5 + author: Lassalle Pierre
  6 + contact: lassallepierre34@gmail.com
  7 +
  8 +
  9 +
  10 + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved
  11 +
  12 +
  13 + This software is distributed WITHOUT ANY WARRANTY; without even
  14 + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15 + PURPOSE. See the above copyright notices for more information.
  16 +
  17 + Template Model to help the developper to add a new criterion
  18 + This file as well as his corresponding txx file has to be added
  19 + src folder.
  20 +
  21 +=========================================================================*/
  22 +#ifndef __GRM_MYSEGMENTER_H
  23 +#define __GRM_MYSEGMENTER_H
  24 +#include "grmSegmenter.h"
  25 +
  26 +namespace grm
  27 +{
  28 + struct MySpecificNode : Node<MySpecificNode>
  29 + {
  30 + // Specific Attributes for your criterion.
  31 + };
  32 +
  33 + struct MySpecificParams
  34 + {
  35 + // Specific user-defined parameters for your criterion.
  36 + };
  37 +
  38 + template<class TImage>
  39 + class MySegmenter : public Segmenter< TImage, MySpecificNode, MySpecificParams>
  40 + {
  41 + public:
  42 +
  43 + /* Some convenient typedefs (put them all) */
  44 + typedef Segmenter<TImage, MySpecificNode, MySpecificParams> Superclass;
  45 + typedef TImage ImageType;
  46 + typedef MySpecificParams ParameterType;
  47 + typedef typename Superclass::GraphType GraphType;
  48 + typedef MySpecificNode NodeType;
  49 + typedef typename Superclass::EdgeType EdgeType;
  50 + typedef typename Superclass::NodePointerType NodePointerType;
  51 + typedef typename Superclass::GraphOperatorType GraphOperatorType;
  52 + typedef GraphToOtbImage<GraphType> IOType;
  53 +
  54 + // Mandatory functions to be defined by the developer.
  55 + void InitFromImage();
  56 + float ComputeMergingCost(NodePointerType n1, NodePointerType n2);
  57 + void UpdateSpecificAttributes(NodePointerType n1, NodePointerType n2);
  58 + };
  59 +
  60 +} // end of namespace grm
  61 +#include "GRMSegmenterTemplate.txx"
  62 +#endif
... ...
GRMSegmenterTemplate.txx 0 → 100644
... ... @@ -0,0 +1,97 @@
  1 +/*=========================================================================
  2 +
  3 + Program: Generic Region Merging Library
  4 + Language: C++
  5 + author: Lassalle Pierre
  6 + contact: lassallepierre34@gmail.com
  7 +
  8 +
  9 +
  10 + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved
  11 +
  12 +
  13 + This software is distributed WITHOUT ANY WARRANTY; without even
  14 + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15 + PURPOSE. See the above copyright notices for more information.
  16 +
  17 + Template Model to help the developper to add a new criterion
  18 + This file as well as his corresponding txx file has to be added
  19 + src folder.
  20 +
  21 +=========================================================================*/
  22 +#ifndef __GRM_MYSEGMENTER_TXX
  23 +#define __GRM_MYSEGMENTER_TXX
  24 +#include <otbImageFileReader.h>
  25 +#include <itkImageRegionIterator.h>
  26 +
  27 +/*
  28 + Important to read:
  29 +
  30 + The graph of segments can be accessed like this: this->m_Graph
  31 + The number of segments in the graph: this->m_Graph.size()
  32 + To access to the segment pointer at the position idx: this->m_Graph.m_Nodes[idx]
  33 + For each segment pointer you can used the following attributes:
  34 + this->m_Graph.m_Nodes[idx]->m_Perimeter // Perimeter of the segment.
  35 + this->m_Graph.m_Nodes[idx]->m_Area // Number of pixels contained in the segment.
  36 + this->m_Graph.m_Nodes[idx]->m_Bbox // Bounding box of the segment:
  37 + this->m_Graph.m_Nodes[idx]->m_Bbox.m_UX : upper left x coordinate
  38 + this->m_Graph.m_Nodes[idx]->m_Bbox.m_UY : upper left y coordinate
  39 + this->m_Graph.m_Nodes[idx]->m_Bbox.m_W : width
  40 + this->m_Graph.m_Nodes[idx]->m_Bbox.m_UX : height
  41 + this->m_Graph.m_Nodes[idx]->m_Contour: moves along the contour of the segment:
  42 + To generate the set of the coordinates of the border pixels:
  43 + lp::CellLists borderPixels; // (std::unordered_set<long unsigned int>)
  44 + lp::ContourOperations::GenerateBorderCells(borderPixels, this->m_Graph.m_Nodes[idx]->m_Contour, this->m_Graph.m_Nodes[idx]->m_Id, this->m_ImageWidth);
  45 + this->m_Graph.m_Nodes[idx]->m_Edges // std::vector<EdgeType> containing edges to adjacent segment
  46 + Given an edge e:
  47 + e.GetRegion() : access to the adjacent segment pointer.
  48 + e.m_Boundary : lenght of the border between the current segment and the adjacent segment.
  49 + e.m_Cost: merging cost between the current segment and the adjacent segment.
  50 +*/
  51 +
  52 +namespace grm
  53 +{
  54 +
  55 + template<class TImage>
  56 + void
  57 + MySegmenter<TImage>::InitFromImage()
  58 + {
  59 + typedef itk::ImageRegionIterator<TImage> ImageIterator;
  60 +
  61 + this->m_ImageWidth = this->m_InputImage->GetLargestPossibleRegion().GetSize()[0];
  62 + this->m_ImageHeight =this->m_InputImage->GetLargestPossibleRegion().GetSize()[1];
  63 + this->m_NumberOfComponentsPerPixel = this->m_InputImage->GetNumberOfComponentsPerPixel();
  64 +
  65 + std::size_t idx = 0;
  66 + ImageIterator it(this->m_InputImage, this->m_InputImage->GetLargestPossibleRegion());
  67 + for(it.GoToBegin(); !it.IsAtEnd(); ++it)
  68 + {
  69 + // Initialize your specific attributes for each pixel of the image.
  70 +
  71 + for(std::size_t b = 0; b < this->m_NumberOfComponentsPerPixel; ++b)
  72 + {
  73 + // Initialize your specific attributes if they depend on spectral values of pixels.
  74 + }
  75 + ++idx;
  76 + }
  77 + }
  78 +
  79 + template<class TImage>
  80 + float
  81 + MySegmenter<TImage>::ComputeMergingCost(NodePointerType n1, NodePointerType n2)
  82 + {
  83 + // Determine how to compute the merging cost between the two adjacent segments.
  84 + }
  85 +
  86 + template<class TImage>
  87 + void
  88 + MySegmenter<TImage>::UpdateSpecificAttributes(NodePointerType n1, NodePointerType n2)
  89 + {
  90 + // Determine how to update your specif attributes when segment n2 is merged into segment n1.
  91 + // This means that you have to update the specific attributes of segment n1 according to
  92 + // the specific attributes of segments n1 and n2.
  93 + }
  94 +
  95 +} // end of namespace grm
  96 +
  97 +#endif
... ...
README.md 0 → 100644
... ... @@ -0,0 +1,25 @@
  1 +Summary
  2 +=======
  3 +
  4 +This module provides the GRM OTB application to perform multiscale region-merging segmentation on satellite images.
  5 +Three local homogeneity criteria are available: the Baatz & Schäpe criterion, the Full Lambda Schedule criterion and
  6 +the simple Euclidean Distance criterion.
  7 +
  8 +This application uses the GRM (Generic Region Merging) library which allows to add quickly a new local homogeneity criterion.
  9 +Look at the template header file: GRMSegmenterTemplate.h to see which format you must respect to add a new criterion.
  10 +
  11 +Licence
  12 +=======
  13 +
  14 +Copyright (c) Centre National d'Études Spatiales. All rights reserved.
  15 +
  16 +This is free software under the GPL v3 licence. See http://www.gnu.org/licenses/gpl-3.0.html for details.
  17 +
  18 +This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  19 +
  20 +Contact
  21 +=======
  22 +
  23 +Author: Lassalle Pierre
  24 +email: lassallepierre34@gmail.com
  25 +website: http://pierre33.github.io/
... ...
app/CMakeLists.txt 0 → 100644
... ... @@ -0,0 +1,4 @@
  1 +OTB_CREATE_APPLICATION(NAME GRM
  2 + SOURCES otbGRM.cxx
  3 + LINK_LIBRARIES ${${otb-module}_LIBRARIES}
  4 +)
... ...
app/CMakeLists.txt~ 0 → 100644
... ... @@ -0,0 +1,4 @@
  1 +OTB_CREATE_APPLICATION(NAME GRMSegmentation
  2 + SOURCES otbGRM.cxx
  3 + LINK_LIBRARIES ${${otb-module}_LIBRARIES}
  4 +)
... ...
app/otbGRM.cxx 0 → 100644
... ... @@ -0,0 +1,174 @@
  1 +/*=======================================================================
  2 + Program: ORFEO Toolbox
  3 + Language: C++
  4 + Date: $Date$
  5 + Version: $Revision$
  6 +
  7 + Author: Lassalle Pierre
  8 + Contact: lassallepierre34@gmail.com
  9 + Website: http://pierre33.github.io/
  10 +
  11 + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  12 + See OTBCopyright.txt for details.
  13 +
  14 + This software is distributed WITHOUT ANY WARRANTY; without even
  15 + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  16 + PURPOSE. See the above copyright notices for more information.
  17 +
  18 + =======================================================================*/
  19 +#include "otbImage.h"
  20 +#include "otbVectorImage.h"
  21 +#include "otbImageFileReader.h"
  22 +#include "otbImageFileWriter.h"
  23 +#include "grmSpringSegmenter.h"
  24 +#include "grmFullLambdaScheduleSegmenter.h"
  25 +#include "grmBaatzSegmenter.h"
  26 +#include "otbWrapperApplication.h"
  27 +
  28 +namespace otb
  29 +{
  30 + namespace Wrapper
  31 + {
  32 + class otbGRM : public Application
  33 + {
  34 + public:
  35 + typedef otbGRM Self;
  36 + typedef itk::SmartPointer<Self> Pointer;
  37 +
  38 + typedef FloatVectorImageType ImageType;
  39 + typedef UInt32ImageType LabelImageType;
  40 +
  41 + itkNewMacro(Self);
  42 + itkTypeMacro(otbGRM, otb::Application);
  43 +
  44 + private:
  45 +
  46 + void DoInit()
  47 + {
  48 + SetName("otbGRM");
  49 + SetDescription("This application allows to use the Generic Region Merging library (GRM) and provides currently 3 homogeneity criteria: Euclidean Distance, Full Lambda Schedule and Baatz & Schape criterion.");
  50 +
  51 + AddParameter(ParameterType_InputImage, "in", "Input Image");
  52 + AddParameter(ParameterType_OutputFilename, "out", "Ouput Label Image");
  53 +
  54 + AddParameter(ParameterType_Choice, "criterion", "Homogeneity criterion to use");
  55 + AddChoice("bs", "Baatz & Schape");
  56 + AddChoice("ed", "Euclidean Distance");
  57 + AddChoice("fls", "Full Lambda Schedule");
  58 +
  59 + AddParameter(ParameterType_Float, "threshold", "Threshold for the criterion");
  60 +
  61 + AddParameter(ParameterType_Int, "niter", "Number of iterations");
  62 + SetDefaultParameterFloat("niter", 0);
  63 + MandatoryOff("niter");
  64 +
  65 + AddParameter(ParameterType_Int, "speed", "Activate it to boost the segmentation speed");
  66 + SetDefaultParameterFloat("speed", 0);
  67 + MandatoryOff("speed");
  68 +
  69 + // For Baatz & Schape
  70 + AddParameter(ParameterType_Float, "cw", "Weight for the spectral homogeneity");
  71 + SetDefaultParameterFloat("cw", 0.5);
  72 + MandatoryOff("cw");
  73 + AddParameter(ParameterType_Float, "sw", "Weight for the spatial homogeneity");
  74 + SetDefaultParameterFloat("sw", 0.5);
  75 + MandatoryOff("sw");
  76 + }
  77 +
  78 + void DoUpdateParameters()
  79 + {
  80 + }
  81 +
  82 + void DoExecute()
  83 + {
  84 +
  85 +
  86 + // Mandatory parameters
  87 + // Input Image
  88 + ImageType::Pointer image = GetParameterImage("in");
  89 + image->Update();
  90 +
  91 + // Output label file name.
  92 + const std::string labelImageFileName = GetParameterString("out");
  93 +
  94 + // Criterion selected
  95 + const std::string selectedCriterion = GetParameterString("criterion");
  96 +
  97 + // Threshold
  98 + float threshold = GetParameterFloat("threshold");
  99 +
  100 + const unsigned int niter = GetParameterInt("niter");
  101 + const int speed = GetParameterInt("speed");
  102 +
  103 + typedef otb::ImageFileWriter<LabelImageType> LabelImageWriter;
  104 +
  105 + if(selectedCriterion == "bs")
  106 + {
  107 + const float cw = GetParameterFloat("cw");
  108 + const float sw = GetParameterFloat("sw");
  109 +
  110 + grm::BaatzParam params;
  111 + params.m_SpectralWeight = cw;
  112 + params.m_ShapeWeight = sw;
  113 +
  114 + grm::BaatzSegmenter<ImageType> segmenter;
  115 + segmenter.SetParam(params);
  116 + segmenter.SetThreshold(threshold*threshold);
  117 + segmenter.SetInput(image);
  118 +
  119 + if(niter > 0)
  120 + segmenter.SetNumberOfIterations(niter);
  121 +
  122 + if(speed > 0)
  123 + segmenter.SetDoFastSegmentation(true);
  124 +
  125 + segmenter.Update();
  126 +
  127 +
  128 + LabelImageWriter::Pointer labelWriter = LabelImageWriter::New();
  129 + labelWriter->SetFileName(labelImageFileName);
  130 + labelWriter->SetInput(segmenter.GetLabeledClusteredOutput());
  131 + labelWriter->Update();
  132 + }
  133 + else if(selectedCriterion == "ed")
  134 + {
  135 + grm::SpringSegmenter<ImageType> segmenter;
  136 + segmenter.SetThreshold(threshold);
  137 + segmenter.SetInput(image);
  138 + if(niter > 0)
  139 + segmenter.SetNumberOfIterations(niter);
  140 +
  141 + if(speed > 0)
  142 + segmenter.SetDoFastSegmentation(true);
  143 +
  144 + segmenter.Update();
  145 +
  146 + LabelImageWriter::Pointer labelWriter = LabelImageWriter::New();
  147 + labelWriter->SetFileName(labelImageFileName);
  148 + labelWriter->SetInput(segmenter.GetLabeledClusteredOutput());
  149 + labelWriter->Update();
  150 + }
  151 + else if(selectedCriterion == "fls")
  152 + {
  153 + grm::FullLambdaScheduleSegmenter<ImageType> segmenter;
  154 + segmenter.SetThreshold(threshold);
  155 + segmenter.SetInput(image);
  156 + if(niter > 0)
  157 + segmenter.SetNumberOfIterations(niter);
  158 +
  159 + if(speed > 0)
  160 + segmenter.SetDoFastSegmentation(true);
  161 +
  162 + segmenter.Update();
  163 +
  164 + LabelImageWriter::Pointer labelWriter = LabelImageWriter::New();
  165 + labelWriter->SetFileName(labelImageFileName);
  166 + labelWriter->SetInput(segmenter.GetLabeledClusteredOutput());
  167 + labelWriter->Update();
  168 + }
  169 + }
  170 + };
  171 + } // end of namespace Wrapper
  172 +
  173 +} // end of namespace otb
  174 +
... ...
app/otbGRM.cxx~ 0 → 100644
... ... @@ -0,0 +1,174 @@
  1 +/*=======================================================================
  2 + Program: ORFEO Toolbox
  3 + Language: C++
  4 + Date: $Date$
  5 + Version: $Revision$
  6 +
  7 + Author: Lassalle Pierre
  8 + Contact: lassallepierre34@gmail.com
  9 + Website: http://pierre33.github.io/
  10 +
  11 + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  12 + See OTBCopyright.txt for details.
  13 +
  14 + This software is distributed WITHOUT ANY WARRANTY; without even
  15 + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  16 + PURPOSE. See the above copyright notices for more information.
  17 +
  18 + =======================================================================*/
  19 +#include "otbImage.h"
  20 +#include "otbVectorImage.h"
  21 +#include "otbImageFileReader.h"
  22 +#include "otbImageFileWriter.h"
  23 +#include "grmSpringSegmenter.h"
  24 +#include "grmFullLambdaScheduleSegmenter.h"
  25 +#include "grmBaatzSegmenter.h"
  26 +#include "otbWrapperApplication.h"
  27 +
  28 +namespace otb
  29 +{
  30 + namespace Wrapper
  31 + {
  32 + class otbGRM : public Application
  33 + {
  34 + public:
  35 + typedef otbGRM Self;
  36 + typedef itk::SmartPointer<Self> Pointer;
  37 +
  38 + typedef FloatVectorImageType ImageType;
  39 + typedef UInt32ImageType LabelImageType;
  40 +
  41 + itkNewMacro(Self);
  42 + itkTypeMacro(otbGRM, otb::Application);
  43 +
  44 + private:
  45 +
  46 + void DoInit()
  47 + {
  48 + SetName("otbGRM");
  49 + SetDescription("This application allows to use the Generic Region Merging library (GRM) and provides currently 3 homogeneity criteria: Euclidean Distance, Full Lambda Schedule and Baatz & Schape criterion.");
  50 +
  51 + AddParameter(ParameterType_InputImage, "in", "Input Image");
  52 + AddParameter(ParameterType_OutputFilename, "out", "Ouput Label Image");
  53 +
  54 + AddParameter(ParameterType_Choice, "criterion", "Homogeneity criterion to use");
  55 + AddChoice("bs", "Baatz & Schape");
  56 + AddChoice("ed", "Euclidean Distance");
  57 + AddChoice("fls", "Full Lambda Schedule");
  58 +
  59 + AddParameter(ParameterType_Float, "threshold", "Threshold for the criterion");
  60 +
  61 + AddParameter(ParameterType_Int, "niter", "Number of iterations");
  62 + SetDefaultParameterFloat("niter", 0);
  63 + MandatoryOff("niter");
  64 +
  65 + AddParameter(ParameterType_Int, "speed", "Activate it to boost the segmentation speed");
  66 + SetDefaultParameterFloat("speed", 0);
  67 + MandatoryOff("speed");
  68 +
  69 + // For Baatz & Schape
  70 + AddParameter(ParameterType_Float, "cw", "Weight for the spectral homogeneity");
  71 + SetDefaultParameterFloat("cw", 0.5);
  72 + MandatoryOff("cw");
  73 + AddParameter(ParameterType_Float, "sw", "Weight for the spatial homogeneity");
  74 + SetDefaultParameterFloat("sw", 0.5);
  75 + MandatoryOff("sw");
  76 + }
  77 +
  78 + void DoUpdateParameters()
  79 + {
  80 + }
  81 +
  82 + void DoExecute()
  83 + {
  84 +
  85 +
  86 + // Mandatory parameters
  87 + // Input Image
  88 + ImageType::Pointer image = GetParameterImage("in");
  89 + image->Update();
  90 +
  91 + // Output label file name.
  92 + const std::string labelImageFileName = GetParameterString("out");
  93 +
  94 + // Criterion selected
  95 + const std::string selectedCriterion = GetParameterString("criterion");
  96 +
  97 + // Threshold
  98 + float threshold = GetParameterFloat("threshold");
  99 +
  100 + const unsigned int niter = GetParameterInt("niter");
  101 + const int speed = GetParameterInt("speed");
  102 +
  103 + typedef otb::ImageFileWriter<LabelImageType> LabelImageWriter;
  104 +
  105 + if(selectedCriterion == "bs")
  106 + {
  107 + const float cw = GetParameterFloat("cw");
  108 + const float sw = GetParameterFloat("sw");
  109 +
  110 + grm::BaatzParam params;
  111 + params.m_SpectralWeight = cw;
  112 + params.m_ShapeWeight = sw;
  113 +
  114 + grm::BaatzSegmenter<ImageType> segmenter;
  115 + segmenter.SetParam(params);
  116 + segmenter.SetThreshold(threshold*threshold);
  117 + segmenter.SetInput(image);
  118 +
  119 + if(niter > 0)
  120 + segmenter.SetNumberOfIterations(niter);
  121 +
  122 + if(speed > 0)
  123 + segmenter.SetDoFastSegmentation(true);
  124 +
  125 + segmenter.Update();
  126 +
  127 +
  128 + LabelImageWriter::Pointer labelWriter = LabelImageWriter::New();
  129 + labelWriter->SetFileName(labelImageFileName);
  130 + labelWriter->SetInput(segmenter.GetLabeledClusteredOutput());
  131 + labelWriter->Update();
  132 + }
  133 + else if(selectedCriterion == "ed")
  134 + {
  135 + grm::SpringSegmenter<ImageType> segmenter;
  136 + segmenter.SetThreshold(threshold);
  137 + segmenter.SetInput(image);
  138 + if(niter > 0)
  139 + segmenter.SetNumberOfIterations(niter);
  140 +
  141 + if(speed > 0)
  142 + segmenter.SetDoFastSegmentation(true);
  143 +
  144 + segmenter.Update();
  145 +
  146 + LabelImageWriter::Pointer labelWriter = LabelImageWriter::New();
  147 + labelWriter->SetFileName(labelImageFileName);
  148 + labelWriter->SetInput(segmenter.GetLabeledClusteredOutput());
  149 + labelWriter->Update();
  150 + }
  151 + else if(selectedCriterion == "fls")
  152 + {
  153 + grm::FullLambdaScheduleSegmenter<ImageType> segmenter;
  154 + segmenter.SetThreshold(threshold);
  155 + segmenter.SetInput(image);
  156 + if(niter > 0)
  157 + segmenter.SetNumberOfIterations(niter);
  158 +
  159 + if(speed > 0)
  160 + segmenter.SetDoFastSegmentation(true);
  161 +
  162 + segmenter.Update();
  163 +
  164 + LabelImageWriter::Pointer labelWriter = LabelImageWriter::New();
  165 + labelWriter->SetFileName(labelImageFileName);
  166 + labelWriter->SetInput(segmenter.GetLabeledClusteredOutput());
  167 + labelWriter->Update();
  168 + }
  169 + }
  170 + };
  171 + } // end of namespace Wrapper
  172 +
  173 +} // end of namespace otb
  174 +
... ...
grm-copyright.txt 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +author: Lassalle Pierre
  2 +
  3 +Copyright (c) Centre National d'Études Spatiales. All rights reserved.
  4 +
  5 +This work has been funded by CNES, CS Systèmes d'Information,
  6 +Université Paul Sabatier Toulouse III, and CNRS,
  7 +in the frame of the PHD thesis of Pierre Lassalle.
... ...
otb-module.cmake 0 → 100644
... ... @@ -0,0 +1,16 @@
  1 +set(DOCUMENTATION "GRM OTB Application for region merging segmentation of very high resolution satellite scenes.")
  2 +
  3 +# define the dependencies of the include module and the tests
  4 +otb_module(otbGRM
  5 + DEPENDS
  6 + OTBCommon
  7 + OTBApplicationEngine
  8 + OTBStreaming
  9 + OTBExtendedFilename
  10 + OTBImageIO
  11 + TEST_DEPENDS
  12 + OTBTestKernel
  13 + OTBCommandLine
  14 + DESCRIPTION
  15 + "${DOCUMENTATION}"
  16 +)
... ...
src/CMakeLists.txt 0 → 100644
... ... @@ -0,0 +1,14 @@
  1 +set(${otb-module}_SRC
  2 + grmBaatzSegmenter.txx
  3 + grmFullLambdaScheduleSegmenter.txx
  4 + grmGraphOperations.txx
  5 + grmGraphToOtbImage.txx
  6 + grmNeighborhood.cxx
  7 + grmSpringSegmenter.txx
  8 + lpContour.cxx
  9 +)
  10 +
  11 +add_library(${otb-module} ${${otb-module}_SRC})
  12 +target_link_libraries(${otb_module} ${OTBCommon_LIBRARIES})
  13 +
  14 +otb_module_target(${otb-module})
... ...
src/grmBaatzSegmenter.h 0 → 100644
... ... @@ -0,0 +1,63 @@
  1 +/*=========================================================================
  2 +
  3 + Program: Generic Region Merging Library
  4 + Language: C++
  5 + author: Lassalle Pierre
  6 + contact: lassallepierre34@gmail.com
  7 +
  8 +
  9 +
  10 + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved
  11 +
  12 +
  13 + This software is distributed WITHOUT ANY WARRANTY; without even
  14 + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15 + PURPOSE. See the above copyright notices for more information.
  16 +
  17 +=========================================================================*/
  18 +#ifndef __GRM_BAATZ_SEGMENTER_H
  19 +#define __GRM_BAATZ_SEGMENTER_H
  20 +#include "grmSegmenter.h"
  21 +
  22 +namespace grm
  23 +{
  24 + struct BaatzNode : Node<BaatzNode>
  25 + {
  26 + std::vector<float> m_Means;
  27 + std::vector<float> m_SquareMeans;
  28 + std::vector<float> m_SpectralSum;
  29 + std::vector<float> m_Std;
  30 + };
  31 +
  32 + struct BaatzParam
  33 + {
  34 + float m_SpectralWeight;
  35 + float m_ShapeWeight;
  36 + };
  37 +
  38 + template<class TImage>
  39 + class BaatzSegmenter : public Segmenter< TImage, BaatzNode, BaatzParam>
  40 + {
  41 + public:
  42 +
  43 + /* Some convenient typedefs */
  44 + typedef Segmenter<TImage, BaatzNode, BaatzParam> Superclass;
  45 + typedef TImage ImageType;
  46 + typedef BaatzParam ParameterType;
  47 + typedef typename Superclass::GraphType GraphType;
  48 + typedef BaatzNode NodeType;
  49 + typedef typename Superclass::EdgeType EdgeType;
  50 + typedef typename Superclass::NodePointerType NodePointerType;
  51 + typedef typename Superclass::GraphOperatorType GraphOperatorType;
  52 + typedef GraphToOtbImage<GraphType> IOType;
  53 +
  54 + float ComputeMergingCost(NodePointerType n1, NodePointerType n2);
  55 + void UpdateSpecificAttributes(NodePointerType n1, NodePointerType n2);
  56 + void InitFromImage();
  57 + };
  58 +} // end of namespace grm
  59 +#include "grmBaatzSegmenter.txx"
  60 +#endif
  61 +
  62 +
  63 +
... ...
src/grmBaatzSegmenter.txx 0 → 100644
... ... @@ -0,0 +1,126 @@
  1 +/*=========================================================================
  2 +
  3 + Program: Generic Region Merging Library
  4 + Language: C++
  5 + author: Lassalle Pierre
  6 + contact: lassallepierre34@gmail.com
  7 +
  8 +
  9 +
  10 + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved
  11 +
  12 +
  13 + This software is distributed WITHOUT ANY WARRANTY; without even
  14 + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15 + PURPOSE. See the above copyright notices for more information.
  16 +
  17 +=========================================================================*/
  18 +#ifndef __GRM_BAATZ_SEGMENTER_TXX
  19 +#define __GRM_BAATZ_SEGMENTER_TXX
  20 +#include <otbImageFileReader.h>
  21 +#include <itkImageRegionIterator.h>
  22 +
  23 +namespace grm
  24 +{
  25 +
  26 + template<class TImage>
  27 + void
  28 + BaatzSegmenter<TImage>::InitFromImage()
  29 + {
  30 + typedef itk::ImageRegionIterator<TImage> ImageIterator;
  31 +
  32 + this->m_ImageWidth = this->m_InputImage->GetLargestPossibleRegion().GetSize()[0];
  33 + this->m_ImageHeight =this->m_InputImage->GetLargestPossibleRegion().GetSize()[1];
  34 + this->m_NumberOfComponentsPerPixel = this->m_InputImage->GetNumberOfComponentsPerPixel();
  35 +
  36 + std::size_t idx = 0;
  37 + ImageIterator it(this->m_InputImage, this->m_InputImage->GetLargestPossibleRegion());
  38 + for(it.GoToBegin(); !it.IsAtEnd(); ++it)
  39 + {
  40 + this->m_Graph.m_Nodes[idx]->m_Means.reserve(this->m_NumberOfComponentsPerPixel);
  41 + this->m_Graph.m_Nodes[idx]->m_SquareMeans.reserve(this->m_NumberOfComponentsPerPixel);
  42 + this->m_Graph.m_Nodes[idx]->m_SpectralSum.reserve(this->m_NumberOfComponentsPerPixel);
  43 + this->m_Graph.m_Nodes[idx]->m_Std.assign(this->m_NumberOfComponentsPerPixel, 0.0f);
  44 +
  45 + for(std::size_t b = 0; b < this->m_NumberOfComponentsPerPixel; ++b)
  46 + {
  47 + this->m_Graph.m_Nodes[idx]->m_Means.push_back(it.Get()[b]);
  48 + this->m_Graph.m_Nodes[idx]->m_SquareMeans.push_back((it.Get()[b])*(it.Get()[b]));
  49 + this->m_Graph.m_Nodes[idx]->m_SpectralSum.push_back(it.Get()[b]);
  50 + }
  51 + ++idx;
  52 + }
  53 + }
  54 +
  55 + template<class TImage>
  56 + float
  57 + BaatzSegmenter<TImage>::ComputeMergingCost(NodePointerType n1, NodePointerType n2)
  58 + {
  59 + const unsigned int a1 = n1->m_Area, a2 = n2->m_Area, a_sum = a1 + a2;
  60 +
  61 + float spect_cost = 0.0f;
  62 + float mean, square_mean, sum, std;
  63 +
  64 + for (unsigned int b = 0; b < this->m_NumberOfComponentsPerPixel; b++)
  65 + {
  66 + mean = ((a1 * n1->m_Means[b]) + (a2 * n2->m_Means[b])) / a_sum;
  67 + square_mean = n1->m_SquareMeans[b] + n2->m_SquareMeans[b];
  68 + sum = n1->m_SpectralSum[b] + n2->m_SpectralSum[b];
  69 + std = std::sqrt((square_mean - 2*mean*sum + a_sum * mean* mean) / a_sum);
  70 + spect_cost += (a_sum * std - a1 * n1->m_Std[b] - a2 * n2->m_Std[b]);
  71 + }
  72 + spect_cost *= this->m_Param.m_ShapeWeight;
  73 +
  74 + if(spect_cost < this->m_Threshold)
  75 + {
  76 + float shape_cost, smooth_f, compact_f;
  77 +
  78 + // Compute the shape merging cost
  79 + const float p1 = static_cast<float>(n1->m_Perimeter);
  80 + const float p2 = static_cast<float>(n2->m_Perimeter);
  81 + const unsigned int boundary = (GraphOperatorType::FindEdge(n1, n2))->m_Boundary;
  82 + const float p3 = p1 + p2 - 2 * static_cast<float>(boundary);
  83 +
  84 + const lp::BoundingBox merged_bbox = lp::ContourOperations::MergeBoundingBoxes(n1->m_Bbox, n2->m_Bbox);
  85 + const float bb1_perimeter = static_cast<float>(2*n1->m_Bbox.m_W + 2*n1->m_Bbox.m_H);
  86 + const float bb2_perimeter = static_cast<float>(2*n2->m_Bbox.m_W + 2*n2->m_Bbox.m_H);
  87 + const float mbb_perimeter = static_cast<float>(2 * merged_bbox.m_W + 2 * merged_bbox.m_H);
  88 +
  89 + smooth_f = a_sum*p3/mbb_perimeter - a1*p1/bb1_perimeter - a2*p2/bb2_perimeter;
  90 + compact_f = a_sum*p3/std::sqrt(a_sum) - a1*p1/std::sqrt(a1) - a2*p2/std::sqrt(a2);
  91 +
  92 + shape_cost = this->m_Param.m_ShapeWeight * compact_f + (1-this->m_Param.m_ShapeWeight) * smooth_f;
  93 +
  94 + return (spect_cost + (1-this->m_Param.m_ShapeWeight)*shape_cost);
  95 + }
  96 + else
  97 + return spect_cost;
  98 + }
  99 +
  100 + template<class TImage>
  101 + void
  102 + BaatzSegmenter<TImage>::UpdateSpecificAttributes(NodePointerType n1, NodePointerType n2)
  103 + {
  104 + const float a1 = static_cast<float>(n1->m_Area);
  105 + const float a2 = static_cast<float>(n2->m_Area);
  106 + const float a_sum = a1 + a2;
  107 +
  108 + for(unsigned int b = 0; b < this->m_NumberOfComponentsPerPixel; ++b)
  109 + {
  110 + n1->m_Means[b] = (a1 * n1->m_Means[b] + a2 * n2->m_Means[b]) / a_sum;
  111 + n1->m_SquareMeans[b] += n2->m_SquareMeans[b];
  112 + n1->m_SpectralSum[b] += n2->m_SpectralSum[b];
  113 + n1->m_Std[b] = std::sqrt((n1->m_SquareMeans[b] - 2 * n1->m_Means[b] * n1->m_SpectralSum[b] +
  114 + a_sum * n1->m_Means[b] * n1->m_Means[b]) / a_sum);
  115 + }
  116 + }
  117 +} // end of namespace grm
  118 +
  119 +#endif
  120 +
  121 +
  122 +
  123 +
  124 +
  125 +
  126 +
... ...
src/grmDataStructures.h 0 → 100644
... ... @@ -0,0 +1,63 @@
  1 +/*=========================================================================
  2 +
  3 + Program: Generic Region Merging Library
  4 + Language: C++
  5 + author: Lassalle Pierre
  6 + contact: lassallepierre34@gmail.com
  7 +
  8 +
  9 +
  10 + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved
  11 +
  12 +
  13 + This software is distributed WITHOUT ANY WARRANTY; without even
  14 + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15 + PURPOSE. See the above copyright notices for more information.
  16 +
  17 +=========================================================================*/
  18 +#ifndef __GRM_DATA_STRUCTURES_H
  19 +#define __GRM_DATA_STRUCTURES_H
  20 +#include <stdexcept>
  21 +#include <bitset>
  22 +#include <vector>
  23 +
  24 +namespace grm
  25 +{
  26 +
  27 + struct BoundingBox
  28 + {
  29 + /* X coordinate of the upper left. */
  30 + long unsigned int m_UX;
  31 +
  32 + /* Y coordinate of the upper left. */
  33 + long unsigned int m_UY;
  34 +
  35 + /* Width */
  36 + unsigned int m_W;
  37 +
  38 + /* Height */
  39 + unsigned int m_H;
  40 + };
  41 +
  42 + BoundingBox MergeBoundingBoxes(const BoundingBox& bb1,
  43 + const BoundingBox& bb2)
  44 + {
  45 + long unsigned int min_ux, min_uy, max_xw, max_yh;
  46 + BoundingBox bb;
  47 +
  48 + min_ux = std::min(bb1.m_UX, bb2.m_UX);
  49 + min_uy = std::min(bb1.m_UY, bb2.m_UY);
  50 + max_xw = std::max(bb1.m_UX + bb1.m_W, bb2.m_UX + bb2.m_W);
  51 + max_yh = std::max(bb1.m_UY + bb1.m_H, bb2.m_UY + bb2.m_H);
  52 +
  53 + bb.m_UX = min_ux;
  54 + bb.m_UY = min_uy;
  55 + bb.m_W = max_xw - min_ux;
  56 + bb.m_H = max_yh - min_uy;
  57 +
  58 + return bb;
  59 + }
  60 +
  61 +} // end of namespace grm
  62 +
  63 +#endif
... ...
src/grmFullLambdaScheduleSegmenter.h 0 → 100644
... ... @@ -0,0 +1,50 @@
  1 +/*=========================================================================
  2 +
  3 + Program: Generic Region Merging Library
  4 + Language: C++
  5 + author: Lassalle Pierre
  6 + contact: lassallepierre34@gmail.com
  7 +
  8 +
  9 +
  10 + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved
  11 +
  12 +
  13 + This software is distributed WITHOUT ANY WARRANTY; without even
  14 + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15 + PURPOSE. See the above copyright notices for more information.
  16 +
  17 +=========================================================================*/
  18 +#ifndef __GRM_FULL_LAMBDA_SCHEDULE_SEGMENTER_H
  19 +#define __GRM_FULL_LAMBDA_SCHEDULE_SEGMENTER_H
  20 +#include "grmSegmenter.h"
  21 +
  22 +namespace grm
  23 +{
  24 + struct FLSNode : Node<FLSNode>
  25 + {
  26 + std::vector<float> m_Means;
  27 + };
  28 +
  29 + struct FLSParam{};
  30 +
  31 + template<class TImage>
  32 + class FullLambdaScheduleSegmenter : public Segmenter< TImage, FLSNode, FLSParam>
  33 + {
  34 + public:
  35 + /* Some convenient typedefs */
  36 + typedef Segmenter<TImage, FLSNode, FLSParam> Superclass;
  37 + typedef TImage ImageType;
  38 + typedef typename Superclass::GraphType GraphType;
  39 + typedef typename Superclass::NodePointerType NodePointerType;
  40 + typedef typename Superclass::GraphOperatorType GraphOperatorType;
  41 + typedef GraphToOtbImage<GraphType> IOType;
  42 +
  43 + float ComputeMergingCost(NodePointerType n1, NodePointerType n2);
  44 + void UpdateSpecificAttributes(NodePointerType n1, NodePointerType n2);
  45 + void InitFromImage();
  46 + };
  47 +} // end of namespace grm
  48 +#include "grmFullLambdaScheduleSegmenter.txx"
  49 +#endif
  50 +
... ...
src/grmFullLambdaScheduleSegmenter.txx 0 → 100644
... ... @@ -0,0 +1,84 @@
  1 +/*=========================================================================
  2 +
  3 + Program: Generic Region Merging Library
  4 + Language: C++
  5 + author: Lassalle Pierre
  6 + contact: lassallepierre34@gmail.com
  7 +
  8 +
  9 +
  10 + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved
  11 +
  12 +
  13 + This software is distributed WITHOUT ANY WARRANTY; without even
  14 + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15 + PURPOSE. See the above copyright notices for more information.
  16 +
  17 +=========================================================================*/
  18 +#ifndef __GRM_FULL_LAMBDA_SCHEDULE_SEGMENTER_TXX
  19 +#define __GRM_FULL_LAMBDA_SCHEDULE_SEGMENTER_TXX
  20 +
  21 +namespace grm
  22 +{
  23 + template<class TImage>
  24 + void
  25 + FullLambdaScheduleSegmenter<TImage>::InitFromImage()
  26 + {
  27 + typedef itk::ImageRegionIterator<TImage> ImageIterator;
  28 +
  29 + this->m_ImageWidth = this->m_InputImage->GetLargestPossibleRegion().GetSize()[0];
  30 + this->m_ImageHeight =this->m_InputImage->GetLargestPossibleRegion().GetSize()[1];
  31 + this->m_NumberOfComponentsPerPixel = this->m_InputImage->GetNumberOfComponentsPerPixel();
  32 +
  33 + std::size_t idx = 0;
  34 + ImageIterator it(this->m_InputImage, this->m_InputImage->GetLargestPossibleRegion());
  35 + for(it.GoToBegin(); !it.IsAtEnd(); ++it)
  36 + {
  37 + this->m_Graph.m_Nodes[idx]->m_Means.reserve(this->m_NumberOfComponentsPerPixel);
  38 +
  39 + for(std::size_t b = 0; b < this->m_NumberOfComponentsPerPixel; ++b)
  40 + {
  41 + this->m_Graph.m_Nodes[idx]->m_Means.push_back(it.Get()[b]);
  42 + }
  43 + ++idx;
  44 + }
  45 + }
  46 +
  47 + template<class TImage>
  48 + float
  49 + FullLambdaScheduleSegmenter<TImage>::ComputeMergingCost(NodePointerType n1, NodePointerType n2)
  50 + {
  51 + float eucDist = 0.0;
  52 + const float a1 = static_cast<float>(n1->m_Area);
  53 + const float a2 = static_cast<float>(n2->m_Area);
  54 + const float a_sum = a1 + a2;
  55 +
  56 + for(unsigned int b = 0; b < this->m_NumberOfComponentsPerPixel; b++)
  57 + {
  58 + eucDist += (n1->m_Means[b] - n2->m_Means[b])*(n1->m_Means[b] - n2->m_Means[b]);
  59 + }
  60 +
  61 + // Retrieve the length of the boundary between n1 and n2
  62 + auto toN2 = GraphOperatorType::FindEdge(n1, n2);
  63 +
  64 + float cost = (((a1*a2)/a_sum)*eucDist) / (static_cast<float>(toN2->m_Boundary));
  65 +
  66 + return cost;
  67 + }
  68 +
  69 + template<class TImage>
  70 + void
  71 + FullLambdaScheduleSegmenter<TImage>::UpdateSpecificAttributes(NodePointerType n1, NodePointerType n2)
  72 + {
  73 + const float a1 = static_cast<float>(n1->m_Area);
  74 + const float a2 = static_cast<float>(n2->m_Area);
  75 + const float a_sum = a1 + a2;
  76 +
  77 + for(unsigned int b = 0; b < this->m_NumberOfComponentsPerPixel; ++b)
  78 + {
  79 + n1->m_Means[b] = (a1 * n1->m_Means[b] + a2 * n2->m_Means[b]) / a_sum;
  80 + }
  81 + }
  82 +} // end of namespace grm
  83 +
  84 +#endif
... ...
src/grmGraph.h 0 → 100644
... ... @@ -0,0 +1,108 @@
  1 +/*=========================================================================
  2 +
  3 + Program: Generic Region Merging Library
  4 + Language: C++
  5 + author: Lassalle Pierre
  6 + contact: lassallepierre34@gmail.com