OTB  6.1.0
Orfeo Toolbox
otbImageMultiSegmentationToRCC8GraphFilter.txx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2017 Centre National d'Etudes Spatiales (CNES)
3  *
4  * This file is part of Orfeo Toolbox
5  *
6  * https://www.orfeo-toolbox.org/
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 #ifndef otbImageMultiSegmentationToRCC8GraphFilter_txx
22 #define otbImageMultiSegmentationToRCC8GraphFilter_txx
23 
27 #include "otbRCC8VertexIterator.h"
28 #include "otbRCC8InEdgeIterator.h"
29 #include "otbRCC8OutEdgeIterator.h"
30 #include "itkProgressReporter.h"
33 
34 namespace otb
35 {
39 template <class TInputImage, class TOutputGraph>
42 {
43  m_Optimisation = false;
44 }
45 
49 template <class TInputImage, class TOutputGraph>
52 {}
53 
54 template <class TInputImage, class TOutputGraph>
55 unsigned int
58 {
59  return m_Accumulator[val];
60 }
61 
62 template <class TInputImage, class TOutputGraph>
63 unsigned int
66 {
67  unsigned int result = 0;
68  for (unsigned int i = 0; i < 8; ++i)
69  {
70  result += m_Accumulator[i];
71 
72  }
73  return result;
74 }
75 template <class TInputImage, class TOutputGraph>
77 ::KnowledgeStateType
80 {
81  m_Accumulator[0] = 0;
82  m_Accumulator[1] = 0;
83  m_Accumulator[2] = 0;
84  m_Accumulator[3] = 0;
85  m_Accumulator[4] = 0;
86  m_Accumulator[5] = 0;
87  m_Accumulator[6] = 0;
88  m_Accumulator[7] = 0;
89 
90  // otbMsgDebugMacro(<<"RCC8GraphFilter: entering GetKnowledge method.");
91  // This is the RCC8 composition table
92  const int knowledge[8][8]
93  =
94  { {-3, -2, -2, -2, 0, -2, 0, 0},
98  {-1, -3, -2, -3, -1, -3, 0, 1},
100  {-1, -1, -3, -3, -1, -3, -1, 2},
102  { 0, -1, -2, -3, -3, 5, -1, 3},
104  {-1, -1, -1, -3, -1, -3, 6, 4},
106  { 0, 0, -2, 5, -2, 5, -3, 5},
108  {-1, -1, -1, -1, 6, -3, 6, 6},
110  { 0, 1, 2, 3, 4, 5, 6, 7}
112  };
113 
114  int value = knowledge[r1][r2];
115  // Each negative case correspond to a level of knowledge
116  if (value >= 0)
117  {
118  // otbMsgDebugMacro(<<"RCC8GraphFilter: leaving GetKnowledge method: FULL");
119  return KnowledgeStateType(FULL, static_cast<RCC8ValueType>(value));
120  }
121  else if (value == -1)
122  {
123  // otbMsgDebugMacro(<<"RCC8GraphFilter: leaving GetKnowledge method: LEVEL_1");
124  return KnowledgeStateType(LEVEL_1, OTB_RCC8_DC);
125  }
126  else if (value == -2)
127  {
128  // otbMsgDebugMacro(<<"RCC8GraphFilter: leaving GetKnowledge method.LEVEL_3");
129  return KnowledgeStateType(LEVEL_3, OTB_RCC8_DC);
130  }
131  else
132  {
133  // otbMsgDebugMacro(<<"RCC8GraphFilter: leaving GetKnowledge method.NO_INFO");
134  return KnowledgeStateType(NO_INFO, OTB_RCC8_DC);
135  }
136 }
140 template <class TInputImage, class TOutputGraph>
141 void
144 {
145  // Input image list pointer
146  InputImageListPointerType segList = this->GetInput();
147 
148  // Output graph pointer
149  OutputGraphPointerType graph = this->GetOutput();
150 
151  // invert value vector
154 
155  // Some typedefs
156  typedef otb::ImageToEdgePathFilter<InputImageType, PathType> EdgeExtractionFilterType;
157  typedef otb::SimplifyPathListFilter<PathType> SimplifyPathFilterType;
158  typedef typename SimplifyPathFilterType::InputListType PathListType;
159 
160  typedef itk::MinimumMaximumImageCalculator<InputImageType> MinMaxCalculatorType;
161  typedef PolygonToPolygonRCC8Calculator<PathType> RCC8CalculatorType;
162  typedef RCC8VertexIterator<OutputGraphType> VertexIteratorType;
163  typedef RCC8InEdgeIterator<OutputGraphType> InEdgeIteratorType;
164 
165 
166  // Vector of label
167  std::vector<PixelType> maxLabelVector;
168 
169  // Vertex indexes
170  unsigned int vertexIndex = 0;
171  unsigned int segmentationImageIndex = 0;
172  unsigned int nbVertices = 0;
173 
174  // For each segmentation image
175  for (ConstListIteratorType it = segList->Begin(); it != segList->End(); ++it)
176  {
177  // Compute the maximum label
178  typename MinMaxCalculatorType::Pointer minMax = MinMaxCalculatorType::New();
179  minMax->SetImage(it.Get());
180  minMax->ComputeMaximum();
181  maxLabelVector.push_back(minMax->GetMaximum());
182  otbMsgDebugMacro(<< "Number of objects in image " << segmentationImageIndex << ": "
183  << minMax->GetMaximum());
184 
185  // then for each region of the images
186  for (PixelType label = 1; label <= maxLabelVector.back(); ++label)
187  {
188  typename PathListType::Pointer region = PathListType::New();
189  typename EdgeExtractionFilterType::Pointer extraction = EdgeExtractionFilterType::New();
190  extraction->SetInput(it.Get());
191  extraction->SetForegroundValue(label);
192  extraction->Update();
193  region->PushBack(extraction->GetOutput());
194  typename SimplifyPathFilterType::Pointer simplifier = SimplifyPathFilterType::New();
195  simplifier->SetInput(region);
196  simplifier->GetFunctor().SetTolerance(0.1);
197  simplifier->Update();
198 
199  // Create a new vertex
200  VertexPointerType vertex = VertexType::New();
201  // Set its properties
202  vertex->SetPath(simplifier->GetOutput()->GetNthElement(0));
203  vertex->SetSegmentationLevel(segmentationImageIndex / 2);
204  vertex->SetSegmentationType(segmentationImageIndex % 2);
205  // Put it in the graph
206  graph->SetVertex(vertexIndex, vertex);
207  ++vertexIndex;
208  ++nbVertices;
209  }
210  ++segmentationImageIndex;
211  }
212 
213  itk::ProgressReporter progress(this, 0, nbVertices*nbVertices);
214 
215  VertexIteratorType vIt1(graph);
216  VertexIteratorType vIt2(graph);
217 
218  // For each couple of vertices
219  for (vIt1.GoToBegin(); !vIt1.IsAtEnd(); ++vIt1)
220  {
221  for (vIt2.GoToBegin(); !vIt2.IsAtEnd(); ++vIt2)
222  {
223  //We do not examine each couple because of the RCC8 symmetry
224  if (vIt1.GetIndex() < vIt2.GetIndex())
225  {
226 
227  // Compute the RCC8 relation
228  typename RCC8CalculatorType::Pointer calc = RCC8CalculatorType::New();
229  calc->SetPolygon1(vIt1.Get()->GetPath());
230  calc->SetPolygon2(vIt2.Get()->GetPath());
231  RCC8ValueType value = OTB_RCC8_DC;
232 
233  // if the optimisations are activated
234  if (m_Optimisation)
235  {
236  // otbMsgDebugMacro(<<"RCC8GraphFilter: Entering optimisation loop");
237  InEdgeIteratorType inIt1(vIt1.GetIndex(), graph);
238  InEdgeIteratorType inIt2(vIt2.GetIndex(), graph);
239  // otbMsgDebugMacro(<<"Optimisation loop: iterators initialised");
240  VertexDescriptorType betweenIndex;
241  KnowledgeStateType know(NO_INFO, OTB_RCC8_DC);
242  inIt1.GoToBegin();
243 
244  // Iterate through the edges going to the first vertex
245  while (!inIt1.IsAtEnd() && (know.first != FULL))
246  {
247  betweenIndex = inIt1.GetSourceIndex();
248  inIt2.GoToBegin();
249  bool edgeFound = false;
250  while (!inIt2.IsAtEnd() && (know.first != FULL))
251  {
252  // try to find an intermediate vertex between the two ones which
253  // we vant to compute the relationship
254  if (inIt2.GetSourceIndex() == betweenIndex)
255  {
256  // if an intermediate vertex is found
257  edgeFound = true;
258  // otbMsgDebugMacro(<<"Optimisation loop: found an intermediary vertex:" <<betweenIndex);
259  // See if it brings some info on the RCCC8 value
260  know = GetKnowledge(invert[inIt1.GetValue()], inIt2.GetValue());
261  calc->SetLevel1APrioriKnowledge(know.first == LEVEL_1);
262  calc->SetLevel3APrioriKnowledge(know.first == LEVEL_3);
263  // otbMsgDebugMacro(<<"Optimisation loop: knowledge: "<<know.first<<","<<know.second);
264  }
265  ++inIt2;
266  }
267  // If no intermediate was found
268  if (!edgeFound)
269  {
270  // otbMsgDebugMacro(<<"Optimisation loop: found an intermediary vertex:" <<betweenIndex);
271  // Try using a DC relationship
272  know = GetKnowledge(invert[inIt1.GetValue()], OTB_RCC8_DC);
273  calc->SetLevel1APrioriKnowledge(know.first == LEVEL_1);
274  calc->SetLevel3APrioriKnowledge(know.first == LEVEL_3);
275  // otbMsgDebugMacro(<<"Optimisation loop: knowledge: "<<know.first<<","<<know.second);
276  }
277  ++inIt1;
278  }
279  // If the search has fully determined the RCC8
280  if (know.first == FULL)
281  {
282  // Get the value
283  value = know.second;
284  }
285  else
286  {
287  // Else trigger the computation
288  // (which will take the optimisation phase info into account)
289  calc->Compute();
290  value = calc->GetValue();
291  }
292  // otbMsgDebugMacro(<<"RCC8GraphFilter: Leaving optimisation loop");
293  }
294  // If the optimisations are not activated
295  else
296  {
297  calc->Compute();
298  value = calc->GetValue();
299  }
300  m_Accumulator[value] += 1;
301  m_Accumulator[invert[value]] += 1;
302  // If the vertices are connected
303  if (value > OTB_RCC8_DC)
304  {
305  // Add the edge to the graph.
306  otbMsgDevMacro(<< "Adding edge: " << vIt1.GetIndex() << " -> " << vIt2.GetIndex() << ": " << value);
307  graph->AddEdge(vIt1.GetIndex(), vIt2.GetIndex(), value);
308  }
309  }
310  progress.CompletedPixel();
311  progress.CompletedPixel();
312  }
313  }
314 }
315 
316 template <class TInputImage, class TOutputGraph>
317 void
319 ::PrintSelf(std::ostream& os, itk::Indent indent) const
320 {
321  Superclass::PrintSelf(os, indent);
322 }
323 } // end namespace otb
324 #endif
OutputGraphType::RCC8ValueType RCC8ValueType
void PrintSelf(std::ostream &os, itk::Indent indent) const ITK_OVERRIDE
This class compute the RCC8 relation between the regions from two segmentation images.
KnowledgeStateType GetKnowledge(RCC8ValueType r1, RCC8ValueType r2)
#define otbMsgDebugMacro(x)
Definition: otbMacro.h:58
This filter performs a simplification of the path in the input list.
Iterates on the graph vertices.
This filter compute the closed edge path of a labelled object in an image (for example coming from a ...
Iterates on the graph in edges from a vertex.
std::pair< KnowledgeValueType, RCC8ValueType > KnowledgeStateType
Superclass::OutputGraphPointerType OutputGraphPointerType
This class takes a list of labelled segmentation images and build the RCC8 graph of the set of region...
#define otbMsgDevMacro(x)
Definition: otbMacro.h:98