Commit ff8510c639050f3a675299308b4f53c6992ae74d

Authored by Pierre Lassalle
1 parent 3b980eec
Exists in master

Remove older grm version

Applications/CMakeLists.txt
... ... @@ -1,19 +0,0 @@
1   -#=========================================================================
2   -
3   -# Program: Generic Region Merging Library (GRM)
4   -# Language: C++
5   -# author: Lassalle Pierre
6   -
7   -
8   -
9   -# Copyright (c) Centre National d'Etudes Spatiales. All rights reserved
10   -
11   -# See grmlib-copyright.txt for details.
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   -add_executable(RegionMergingSegmentation RegionMergingSegmentation.cxx)
19   -target_link_libraries(RegionMergingSegmentation OTBGRM)
Applications/RegionMergingSegmentation.cxx
... ... @@ -1,74 +0,0 @@
1   -#include <iostream>
2   -#include <otbImage.h>
3   -#include <otbVectorImage.h>
4   -#include <otbImageFileReader.h>
5   -#include <otbImageFileWriter.h>
6   -#include "lsrmBaatzSegmenter.h"
7   -
8   -int main(int argc, char *argv[])
9   -{
10   - if(argc != 7)
11   - {
12   - std::cerr << "Usage: ./" << argv[0] << "\n"
13   - << "\t[input image path] : (.jpg, .png, .tif)\n"
14   - << "\t[output clustered image] : (.jpg, .png, .tif)\n"
15   - << "\t[output label image] : (.tif)\n"
16   - << "\t[spectral weight] : range from 0 to 1\n"
17   - << "\t[shape weight] : range from 0 to 1\n"
18   - << "\t[scale threshold] : unlimited positive value"
19   - << std::endl;
20   - return 1;
21   - }
22   -
23   - lsrm::BaatzParam params;
24   - const char * inFileName = argv[1];
25   - const char * clusterFileName = argv[2];
26   - const char * labelFileName = argv[3];
27   - params.m_SpectralWeight = atof(argv[4]);
28   - params.m_ShapeWeight = atof(argv[5]);
29   - float sqrt_scale = atof(argv[6]);
30   - const float scale = sqrt_scale * sqrt_scale;
31   -
32   - typedef float PixelType;
33   - typedef unsigned long int LabelPixelType;
34   - typedef unsigned char ClusterPixelType;
35   - typedef otb::VectorImage<PixelType, 2> InputImageType;
36   - typedef otb::Image<LabelPixelType, 2> LabelImageType;
37   - typedef otb::VectorImage<ClusterPixelType, 2> ClusterImageType;
38   - typedef otb::ImageFileReader<InputImageType> InputImageReaderType;
39   - typedef otb::ImageFileWriter<LabelImageType> LabelImageWriterType;
40   - typedef otb::ImageFileWriter<ClusterImageType> ClusterImageWriterType;
41   - typedef lsrm::BaatzSegmenter<InputImageType> SegmenterType;
42   -
43   - auto imgReader = InputImageReaderType::New();
44   - imgReader->SetFileName(inFileName);
45   - imgReader->Update();
46   -
47   -
48   - SegmenterType segmenter;
49   - segmenter.SetParam(params);
50   - segmenter.SetThreshold(scale);
51   - segmenter.SetInput(imgReader->GetOutput());
52   - segmenter.Update();
53   -
54   - auto labelWriter = LabelImageWriterType::New();
55   - labelWriter->SetFileName(labelFileName);
56   - labelWriter->SetInput(segmenter.GetLabeledClusteredOutput());
57   - labelWriter->Update();
58   -
59   - auto clusterWriter = ClusterImageWriterType::New();
60   - clusterWriter->SetFileName(clusterFileName);
61   - clusterWriter->SetInput(segmenter.GetClusteredImageOutput());
62   - clusterWriter->Update();
63   -
64   - return 0;
65   -}
66   -
67   -
68   -
69   -
70   -
71   -
72   -
73   -
74   -
CMakeLists.txt
... ... @@ -1,42 +0,0 @@
1   -#=========================================================================
2   -
3   -# Program: Generic Region Merging Library (GRM)
4   -# Language: C++
5   -# author: Lassalle Pierre
6   -
7   -
8   -
9   -# Copyright (c) Centre National d'Etudes Spatiales. All rights reserved
10   -
11   -# See grmlib-copyright.txt for details.
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   -project(GRM)
19   -
20   -cmake_minimum_required(VERSION 2.8)
21   -
22   -find_package(OTB)
23   -IF(OTB_FOUND)
24   - include(${OTB_USE_FILE})
25   -ELSE(OTB_FOUND)
26   - message(FATAL_ERROR
27   - "Cannot build OTB project without OTB. Please set OTB_DIR.")
28   -ENDIF(OTB_FOUND)
29   -
30   -#Activate c++11
31   -include(CheckCXXCompilerFlag)
32   -CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
33   -if(COMPILER_SUPPORTS_CXX11)
34   - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fpermissive -Wall -Wmaybe-uninitialized")
35   -else()
36   - message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
37   -endif()
38   -
39   -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/Code)
40   -
41   -add_subdirectory(Code)
42   -add_subdirectory(Applications)
Code/CMakeLists.txt
... ... @@ -1,21 +0,0 @@
1   -#=========================================================================
2   -
3   -# Program: Generic Region Merging Library (GRM)
4   -# Language: C++
5   -# author: Lassalle Pierre
6   -
7   -
8   -
9   -# Copyright (c) Centre National d'Etudes Spatiales. All rights reserved
10   -
11   -# See grmlib-copyright.txt for details.
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   -add_library(OTBGRM
19   - lsrmNeighborhood.cpp)
20   -
21   -target_link_libraries(OTBGRM OTBCommon OTBIO)
Code/lsrmBaatzSegmenter.h
... ... @@ -1,101 +0,0 @@
1   -#ifndef __LSRM_BAATZ_SEGMENTER_H
2   -#define __LSRM_BAATZ_SEGMENTER_H
3   -#include "lsrmSegmenter.h"
4   -/*
5   - * Tutorial : Implementation of the Baatz & Schape criterion
6   - *
7   - * Details about the criterion can be found in the following publication:
8   - *
9   - * Martin Baatz and Arno Schape. Multiresolution segmentation: an optimization approach for high quality multi-scale image segmentation.
10   - * Angewandte Geographische Informationsverarbeitung XII, pages 12–23, 2000.
11   - *
12   - * The steps are ordered has to be followed in a chronological way for a full understanding.
13   - * This tutorial does not aim at explaining all the details of the large scale region merging
14   - * but gives all the elements to use it properly.
15   - */
16   -
17   -namespace lsrm
18   -{
19   - /*
20   - * Step 1 :
21   - * We define the specific attributes required for the Baatz & Schape criterion.
22   - * Regions are represented by nodes in a graph and the lsrm library has an internal
23   - * representation of the nodes with the class lsrm::Node.
24   - * --> A node contains a unique number to be indentified, it corresponds to the vectorized
25   - * coordinates of its first pixel and its name is m_Id.
26   - * To retrieve the 2D coordinates from the value of m_Id, it is necessary to know the dimension
27   - * of the image (the number of rows and columns), then :
28   - * x = m_Id % columns and y = m_Id / columns.
29   - *
30   - * --> A node contains the perimeter (m_Perimeter) of its corresponding region, it is the length of the external
31   - * boundary of the region. For example a region of one pixel has a perimeter of 4.
32   - *
33   - * --> A node contains the area (m_Area) of its corresponding region, it is the number of pixels within the
34   - * region.
35   - *
36   - * --> A node contains the minimum rectangular bounding box (parrallel to the image axis) of the region (m_Bbox).
37   - * the boundix box is determined by the structure lsrm::BoundingBox with the coordinates of the upper left
38   - * corner pixel and the width and the height (m_UX, m_UY, m_W, m_H).
39   - *
40   - * After Reading the paper about the Baatz & Schape criterion, we can conclude that we have to define additional
41   - * spectral attributes for a node: its mean vector, the square mean vector, the sum of all the pixels
42   - * and the standard deviation vector.
43   - *
44   - * We define a new class BaatzNode which inherits from the template structure Node. Notice that the template
45   - * is the derived node type, then the template type is BaatzNode.
46   - */
47   - struct BaatzNode : Node<BaatzNode>
48   - {
49   - std::vector<float> m_Means;
50   - std::vector<float> m_SquareMeans;
51   - std::vector<float> m_SpectralSum;
52   - std::vector<float> m_Std;
53   - };
54   -
55   - /*
56   - * Step 2
57   - *
58   - * The Baatz & Schape criterion has user-defined parameters, the spectral weight
59   - * which is the relative importance given to the spectral components and the shape
60   - * weight for the shape components.
61   - *
62   - * We define then a structure wrapping these two parameters we called BaatzParam.
63   - */
64   - struct BaatzParam
65   - {
66   - float m_SpectralWeight;
67   - float m_ShapeWeight;
68   - };
69   -
70   - /*
71   - * Step 3 :
72   - *
73   - */
74   -
75   - template<class TImage>
76   - class BaatzSegmenter : public Segmenter< TImage, BaatzNode, BaatzParam>
77   - {
78   - public:
79   -
80   - /* Some convenient typedefs */
81   - typedef Segmenter<TImage, BaatzNode, BaatzParam> Superclass;
82   - typedef TImage ImageType;
83   - typedef typename Superclass::GraphType GraphType;
84   - typedef typename Superclass::NodePointerType NodePointerType;
85   - typedef typename Superclass::GraphOperatorType GraphOperatorType;
86   - typedef GraphToOtbImage<GraphType> IOType;
87   -
88   - BaatzSegmenter();
89   -
90   - void Update();
91   - float ComputeMergingCost(NodePointerType n1, NodePointerType n2);
92   - void UpdateSpecificAttributes(NodePointerType n1, NodePointerType n2);
93   - void InitFromImage();
94   - };
95   -
96   -} // end of namespace lsrm
97   -#include "lsrmBaatzSegmenter.txx"
98   -#endif
99   -
100   -
101   -
Code/lsrmBaatzSegmenter.txx
... ... @@ -1,148 +0,0 @@
1   -#ifndef __LSRM_BAATZ_SEGMENTER_TXX
2   -#define __LSRM_BAATZ_SEGMENTER_TXX
3   -#include <otbImageFileReader.h>
4   -#include <itkImageRegionIterator.h>
5   -
6   -namespace lsrm
7   -{
8   -
9   - template<class TImage>
10   - BaatzSegmenter<TImage>::BaatzSegmenter() : Superclass()
11   - {
12   - this->m_DoBFSegmentation = true;
13   - this->m_NumberOfIterations = 75;
14   - }
15   -
16   - template<class TImage>
17   - void
18   - BaatzSegmenter<TImage>::InitFromImage()
19   - {
20   - typedef itk::ImageRegionIterator<TImage> ImageIterator;
21   -
22   - this->m_ImageWidth = this->m_InputImage->GetLargestPossibleRegion().GetSize()[0];
23   - this->m_ImageHeight =this->m_InputImage->GetLargestPossibleRegion().GetSize()[1];
24   - this->m_NumberOfComponentsPerPixel = this->m_InputImage->GetNumberOfComponentsPerPixel();
25   -
26   - std::size_t idx = 0;
27   - ImageIterator it(this->m_InputImage, this->m_InputImage->GetLargestPossibleRegion());
28   - for(it.GoToBegin(); !it.IsAtEnd(); ++it)
29   - {
30   - this->m_Graph.m_Nodes[idx]->m_Means.reserve(this->m_NumberOfComponentsPerPixel);
31   - this->m_Graph.m_Nodes[idx]->m_SquareMeans.reserve(this->m_NumberOfComponentsPerPixel);
32   - this->m_Graph.m_Nodes[idx]->m_SpectralSum.reserve(this->m_NumberOfComponentsPerPixel);
33   - this->m_Graph.m_Nodes[idx]->m_Std.assign(this->m_NumberOfComponentsPerPixel, 0.0f);
34   -
35   - for(std::size_t b = 0; b < this->m_NumberOfComponentsPerPixel; ++b)
36   - {
37   - this->m_Graph.m_Nodes[idx]->m_Means.push_back(it.Get()[b]);
38   - this->m_Graph.m_Nodes[idx]->m_SquareMeans.push_back((it.Get()[b])*(it.Get()[b]));
39   - this->m_Graph.m_Nodes[idx]->m_SpectralSum.push_back(it.Get()[b]);
40   - }
41   - ++idx;
42   - }
43   - }
44   -
45   - template<class TImage>
46   - float
47   - BaatzSegmenter<TImage>::ComputeMergingCost(NodePointerType n1, NodePointerType n2)
48   - {
49   - const unsigned int a1 = n1->m_Area, a2 = n2->m_Area, a_sum = a1 + a2;
50   -
51   - float spect_cost = 0.0f;
52   - float mean, square_mean, sum, std;
53   -
54   - for (unsigned int b = 0; b < this->m_NumberOfComponentsPerPixel; b++)
55   - {
56   - mean = ((a1 * n1->m_Means[b]) + (a2 * n2->m_Means[b])) / a_sum;
57   - square_mean = n1->m_SquareMeans[b] + n2->m_SquareMeans[b];
58   - sum = n1->m_SpectralSum[b] + n2->m_SpectralSum[b];
59   - std = std::sqrt((square_mean - 2*mean*sum + a_sum * mean* mean) / a_sum);
60   - spect_cost += (a_sum * std - a1 * n1->m_Std[b] - a2 * n2->m_Std[b]);
61   - }
62   - spect_cost *= this->m_Param.m_ShapeWeight;
63   -
64   - if(spect_cost < this->m_Threshold)
65   - {
66   - float shape_cost, smooth_f, compact_f;
67   -
68   - // Compute the shape merging cost
69   - const float p1 = static_cast<float>(n1->m_Perimeter);
70   - const float p2 = static_cast<float>(n2->m_Perimeter);
71   - const unsigned int boundary = (GraphOperatorType::FindEdge(n1, n2))->m_Boundary;
72   - const float p3 = p1 + p2 - 2 * static_cast<float>(boundary);
73   -
74   - const BoundingBox merged_bbox = MergeBoundingBoxes(n1->m_Bbox, n2->m_Bbox);
75   - const float bb1_perimeter = static_cast<float>(2*n1->m_Bbox.m_W + 2*n1->m_Bbox.m_H);
76   - const float bb2_perimeter = static_cast<float>(2*n2->m_Bbox.m_W + 2*n2->m_Bbox.m_H);
77   - const float mbb_perimeter = static_cast<float>(2 * merged_bbox.m_W + 2 * merged_bbox.m_H);
78   -
79   - smooth_f = a_sum*p3/mbb_perimeter - a1*p1/bb1_perimeter - a2*p2/bb2_perimeter;
80   - compact_f = a_sum*p3/std::sqrt(a_sum) - a1*p1/std::sqrt(a1) - a2*p2/std::sqrt(a2);
81   -
82   - shape_cost = this->m_Param.m_ShapeWeight * compact_f + (1-this->m_Param.m_ShapeWeight) * smooth_f;
83   -
84   - return (spect_cost + (1-this->m_Param.m_ShapeWeight)*shape_cost);
85   - }
86   - else
87   - return spect_cost;
88   - }
89   -
90   - template<class TImage>
91   - void
92   - BaatzSegmenter<TImage>::UpdateSpecificAttributes(NodePointerType n1, NodePointerType n2)
93   - {
94   - const float a1 = static_cast<float>(n1->m_Area);
95   - const float a2 = static_cast<float>(n2->m_Area);
96   - const float a_sum = a1 + a2;
97   -
98   - for(unsigned int b = 0; b < this->m_NumberOfComponentsPerPixel; ++b)
99   - {
100   - n1->m_Means[b] = (a1 * n1->m_Means[b] + a2 * n2->m_Means[b]) / a_sum;
101   - n1->m_SquareMeans[b] += n2->m_SquareMeans[b];
102   - n1->m_SpectralSum[b] += n2->m_SpectralSum[b];
103   - n1->m_Std[b] = std::sqrt((n1->m_SquareMeans[b] - 2 * n1->m_Means[b] * n1->m_SpectralSum[b] +
104   - a_sum * n1->m_Means[b] * n1->m_Means[b]) / a_sum);
105   - }
106   - }
107   -
108   - template<class TImage>
109   - void
110   - BaatzSegmenter<TImage>::Update()
111   - {
112   - GraphOperatorType::InitNodes(this->m_InputImage, this->m_Graph, *this, FOUR);
113   - bool prev_merged = false;
114   -
115   - if(this->m_NumberOfIterations > 0)
116   - {
117   - prev_merged =
118   - GraphOperatorType::PerfomAllIterationsWithLMBFAndConstThreshold(this->m_Graph, *this,
119   - this->m_Threshold, this->m_NumberOfIterations,
120   - this->m_ImageWidth, this->m_ImageHeight);
121   -
122   - if(prev_merged && this->m_DoBFSegmentation)
123   - {
124   - prev_merged =
125   - GraphOperatorType::PerfomAllIterationsWithBFAndConstThreshold(this->m_Graph, *this,
126   - this->m_Threshold, this->m_NumberOfIterations,
127   - this->m_ImageWidth, this->m_ImageHeight);
128   - }
129   - }
130   - else
131   - {
132   - assert(this->m_DoBFSegmentation == true);
133   - prev_merged =
134   - GraphOperatorType::PerfomAllIterationsWithBFAndConstThreshold(this->m_Graph, *this,
135   - this->m_Threshold, this->m_NumberOfIterations,
136   - this->m_ImageWidth, this->m_ImageHeight);
137   - }
138   - }
139   -} // end of namespace lsrm
140   -
141   -#endif
142   -
143   -
144   -
145   -
146   -
147   -
148   -
Code/lsrmDataStructures.h
... ... @@ -1,46 +0,0 @@
1   -#ifndef __LSRM_DATA_STRUCTURES_H
2   -#define __LSRM_DATA_STRUCTURES_H
3   -#include <stdexcept>
4   -#include <bitset>
5   -#include <vector>
6   -
7   -namespace lsrm
8   -{
9   -
10   - struct BoundingBox
11   - {
12   - /* X coordinate of the upper left. */
13   - long unsigned int m_UX;
14   -
15   - /* Y coordinate of the upper left. */
16   - long unsigned int m_UY;
17   -
18   - /* Width */
19   - unsigned int m_W;
20   -
21   - /* Height */
22   - unsigned int m_H;
23   - };
24   -
25   - BoundingBox MergeBoundingBoxes(const BoundingBox& bb1,
26   - const BoundingBox& bb2)
27   - {
28   - long unsigned int min_ux, min_uy, max_xw, max_yh;
29   - BoundingBox bb;
30   -
31   - min_ux = std::min(bb1.m_UX, bb2.m_UX);
32   - min_uy = std::min(bb1.m_UY, bb2.m_UY);
33   - max_xw = std::max(bb1.m_UX + bb1.m_W, bb2.m_UX + bb2.m_W);
34   - max_yh = std::max(bb1.m_UY + bb1.m_H, bb2.m_UY + bb2.m_H);
35   -
36   - bb.m_UX = min_ux;
37   - bb.m_UY = min_uy;
38   - bb.m_W = max_xw - min_ux;
39   - bb.m_H = max_yh - min_uy;
40   -
41   - return bb;
42   - }
43   -
44   -} // end of namespace lsrm
45   -
46   -#endif
Code/lsrmGraph.h
... ... @@ -1,90 +0,0 @@
1   -#ifndef __LSRM_GRAPH_H
2   -#define __LSRM_GRAPH_H
3   -#include "lsrmDataStructures.h"
4   -
5   -namespace lsrm
6   -{
7   - struct BaseNode
8   - {
9   - /* Node already merged. */
10   - bool m_Valid;
11   -
12   - /* Node has to be removed from the graph. */
13   - bool m_Expired;
14   -
15   - /* Does the node merge at the previous iteration */
16   - bool m_IsMerged;
17   -
18   - /* Perimeter of the region */
19   - unsigned int m_Perimeter;
20   -
21   - /* Area (number of inner pixels) of the region */
22   - unsigned int m_Area;
23   -
24   - /*
25   - Node is identified by the location
26   - of the first pixel of the region.
27   - */
28   - long unsigned int m_Id;
29   -
30   - /*
31   - Bounding box of the region
32   - in the image.
33   - */
34   - BoundingBox m_Bbox;
35   -
36   - /* List of pixels contained in the regions */
37   - std::vector<unsigned long int> m_Pixels;
38   - };
39   -
40   - template<class DerivedNode>
41   - struct NeighborType
42   - {
43   - typedef std::weak_ptr<DerivedNode> WeakDerived;
44   - typedef std::shared_ptr<DerivedNode> SharedDerived;
45   -
46   - WeakDerived m_Target;
47   - float m_Cost;
48   - unsigned int m_Boundary;
49   - bool m_CostUpdated;
50   -
51   - NeighborType(WeakDerived ptr, double w, unsigned int c) :
52   - m_Target(ptr), m_Cost(w), m_Boundary(c), m_CostUpdated(false) {}
53   -
54   - inline SharedDerived GetRegion()
55   - {
56   - SharedDerived ptr(m_Target.lock());
57   - if(!ptr)
58   - throw std::runtime_error("lss_GenericLMBFRegionMergingHandler.h - NeighborType::GetRegion - Region pointer is not valid");
59   - return ptr;
60   - }
61   - };
62   -
63   -
64   - template<class DerivedNode>
65   - struct Node : BaseNode
66   - {
67   - typedef NeighborType<DerivedNode> CRPTNeighborType;
68   - std::vector<CRPTNeighborType> m_Edges;
69   - };
70   -
71   - template<class TNode>
72   - struct Graph
73   - {
74   - typedef TNode NodeType;
75   - typedef std::shared_ptr<NodeType> NodePointerType;
76   - typedef typename NodeType::CRPTNeighborType EdgeType;
77   - typedef std::vector<NodePointerType> NodeListType;
78   - typedef typename NodeListType::iterator NodeIteratorType;
79   - typedef typename NodeListType::const_iterator NodeConstIteratorType;
80   - typedef std::vector<EdgeType> EdgeListType;
81   - typedef typename EdgeListType::iterator EdgeIteratorType;
82   - typedef typename EdgeListType::const_iterator EdgeConstIteratorType;
83   -
84   - std::vector< NodePointerType > m_Nodes;
85   - };
86   -
87   -} // end of namespace lsrm
88   -#endif
89   -
90   -
Code/lsrmGraphOperations.h
... ... @@ -1,240 +0,0 @@
1   -#ifndef __LSRM_GRAPH_OPERATIONS_H
2   -#define __LSRM_GRAPH_OPERATIONS_H
3   -#include "lsrmGraph.h"
4   -#include "lsrmNeighborhood.h"
5   -#include <iostream>
6   -#include <cassert>
7   -#include <limits>
8   -#include <map>
9   -#include <utility>
10   -#include <set>
11   -
12   -namespace lsrm
13   -{
14   - template<class TSegmenter>
15   - class GraphOperations
16   - {
17   - public:
18   -
19   - /* Some convenient typedefs */
20   - typedef TSegmenter SegmenterType;
21   - typedef typename SegmenterType::ImageType ImageType;
22   - typedef typename SegmenterType::GraphType GraphType;
23   - typedef typename GraphType::NodeType NodeType;
24   - typedef typename GraphType::EdgeType EdgeType;
25   - typedef typename GraphType::NodePointerType NodePointerType;
26   - typedef typename GraphType::NodeListType NodeList;
27   - typedef typename GraphType::NodeIteratorType NodeIterator;
28   - typedef typename GraphType::NodeConstIteratorType NodeConstIterator;
29   - typedef typename GraphType::EdgeListType EdgeList;
30   - typedef typename GraphType::EdgeIteratorType EdgeIterator;
31   - typedef typename GraphType::EdgeConstIteratorType EdgeConstIterator;
32   -
33   -
34   - /*
35   - * Given the size of the input image and the mask of the
36   - * neighborhood, we initialize a new graph of nodes
37   - *
38   - * @params:
39   - * GraphType& graph: reference to a graph of nodes
40   - * const unsigned int width: width of the input image
41   - * const unsigned int height: height of the input image
42   - * CONNECTIVITY mask : mask of the neighborhood (4X4 or 8X8)
43   - */
44   - static void InitNodes(ImageType * inputImg,
45   - GraphType& graph,
46   - SegmenterType& seg,
47   - CONNECTIVITY mask);
48   -
49   - /*
50   - * Given a graph of nodes, we explore all the nodes
51   - * and for each node we compute his merging costs
52   - * with all its neighboring nodes given a function
53   - * to compute the merging cost between two nodes.
54   - *
55   - * @params:
56   - * GraphType& graph: reference to the graph of nodes
57   - * float(*fptr)(NodeType*, NodeType*): pointer to the function
58   - * to compute the merging cost between two adjacent nodes.
59   - */
60   - static void UpdateMergingCosts(GraphType& graph, SegmenterType& seg);
61   -
62   - /*
63   - * Given a node A, we analyse its best node B.
64   - * If the node A is also node B's best node
65   - * then it returns a pointer to node B if node A 's id
66   - * is smaller or a pointer to node A if node B's id is
67   - * smaller
68   - * else it returns a null pointer.
69   - * (Local Mutual Best Fitting Heuristic)
70   - *
71   - * @params:
72   - * NodeType * a : Pointer to the node A
73   - * float t : threshold of the criterion
74   - */
75   - static NodePointerType CheckLMBF(NodePointerType, float t);
76   -
77   - /*
78   - * Given a node A, we analyse its best node B.
79   - * If the criterion is checked and the node B
80   - * is valid then it returns a pointer to the
81   - * node A if node's A id is smaller or a pointer
82   - * to node B if node B's id is smaller
83   - * else it returns a null pointer.
84   - *
85   - * @params:
86   - * NodeType * a : pointer to node A
87   - * float t : threshold of the criterion
88   - */
89   - static NodePointerType CheckBF(NodePointerType a, float t);
90   -
91   - /*
92   - * Given the current node and the target node, it returns
93   - * the edge from the current node targeting to the target
94   - * node.
95   - *
96   - * @params
97   - * const NodeType * n : pointer to the current node.
98   - * const NodeType * target : pointer to the target node.
99   - * @return an iterator pointing to the candidate edge.
100   - */
101   - static EdgeIterator FindEdge(NodePointerType n, NodePointerType target);
102   -
103   - /*
104   - * Given a node a and the node b to be merged into node a,
105   - * it updates the neighbors of node a with respect to the
106   - * neighbors of node b.
107   - *
108   - * @params
109   - * NodeType * a : pointer to node a.
110   - * NodeType * b : pointer to node b.
111   - */
112   - static void UpdateNeighbors(NodePointerType a, NodePointerType b);
113   -
114   - /*
115   - * Given 2 nodes A and B (node B being merged into node A)
116   - * we update the internal attributes of node A with respect
117   - * to node B.
118   - *
119   - * @params:
120   - * NodeType * a: pointer to node A.
121   - * NodeType * b: pointer to node B.
122   - */
123   - static void UpdateInternalAttributes(NodePointerType a,
124   - NodePointerType b,
125   - const unsigned int width,
126   - const unsigned int height);
127   -
128   - /*
129   - * Given a graph, it removes all the expired nodes.
130   - *
131   - * @params
132   - * GraphType& graph : reference to the graph.
133   - */
134   - static void RemoveExpiredNodes(GraphType& graph);
135   -
136   -
137   - /*
138   - * Given a graph, a region merging algorithm, a threshold
139   - * and the dimension of the image, it performs one iteration
140   - * of the merging process using the local mutual best fitting
141   - * heuristic.
142   - *
143   - * @params
144   - * GraphType& graph : reference to the graph
145   - * SegmenterType& seg : reference to the region merging algorithm.
146   - * const float threshold : threshold for this iteration.
147   - * const unsigned int width : width of the image.
148   - * const unsigned int height : height of the image.
149   - *
150   - * @return a boolean pointing out if there was at least a fusion
151   - * of nodes.
152   - */
153   - static bool PerfomOneIterationWithLMBF(GraphType& graph,
154   - SegmenterType& seg,
155   - const float threshold,
156   - const unsigned int width,
157   - const unsigned int height);
158   -
159   - /*
160   - * Given a graph, a region merging algorithm, a threshold
161   - * and the dimension of the image, it performs one iteration
162   - * of the merging process using the best fitting
163   - * heuristic.
164   - *
165   - * @params
166   - * GraphType& graph : reference to the graph
167   - * SegmenterType& seg : reference to the region merging algorithm.
168   - * const float threshold : threshold for this iteration.
169   - * const unsigned int width : width of the image.
170   - * const unsigned int height : height of the image.
171   - *
172   - * @return a boolean pointing out if there was at least a fusion
173   - * of nodes.
174   - */
175   - static bool PerfomOneIterationWithBF(GraphType& graph,
176   - SegmenterType& seg,
177   - const float threshold,
178   - const unsigned int width,
179   - const unsigned int height);
180   -
181   - /*
182   - * Given a graph, a region merging algorithm, a threshold,
183   - * the number of iterations to apply and the dimension of the image,
184   - * it performs all the iterations of the merging process using the
185   - * local mutual best fitting heuristic.
186   - * This method can be used when the threshold is constant during
187   - * the region merging process.
188   - *
189   - * @params
190   - * GraphType& graph : reference to the graph
191   - * SegmenterType& seg : reference to the region merging algorithm.
192   - * const float threshold : threshold for this iteration.
193   - * const unsigned int numberOfIterations: number of iteration to perform.
194   - * const unsigned int width : width of the image.
195   - * const unsigned int height : height of the image.
196   - *
197   - * @return a boolean pointing out if there was at least a fusion
198   - * of nodes.
199   - */
200   - static bool PerfomAllIterationsWithLMBFAndConstThreshold(GraphType& graph,
201   - SegmenterType& seg,
202   - const float threshold,
203   - const unsigned int numberOfIterations,
204   - const unsigned int width,
205   - const unsigned int height);
206   -
207   - /*
208   - * Given a graph, a region merging algorithm, a threshold,
209   - * the number of iterations to apply and the dimension of the image,
210   - * it performs all the iterations of the merging process using the
211   - * best fitting heuristic.
212   - * This method can be used when the threshold is constant during
213   - * the region merging process.
214   - *
215   - * @params
216   - * GraphType& graph : reference to the graph
217   - * SegmenterType& seg : reference to the region merging algorithm.
218   - * const float threshold : threshold for this iteration.
219   - * const unsigned int numberOfIterations: number of iteration to perform.
220   - * const unsigned int width : width of the image.
221   - * const unsigned int height : height of the image.
222   - *
223   - * @return a boolean pointing out if there was at least a fusion
224   - * of nodes.
225   - */
226   - static bool PerfomAllIterationsWithBFAndConstThreshold(GraphType& graph,
227   - SegmenterType& seg,
228   - const float threshold,
229   - const unsigned int numberOfIterations,
230   - const unsigned int width,
231   - const unsigned int height);
232   - };
233   -} // end of namespace lsrm
234   -
235   -#include "lsrmGraphOperations.txx"
236   -#endif
237   -
238   -
239   -
240   -
Code/lsrmGraphOperations.txx
... ... @@ -1,465 +0,0 @@
1   -#ifndef __LSRM_GRAPH_OPERATIONS_TXX
2   -#define __LSRM_GRAPH_OPERATIONS_TXX
3   -#include <otbImageFileReader.h>
4   -
5   -namespace lsrm
6   -{
7   - template<class TSegmenter>
8   - void GraphOperations<TSegmenter>::InitNodes(ImageType * inputImg,
9   - GraphType& graph,
10   - SegmenterType& seg,
11   - CONNECTIVITY mask)
12   - {
13   - unsigned int width, height;
14   -
15   - {
16   - width = inputImg->GetLargestPossibleRegion().GetSize()[0];
17   - height = inputImg->GetLargestPossibleRegion().GetSize()[1];
18   - }
19   -
20   - const long unsigned int num_nodes = width * height;
21   -
22   - graph.m_Nodes.reserve(num_nodes);
23   -
24   - for(long unsigned int i = 0;
25   - i < num_nodes;
26   - ++i)
27   - {
28   - NodePointerType n(new NodeType);
29   - n->m_Id = i;
30   - n->m_Valid = true;
31   - n->m_Expired = false;
32   - n->m_IsMerged = true; // force to compute costs for the first iteration
33   - n->m_Perimeter = 4;
34   - n->m_Area = 1;
35   - n->m_Bbox.m_UX = i % width;
36   - n->m_Bbox.m_UY = i / width;
37   - n->m_Bbox.m_W = 1;
38   - n->m_Bbox.m_H = 1;
39   - n->m_Pixels.push_back(i);
40   - graph.m_Nodes.push_back(n);
41   - }
42   -
43   - if(mask == FOUR)
44   - {
45   - for(auto& r : graph.m_Nodes)
46   - {
47   - long int neighborhood[4];
48   - FOURNeighborhood(neighborhood, r->m_Id, width, height);
49   - for(short j = 0; j < 4; ++j)
50   - {
51   - if(neighborhood[j] > -1)
52   - r->m_Edges.push_back(EdgeType( graph.m_Nodes[neighborhood[j]], 0, 1));
53   - }
54   - }
55   - }
56   - else
57   - {
58   - for(auto& r : graph.m_Nodes)
59   - {
60   - long int neighborhood[8];
61   - EIGHTNeighborhood(neighborhood, r->m_Id, width, height);
62   - for(short j = 0; j < 8; ++j)
63   - {
64   - if(neighborhood[j] > -1)
65   - {
66   - if(j % 2 > 0)
67   - r->m_Edges.push_back(EdgeType( graph.m_Nodes[neighborhood[j]], 0, 0));
68   - else
69   - r->m_Edges.push_back(EdgeType( graph.m_Nodes[neighborhood[j]], 0, 1));
70   - }
71   - }
72   - }
73   - }
74   - seg.InitFromImage();
75   - }
76   -
77   - template<class TSegmenter>
78   - void GraphOperations<TSegmenter>::UpdateMergingCosts(GraphType& graph,
79   - SegmenterType& seg)
80   - {
81   - float min_cost;
82   - long unsigned int min_id;
83   - std::size_t idx, min_idx;
84   -
85   - for(auto& r : graph.m_Nodes)
86   - {
87   - for(auto& edge : r->m_Edges)
88   - edge.m_CostUpdated = false;
89   - }
90   -
91   - for(auto& r : graph.m_Nodes)
92   - {
93   - min_cost = std::numeric_limits<float>::max();
94   - min_id = 0;
95   - idx = 0;
96   - min_idx = 0;
97   -
98   - r->m_Expired = false;
99   - r->m_Valid = true;
100   -
101   - for(auto& edge : r->m_Edges)
102   - {
103   - auto neighborR = edge.GetRegion();
104   -
105   - // Compute the cost if necessary
106   - if(!edge.m_CostUpdated && (neighborR->m_IsMerged || r->m_IsMerged))
107   - {
108   - auto edgeFromNeighborToR = FindEdge(neighborR, r);
109   - edge.m_Cost = seg.ComputeMergingCost(r, neighborR);
110   - edgeFromNeighborToR->m_Cost = edge.m_Cost;
111   - edge.m_CostUpdated = true;
112   - edgeFromNeighborToR->m_CostUpdated = true;
113   - }
114   -
115   - // Check if the cost of the edge is the minimum
116   - if(min_cost > edge.m_Cost)
117   - {
118   - min_cost = edge.m_Cost;
119   - min_id = neighborR->m_Id;
120   - min_idx = idx;
121   - }
122   - else if(min_cost == edge.m_Cost)
123   - {
124   - if(min_id > neighborR->m_Id)
125   - {
126   - min_id = neighborR->m_Id;
127   - min_idx = idx;
128   - }
129   - }
130   - ++idx;
131   - }
132   -
133   - assert(min_idx < r->m_Edges.size());
134   - std::swap(r->m_Edges[0], r->m_Edges[min_idx]);
135   -
136   - }
137   -
138   - // Reset the merge flag for all the regions.
139   - for(auto& r : graph.m_Nodes)
140   - r->m_IsMerged = false;
141   - }
142   -
143   - template<class TSegmenter>
144   - typename GraphOperations<TSegmenter>::NodePointerType
145   - GraphOperations<TSegmenter>::CheckLMBF(NodePointerType a, float t)
146   - {
147   - if(a->m_Valid)
148   - {
149   - float cost = a->m_Edges.front().m_Cost;
150   -
151   - if(cost < t)
152   - {
153   - NodePointerType b = a->m_Edges.front().GetRegion();
154   -
155   - if( b->m_Valid)
156   - {
157   - NodePointerType best_b = b->m_Edges.front().GetRegion();
158   -
159   - if(a == best_b)
160   - {
161   - if(a->m_Id < b->m_Id)
162   - return a;
163   - else
164   - return b;
165   - }
166   - else
167   - return NodePointerType();
168   - }
169   - else
170   - return NodePointerType();
171   - }
172   - else
173   - return NodePointerType();
174   - }
175   - else
176   - return NodePointerType();
177   - }
178   -
179   - template<class TSegmenter>
180   - typename GraphOperations<TSegmenter>::NodePointerType
181   - GraphOperations<TSegmenter>::CheckBF(NodePointerType a, float t)
182   - {
183   - if(a->m_Valid)
184   - {
185   - float cost = a->m_Edges.front().m_Cost;
186   -
187   - if( cost < t )
188   - {
189   - NodePointerType b = a->m_Edges.front().GetRegion();
190   -
191   - if(b->m_Valid)
192   - {
193   - if( a->m_Id < b->m_Id )
194   - return a;
195   - else
196   - return b;
197   - }
198   - else
199   - return NodePointerType();
200   - }
201   - else
202   - return NodePointerType();
203   - }
204   - else
205   - return NodePointerType();
206   - }
207   -
208   - template<class TSegmenter>
209   - typename GraphOperations<TSegmenter>::EdgeIterator
210   - GraphOperations<TSegmenter>::FindEdge(NodePointerType n, NodePointerType target)
211   - {
212   - return std::find_if(n->m_Edges.begin(), n->m_Edges.end(),[&](EdgeType& e)->bool{
213   - return e.GetRegion() == target;
214   - });
215   - }
216   -
217   - template<class TSegmenter>
218   - void
219   - GraphOperations<TSegmenter>::UpdateNeighbors(NodePointerType a, NodePointerType b)
220   - {
221   - unsigned int boundary;
222   -
223   - /* Explore the neighbors of b */
224   - for (auto& edge : b->m_Edges)
225   - {
226   - // Retrieve the edge targeting node b.
227   - auto neigh_b = edge.GetRegion();
228   - auto toB = FindEdge(neigh_b, b);
229   -
230   - /* If the edge tageting to node b is the first then
231   - the corresponding node is not valid anymore. */
232   - if(toB == neigh_b->m_Edges.begin())
233   - neigh_b->m_Valid = false;
234   -
235   - /* Keep in memory the boundary between node b
236   - and node neigh_b */
237   - boundary = edge.m_Boundary;
238 <