OTB  5.0.0
Orfeo Toolbox
otbImageMultiSegmentationToRCC8GraphFilter.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: ORFEO Toolbox
4  Language: C++
5  Date: $Date$
6  Version: $Revision$
7 
8 
9  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
10  See OTBCopyright.txt for details.
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 __otbImageMultiSegmentationToRCC8GraphFilter_txx
19 #define __otbImageMultiSegmentationToRCC8GraphFilter_txx
20 
24 #include "otbRCC8VertexIterator.h"
25 #include "otbRCC8InEdgeIterator.h"
26 #include "otbRCC8OutEdgeIterator.h"
27 #include "itkProgressReporter.h"
30 
31 namespace otb
32 {
36 template <class TInputImage, class TOutputGraph>
39 {
40  m_Optimisation = false;
41 }
42 
46 template <class TInputImage, class TOutputGraph>
49 {}
50 
51 template <class TInputImage, class TOutputGraph>
52 unsigned int
55 {
56  return m_Accumulator[val];
57 }
58 
59 template <class TInputImage, class TOutputGraph>
60 unsigned int
63 {
64  unsigned int result = 0;
65  for (unsigned int i = 0; i < 8; ++i)
66  {
67  result += m_Accumulator[i];
68 
69  }
70  return result;
71 }
72 template <class TInputImage, class TOutputGraph>
74 ::KnowledgeStateType
77 {
78  m_Accumulator[0] = 0;
79  m_Accumulator[1] = 0;
80  m_Accumulator[2] = 0;
81  m_Accumulator[3] = 0;
82  m_Accumulator[4] = 0;
83  m_Accumulator[5] = 0;
84  m_Accumulator[6] = 0;
85  m_Accumulator[7] = 0;
86 
87  // otbMsgDebugMacro(<<"RCC8GraphFilter: entering GetKnowledge method.");
88  // This is the RCC8 composition table
89  const int knowledge[8][8]
90  =
91  { {-3, -2, -2, -2, 0, -2, 0, 0},
95  {-1, -3, -2, -3, -1, -3, 0, 1},
97  {-1, -1, -3, -3, -1, -3, -1, 2},
99  { 0, -1, -2, -3, -3, 5, -1, 3},
101  {-1, -1, -1, -3, -1, -3, 6, 4},
103  { 0, 0, -2, 5, -2, 5, -3, 5},
105  {-1, -1, -1, -1, 6, -3, 6, 6},
107  { 0, 1, 2, 3, 4, 5, 6, 7}
109  };
110 
111  int value = knowledge[r1][r2];
112  // Each negative case correspond to a level of knowledge
113  if (value >= 0)
114  {
115  // otbMsgDebugMacro(<<"RCC8GraphFilter: leaving GetKnowledge method: FULL");
116  return KnowledgeStateType(FULL, static_cast<RCC8ValueType>(value));
117  }
118  else if (value == -1)
119  {
120  // otbMsgDebugMacro(<<"RCC8GraphFilter: leaving GetKnowledge method: LEVEL_1");
121  return KnowledgeStateType(LEVEL_1, OTB_RCC8_DC);
122  }
123  else if (value == -2)
124  {
125  // otbMsgDebugMacro(<<"RCC8GraphFilter: leaving GetKnowledge method.LEVEL_3");
126  return KnowledgeStateType(LEVEL_3, OTB_RCC8_DC);
127  }
128  else
129  {
130  // otbMsgDebugMacro(<<"RCC8GraphFilter: leaving GetKnowledge method.NO_INFO");
131  return KnowledgeStateType(NO_INFO, OTB_RCC8_DC);
132  }
133 }
137 template <class TInputImage, class TOutputGraph>
138 void
141 {
142  // Input image list pointer
143  InputImageListPointerType segList = this->GetInput();
144 
145  // Ouptut graph pointer
146  OutputGraphPointerType graph = this->GetOutput();
147 
148  // invert value vector
151 
152  // Some typedefs
153  typedef otb::ImageToEdgePathFilter<InputImageType, PathType> EdgeExtractionFilterType;
154  typedef otb::SimplifyPathListFilter<PathType> SimplifyPathFilterType;
155  typedef typename SimplifyPathFilterType::InputListType PathListType;
156 
157  typedef itk::MinimumMaximumImageCalculator<InputImageType> MinMaxCalculatorType;
158  typedef PolygonToPolygonRCC8Calculator<PathType> RCC8CalculatorType;
159  typedef RCC8VertexIterator<OutputGraphType> VertexIteratorType;
160  typedef RCC8InEdgeIterator<OutputGraphType> InEdgeIteratorType;
161 
162 
163  // Vector of label
164  std::vector<PixelType> maxLabelVector;
165 
166  // Vertex indexes
167  unsigned int vertexIndex = 0;
168  unsigned int segmentationImageIndex = 0;
169  unsigned int nbVertices = 0;
170 
171  // For each segmentation image
172  for (ConstListIteratorType it = segList->Begin(); it != segList->End(); ++it)
173  {
174  // Compute the maximum label
175  typename MinMaxCalculatorType::Pointer minMax = MinMaxCalculatorType::New();
176  minMax->SetImage(it.Get());
177  minMax->ComputeMaximum();
178  maxLabelVector.push_back(minMax->GetMaximum());
179  otbMsgDebugMacro(<< "Number of objects in image " << segmentationImageIndex << ": "
180  << minMax->GetMaximum());
181 
182  // then for each region of the images
183  for (PixelType label = 1; label <= maxLabelVector.back(); ++label)
184  {
185  typename PathListType::Pointer region = PathListType::New();
186  typename EdgeExtractionFilterType::Pointer extraction = EdgeExtractionFilterType::New();
187  extraction->SetInput(it.Get());
188  extraction->SetForegroundValue(label);
189  extraction->Update();
190  region->PushBack(extraction->GetOutput());
191  typename SimplifyPathFilterType::Pointer simplifier = SimplifyPathFilterType::New();
192  simplifier->SetInput(region);
193  simplifier->GetFunctor().SetTolerance(0.1);
194  simplifier->Update();
195 
196  // Create a new vertex
197  VertexPointerType vertex = VertexType::New();
198  // Set its properties
199  vertex->SetPath(simplifier->GetOutput()->GetNthElement(0));
200  vertex->SetSegmentationLevel(segmentationImageIndex / 2);
201  vertex->SetSegmentationType(segmentationImageIndex % 2);
202  // Put it in the graph
203  graph->SetVertex(vertexIndex, vertex);
204  ++vertexIndex;
205  ++nbVertices;
206  }
207  ++segmentationImageIndex;
208  }
209 
210  itk::ProgressReporter progress(this, 0, nbVertices*nbVertices);
211 
212  VertexIteratorType vIt1(graph);
213  VertexIteratorType vIt2(graph);
214 
215  // For each couple of vertices
216  for (vIt1.GoToBegin(); !vIt1.IsAtEnd(); ++vIt1)
217  {
218  for (vIt2.GoToBegin(); !vIt2.IsAtEnd(); ++vIt2)
219  {
220  //We do not examine each couple because of the RCC8 symmetry
221  if (vIt1.GetIndex() < vIt2.GetIndex())
222  {
223 
224  // Compute the RCC8 relation
225  typename RCC8CalculatorType::Pointer calc = RCC8CalculatorType::New();
226  calc->SetPolygon1(vIt1.Get()->GetPath());
227  calc->SetPolygon2(vIt2.Get()->GetPath());
228  RCC8ValueType value = OTB_RCC8_DC;
229 
230  // if the optimisations are activated
231  if (m_Optimisation)
232  {
233  // otbMsgDebugMacro(<<"RCC8GraphFilter: Entering optimisation loop");
234  InEdgeIteratorType inIt1(vIt1.GetIndex(), graph);
235  InEdgeIteratorType inIt2(vIt2.GetIndex(), graph);
236  // otbMsgDebugMacro(<<"Optimisation loop: iterators initialised");
237  VertexDescriptorType betweenIndex;
238  KnowledgeStateType know(NO_INFO, OTB_RCC8_DC);
239  inIt1.GoToBegin();
240 
241  // Iterate through the edges going to the first vertex
242  while (!inIt1.IsAtEnd() && (know.first != FULL))
243  {
244  betweenIndex = inIt1.GetSourceIndex();
245  inIt2.GoToBegin();
246  bool edgeFound = false;
247  while (!inIt2.IsAtEnd() && (know.first != FULL))
248  {
249  // try to find an intermediate vertex between the two ones which
250  // we vant to compute the relationship
251  if (inIt2.GetSourceIndex() == betweenIndex)
252  {
253  // if an intermediate vertex is found
254  edgeFound = true;
255  // otbMsgDebugMacro(<<"Optimisation loop: found an intermediary vertex:" <<betweenIndex);
256  // See if it brings some info on the RCCC8 value
257  know = GetKnowledge(invert[inIt1.GetValue()], inIt2.GetValue());
258  calc->SetLevel1APrioriKnowledge(know.first == LEVEL_1);
259  calc->SetLevel3APrioriKnowledge(know.first == LEVEL_3);
260  // otbMsgDebugMacro(<<"Optimisation loop: knowledge: "<<know.first<<","<<know.second);
261  }
262  ++inIt2;
263  }
264  // If no intermediate was found
265  if (!edgeFound)
266  {
267  // otbMsgDebugMacro(<<"Optimisation loop: found an intermediary vertex:" <<betweenIndex);
268  // Try using a DC relationship
269  know = GetKnowledge(invert[inIt1.GetValue()], OTB_RCC8_DC);
270  calc->SetLevel1APrioriKnowledge(know.first == LEVEL_1);
271  calc->SetLevel3APrioriKnowledge(know.first == LEVEL_3);
272  // otbMsgDebugMacro(<<"Optimisation loop: knowledge: "<<know.first<<","<<know.second);
273  }
274  ++inIt1;
275  }
276  // If the search has fully determined the RCC8
277  if (know.first == FULL)
278  {
279  // Get the value
280  value = know.second;
281  }
282  else
283  {
284  // Else trigger the computation
285  // (which will take the optimisation phase info into account)
286  calc->Compute();
287  value = calc->GetValue();
288  }
289  // otbMsgDebugMacro(<<"RCC8GraphFilter: Leaving optimisation loop");
290  }
291  // If the optimisations are not activated
292  else
293  {
294  calc->Compute();
295  value = calc->GetValue();
296  }
297  m_Accumulator[value] += 1;
298  m_Accumulator[invert[value]] += 1;
299  // If the vertices are connected
300  if (value > OTB_RCC8_DC)
301  {
302  // Add the edge to the graph.
303  otbMsgDevMacro(<< "Adding edge: " << vIt1.GetIndex() << " -> " << vIt2.GetIndex() << ": " << value);
304  graph->AddEdge(vIt1.GetIndex(), vIt2.GetIndex(), value);
305  }
306  }
307  progress.CompletedPixel();
308  progress.CompletedPixel();
309  }
310  }
311 }
312 
313 template <class TInputImage, class TOutputGraph>
314 void
316 ::PrintSelf(std::ostream& os, itk::Indent indent) const
317 {
318  Superclass::PrintSelf(os, indent);
319 }
320 } // end namespace otb
321 #endif
OutputGraphType::RCC8ValueType RCC8ValueType
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:55
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.
void PrintSelf(std::ostream &os, itk::Indent indent) const
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:95