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