Commit 60b9057ad7d4638414446b1a10e67aad2f74e591

Authored by Pierre Lassalle
1 parent 98a7cf2f
Exists in master

Generic Region Merging format

CMakeLists.txt
... ... @@ -21,12 +21,12 @@ else()
21 21 message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
22 22 endif()
23 23  
24   -set(GRM_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/)
  24 +#set(GRM_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/)
25 25  
26   -include_directories(${GRM_INCLUDE_DIR})
  26 +#include_directories(${GRM_INCLUDE_DIR})
27 27  
28   -project(GRM)
  28 +project(OTBGRM)
29 29  
30   -set(GRM_LIBRARIES GRM)
  30 +set(OTBGRM_LIBRARIES OTBGRM)
31 31  
32 32 otb_module_impl()
... ...
app/CMakeLists.txt
1   -OTB_CREATE_APPLICATION(NAME otbGRM
2   - SOURCES otbGRM.cxx
3   - LINK_LIBRARIES ${${otb-module}_LIBRARIES}
  1 +OTB_CREATE_APPLICATION(NAME GenericRegionMerging
  2 + SOURCES GenericRegionMerging.cxx
  3 + LINK_LIBRARIES ${OTBGRM_LIBRARIES}
4 4 )
... ...
app/GenericRegionMerging.cxx 0 → 100644
... ... @@ -0,0 +1,176 @@
  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 +#include "otbWrapperApplicationFactory.h"
  28 +
  29 +namespace otb
  30 +{
  31 + namespace Wrapper
  32 + {
  33 + class GenericRegionMerging : public Application
  34 + {
  35 + public:
  36 + typedef GenericRegionMerging Self;
  37 + typedef itk::SmartPointer<Self> Pointer;
  38 +
  39 + typedef FloatVectorImageType ImageType;
  40 + typedef UInt32ImageType LabelImageType;
  41 +
  42 + itkNewMacro(Self);
  43 + itkTypeMacro(GenericRegionMerging, otb::Application);
  44 +
  45 + private:
  46 +
  47 + void DoInit()
  48 + {
  49 + SetName("GenericRegionMerging");
  50 + 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.");
  51 +
  52 + AddParameter(ParameterType_InputImage, "in", "Input Image");
  53 + AddParameter(ParameterType_OutputImage, "out", "Ouput Label Image");
  54 +
  55 + AddParameter(ParameterType_Choice, "criterion", "Homogeneity criterion to use");
  56 + AddChoice("criterion.bs", "Baatz & Schape");
  57 + AddChoice("criterion.ed", "Euclidean Distance");
  58 + AddChoice("criterion.fls", "Full Lambda Schedule");
  59 +
  60 + AddParameter(ParameterType_Float, "threshold", "Threshold for the criterion");
  61 +
  62 + AddParameter(ParameterType_Int, "niter", "Number of iterations");
  63 + SetDefaultParameterInt("niter", 0);
  64 + MandatoryOff("niter");
  65 +
  66 + AddParameter(ParameterType_Int, "speed", "Activate it to boost the segmentation speed");
  67 + SetDefaultParameterInt("speed", 0);
  68 + MandatoryOff("speed");
  69 +
  70 + // For Baatz & Schape
  71 + AddParameter(ParameterType_Float, "cw", "Weight for the spectral homogeneity");
  72 + SetDefaultParameterFloat("cw", 0.5);
  73 + MandatoryOff("cw");
  74 + AddParameter(ParameterType_Float, "sw", "Weight for the spatial homogeneity");
  75 + SetDefaultParameterFloat("sw", 0.5);
  76 + MandatoryOff("sw");
  77 + }
  78 +
  79 + void DoUpdateParameters()
  80 + {
  81 + }
  82 +
  83 + void DoExecute()
  84 + {
  85 +
  86 +
  87 + // Mandatory parameters
  88 + // Input Image
  89 + ImageType::Pointer image = GetParameterImage("in");
  90 + image->Update();
  91 +
  92 + // Output label file name.
  93 + const std::string labelImageFileName = GetParameterString("out");
  94 +
  95 + // Criterion selected
  96 + const std::string selectedCriterion = GetParameterString("criterion");
  97 +
  98 + // Threshold
  99 + float threshold = GetParameterFloat("threshold");
  100 +
  101 + const unsigned int niter = GetParameterInt("niter");
  102 + const int speed = GetParameterInt("speed");
  103 +
  104 + typedef otb::ImageFileWriter<LabelImageType> LabelImageWriter;
  105 +
  106 + if(selectedCriterion == "bs")
  107 + {
  108 + const float cw = GetParameterFloat("cw");
  109 + const float sw = GetParameterFloat("sw");
  110 +
  111 + grm::BaatzParam params;
  112 + params.m_SpectralWeight = cw;
  113 + params.m_ShapeWeight = sw;
  114 +
  115 + grm::BaatzSegmenter<ImageType> segmenter;
  116 + segmenter.SetParam(params);
  117 + segmenter.SetThreshold(threshold*threshold);
  118 + segmenter.SetInput(image);
  119 +
  120 + if(niter > 0)
  121 + segmenter.SetNumberOfIterations(niter);
  122 +
  123 + if(speed > 0)
  124 + segmenter.SetDoFastSegmentation(true);
  125 +
  126 + segmenter.Update();
  127 +
  128 +
  129 + LabelImageWriter::Pointer labelWriter = LabelImageWriter::New();
  130 + labelWriter->SetFileName(labelImageFileName);
  131 + labelWriter->SetInput(segmenter.GetLabeledClusteredOutput());
  132 + labelWriter->Update();
  133 + }
  134 + else if(selectedCriterion == "ed")
  135 + {
  136 + grm::SpringSegmenter<ImageType> segmenter;
  137 + segmenter.SetThreshold(threshold);
  138 + segmenter.SetInput(image);
  139 + if(niter > 0)
  140 + segmenter.SetNumberOfIterations(niter);
  141 +
  142 + if(speed > 0)
  143 + segmenter.SetDoFastSegmentation(true);
  144 +
  145 + segmenter.Update();
  146 +
  147 + LabelImageWriter::Pointer labelWriter = LabelImageWriter::New();
  148 + labelWriter->SetFileName(labelImageFileName);
  149 + labelWriter->SetInput(segmenter.GetLabeledClusteredOutput());
  150 + labelWriter->Update();
  151 + }
  152 + else if(selectedCriterion == "fls")
  153 + {
  154 + grm::FullLambdaScheduleSegmenter<ImageType> segmenter;
  155 + segmenter.SetThreshold(threshold);
  156 + segmenter.SetInput(image);
  157 + if(niter > 0)
  158 + segmenter.SetNumberOfIterations(niter);
  159 +
  160 + if(speed > 0)
  161 + segmenter.SetDoFastSegmentation(true);
  162 +
  163 + segmenter.Update();
  164 +
  165 + LabelImageWriter::Pointer labelWriter = LabelImageWriter::New();
  166 + labelWriter->SetFileName(labelImageFileName);
  167 + labelWriter->SetInput(segmenter.GetLabeledClusteredOutput());
  168 + labelWriter->Update();
  169 + }
  170 + }
  171 + };
  172 + } // end of namespace Wrapper
  173 +
  174 +} // end of namespace otb
  175 +
  176 +OTB_APPLICATION_EXPORT(otb::Wrapper::GenericRegionMerging)
... ...
app/otbGRM.cxx
... ... @@ -1,175 +0,0 @@
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("criterion.bs", "Baatz & Schape");
56   - AddChoice("criterion.ed", "Euclidean Distance");
57   - AddChoice("criterion.fls", "Full Lambda Schedule");
58   -
59   - AddParameter(ParameterType_Float, "threshold", "Threshold for the criterion");
60   -
61   - AddParameter(ParameterType_Int, "niter", "Number of iterations");
62   - SetDefaultParameterInt("niter", 0);
63   - MandatoryOff("niter");
64   -
65   - AddParameter(ParameterType_Int, "speed", "Activate it to boost the segmentation speed");
66   - SetDefaultParameterInt("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   -
175   -OTB_APPLICATION_EXPORT(otb::Wrapper::otbGRM)
include/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 +
... ...
include/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 +
... ...
include/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
... ...
include/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 +
... ...
include/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
... ...
include/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
  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_GRAPH_H
  19 +#define __GRM_GRAPH_H
  20 +#include "grmDataStructures.h"
  21 +#include "lpContour.h"
  22 +
  23 +namespace grm
  24 +{
  25 + struct BaseNode
  26 + {
  27 + /* Node already merged. */
  28 + bool m_Valid;
  29 +
  30 + /* Node has to be removed from the graph. */
  31 + bool m_Expired;
  32 +
  33 + /* Does the node merge at the previous iteration */
  34 + bool m_IsMerged;
  35 +
  36 + /* Perimeter of the region */
  37 + unsigned int m_Perimeter;
  38 +
  39 + /* Area (number of inner pixels) of the region */
  40 + unsigned int m_Area;
  41 +
  42 + /*
  43 + Node is identified by the location
  44 + of the first pixel of the region.
  45 + */
  46 + long unsigned int m_Id;
  47 +
  48 + /*
  49 + Bounding box of the region
  50 + in the image.
  51 + */
  52 + lp::BoundingBox m_Bbox;
  53 +
  54 + /* Contour of the shape */
  55 + lp::Contour m_Contour;
  56 + };
  57 +
  58 + template<class DerivedNode>
  59 + struct NeighborType
  60 + {
  61 + typedef std::weak_ptr<DerivedNode> WeakDerived;
  62 + typedef std::shared_ptr<DerivedNode> SharedDerived;
  63 +
  64 + WeakDerived m_Target;
  65 + float m_Cost;
  66 + unsigned int m_Boundary;
  67 + bool m_CostUpdated;
  68 +
  69 + NeighborType(WeakDerived ptr, double w, unsigned int c) :
  70 + m_Target(ptr), m_Cost(w), m_Boundary(c), m_CostUpdated(false) {}
  71 +
  72 + inline SharedDerived GetRegion()
  73 + {
  74 + SharedDerived ptr(m_Target.lock());
  75 + if(!ptr)
  76 + throw std::runtime_error("NeighborType::GetRegion - Region pointer is not valid");
  77 + return ptr;
  78 + }
  79 + };
  80 +
  81 +
  82 + template<class DerivedNode>
  83 + struct Node : BaseNode
  84 + {
  85 + typedef NeighborType<DerivedNode> CRPTNeighborType;
  86 + std::vector<CRPTNeighborType> m_Edges;
  87 + };
  88 +
  89 + template<class TNode>
  90 + struct Graph
  91 + {
  92 + typedef TNode NodeType;
  93 + typedef std::shared_ptr<NodeType> NodePointerType;
  94 + typedef typename NodeType::CRPTNeighborType EdgeType;
  95 + typedef std::vector<NodePointerType> NodeListType;
  96 + typedef typename NodeListType::iterator NodeIteratorType;
  97 + typedef typename NodeListType::const_iterator NodeConstIteratorType;
  98 + typedef std::vector<EdgeType> EdgeListType;
  99 + typedef typename EdgeListType::iterator EdgeIteratorType;
  100 + typedef typename EdgeListType::const_iterator EdgeConstIteratorType;
  101 +
  102 + std::vector< NodePointerType > m_Nodes;
  103 + };
  104 +
  105 +} // end of namespace grm
  106 +#endif
  107 +
  108 +
... ...
include/grmGraphOperations.h 0 → 100644
... ... @@ -0,0 +1,210 @@
  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_GRAPH_OPERATIONS_H
  19 +#define __GRM_GRAPH_OPERATIONS_H
  20 +#include "grmGraph.h"
  21 +#include "grmNeighborhood.h"
  22 +#include <iostream>
  23 +#include <cassert>
  24 +#include <limits>
  25 +#include <map>
  26 +#include <utility>
  27 +#include <set>
  28 +#include <random>
  29 +#include <numeric>
  30 +
  31 +namespace grm
  32 +{
  33 + template<class TSegmenter>
  34 + class GraphOperations
  35 + {
  36 + public:
  37 +
  38 + /* Some convenient typedefs */
  39 + typedef TSegmenter SegmenterType;
  40 + typedef typename SegmenterType::ImageType ImageType;
  41 + typedef typename SegmenterType::GraphType GraphType;
  42 + typedef typename GraphType::NodeType NodeType;
  43 + typedef typename GraphType::EdgeType EdgeType;
  44 + typedef typename GraphType::NodePointerType NodePointerType;
  45 + typedef typename GraphType::NodeListType NodeList;
  46 + typedef typename GraphType::NodeIteratorType NodeIterator;
  47 + typedef typename GraphType::NodeConstIteratorType NodeConstIterator;
  48 + typedef typename GraphType::EdgeListType EdgeList;
  49 + typedef typename GraphType::EdgeIteratorType EdgeIterator;
  50 + typedef typename GraphType::EdgeConstIteratorType EdgeConstIterator;
  51 +
  52 + using ContourOperator = lp::ContourOperations;
  53 +
  54 +
  55 + /*
  56 + * Given the size of the input image and the mask of the
  57 + * neighborhood, we initialize a new graph of nodes
  58 + *
  59 + * @params:
  60 + * GraphType& graph: reference to a graph of nodes
  61 + * const unsigned int width: width of the input image
  62 + * const unsigned int height: height of the input image
  63 + * CONNECTIVITY mask : mask of the neighborhood (4X4 or 8X8)
  64 + */
  65 + static void InitNodes(ImageType * inputImg,
  66 + SegmenterType& seg,
  67 + CONNECTIVITY mask);
  68 +
  69 + /*
  70 + * Given a graph of nodes, we explore all the nodes
  71 + * and for each node we compute his merging costs
  72 + * with all its neighboring nodes given a function
  73 + * to compute the merging cost between two nodes.
  74 + *
  75 + * @params:
  76 + * GraphType& graph: reference to the graph of nodes
  77 + * float(*fptr)(NodeType*, NodeType*): pointer to the function
  78 + * to compute the merging cost between two adjacent nodes.
  79 + */
  80 + static void UpdateMergingCosts(SegmenterType& seg);
  81 +
  82 + /*
  83 + * Given a node A, we analyse its best node B.
  84 + * If the node A is also node B's best node
  85 + * then it returns a pointer to node B if node A 's id
  86 + * is smaller or a pointer to node A if node B's id is
  87 + * smaller
  88 + * else it returns a null pointer.
  89 + * (Local Mutual Best Fitting Heuristic)
  90 + *
  91 + * @params:
  92 + * NodeType * a : Pointer to the node A
  93 + * float t : threshold of the criterion
  94 + */
  95 + static NodePointerType CheckLMBF(NodePointerType, float t);
  96 +
  97 + /*
  98 + * Given a node A, we analyse its best node B.
  99 + * If the criterion is checked and the node B
  100 + * is valid then it returns a pointer to the
  101 + * node A if node's A id is smaller or a pointer
  102 + * to node B if node B's id is smaller
  103 + * else it returns a null pointer.
  104 + *
  105 + * @params:
  106 + * NodeType * a : pointer to node A
  107 + * float t : threshold of the criterion
  108 + */
  109 + static NodePointerType CheckBF(NodePointerType a, float t);
  110 +
  111 + /*
  112 + * Given the current node and the target node, it returns
  113 + * the edge from the current node targeting to the target
  114 + * node.
  115 + *
  116 + * @params
  117 + * const NodeType * n : pointer to the current node.
  118 + * const NodeType * target : pointer to the target node.
  119 + * @return an iterator pointing to the candidate edge.
  120 + */
  121 + static EdgeIterator FindEdge(NodePointerType n, NodePointerType target);
  122 +
  123 + /*
  124 + * Given a node a and the node b to be merged into node a,
  125 + * it updates the neighbors of node a with respect to the
  126 + * neighbors of node b.
  127 + *
  128 + * @params
  129 + * NodeType * a : pointer to node a.
  130 + * NodeType * b : pointer to node b.
  131 + */
  132 + static void UpdateNeighbors(NodePointerType a, NodePointerType b);
  133 +
  134 + /*
  135 + * Given 2 nodes A and B (node B being merged into node A)
  136 + * we update the internal attributes of node A with respect
  137 + * to node B.
  138 + *
  139 + * @params:
  140 + * NodeType * a: pointer to node A.
  141 + * NodeType * b: pointer to node B.