22 #ifndef otbLabelImageToLabelMapWithAdjacencyFilter_hxx
23 #define otbLabelImageToLabelMapWithAdjacencyFilter_hxx
26 #include "itkNumericTraits.h"
27 #include "itkProgressReporter.h"
28 #include "itkImageLinearConstIteratorWithIndex.h"
29 #include "itkImageRegionConstIteratorWithIndex.h"
34 template <
class TInputImage,
class TOutputImage>
37 m_BackgroundValue = itk::NumericTraits<OutputImagePixelType>::NonpositiveMin();
40 template <
class TInputImage,
class TOutputImage>
43 for (
unsigned int idx = 0; idx < this->GetNumberOfInputs(); ++idx)
48 input->SetRequestedRegionToLargestPossibleRegion();
61 this->CallCopyOutputRegionToInputRegion(inputRegion, this->GetOutput()->GetRequestedRegion());
62 input->SetRequestedRegion(inputRegion);
68 template <
class TInputImage,
class TOutputImage>
74 template <
class TInputImage,
class TOutputImage>
78 m_TemporaryImages.resize(this->GetNumberOfThreads());
80 m_TemporaryAdjacencyMaps.resize(this->GetNumberOfThreads());
82 for (
unsigned int i = 0; i < this->GetNumberOfThreads(); ++i)
87 m_TemporaryImages[0] = this->GetOutput();
92 m_TemporaryImages[i] = OutputImageType::New();
96 m_TemporaryImages[i]->SetBackgroundValue(m_BackgroundValue);
101 template <
class TInputImage,
class TOutputImage>
105 if (m_TemporaryAdjacencyMaps[threadId].
find(label2) != m_TemporaryAdjacencyMaps[threadId].end())
107 m_TemporaryAdjacencyMaps[threadId][label2].insert(label1);
112 newContainer.insert(label1);
113 m_TemporaryAdjacencyMaps[threadId][label2] = newContainer;
116 if (m_TemporaryAdjacencyMaps[threadId].
find(label1) != m_TemporaryAdjacencyMaps[threadId].end())
118 m_TemporaryAdjacencyMaps[threadId][label1].insert(label2);
123 newContainer.insert(label2);
124 m_TemporaryAdjacencyMaps[threadId][label1] = newContainer;
128 template <
class TInputImage,
class TOutputImage>
132 typename RLEVectorType::const_iterator it = line.begin();
137 while (it != line.end())
143 this->AddAdjacency(previousLabel, nextLabel, threadId);
146 previousLabel = nextLabel;
151 template <
class TInputImage,
class TOutputImage>
153 itk::ThreadIdType threadId)
159 for (
typename RLEVectorType::const_iterator it1 = line1.begin(); it1 != line1.end(); ++it1)
162 long start1 = it1->where[0];
163 long end1 = start1 + it1->length - 1;
167 for (
typename RLEVectorType::const_iterator it2 = line2.begin(); it2 != line2.end(); ++it2)
170 long start2 = it2->where[0];
171 long end2 = start2 + it2->length - 1;
175 if (label1 != label2)
178 if (((start1 >= start2 - offset) && (start1 <= end2 + offset)) || ((end1 >= start2 - offset) && (end1 <= end2 + offset)) ||
179 ((start2 >= start1 - offset) && (start2 <= end1 + offset)) || ((end2 >= start1 - offset) && (end2 <= end1 + offset)))
182 this->AddAdjacency(label1, label2, threadId);
189 template <
class TInputImage,
class TOutputImage>
191 itk::ThreadIdType threadId)
193 itk::ProgressReporter progress(
this, threadId, regionForThread.GetNumberOfPixels());
195 typedef itk::ImageLinearConstIteratorWithIndex<InputImageType> InputLineIteratorType;
197 InputLineIteratorType it(this->GetInput(), regionForThread);
204 typename InputImageType::RegionType previousLineRegion;
205 typename InputImageType::SizeType previousLineRegionSize;
206 typename InputImageType::IndexType previousLineRegionIndex;
208 previousLineRegionIndex = regionForThread.GetIndex();
209 previousLineRegionIndex[1]--;
211 previousLineRegionSize = regionForThread.GetSize();
212 previousLineRegionSize[1] = 1;
214 previousLineRegion.SetIndex(previousLineRegionIndex);
215 previousLineRegion.SetSize(previousLineRegionSize);
218 if (previousLineRegion.Crop(this->GetInput()->GetRequestedRegion()))
221 itk::ImageRegionConstIteratorWithIndex<InputImageType> pIt(this->GetInput(), previousLineRegion);
225 while (!pIt.IsAtEnd())
229 if (v != m_BackgroundValue)
235 while (!pIt.IsAtEnd() && pIt.Get() == v)
240 previousLine.push_back(
RLE(idx, length, v));
250 for (it.GoToBegin(); !it.IsAtEnd(); it.NextLine())
253 it.GoToBeginOfLine();
259 while (!it.IsAtEndOfLine())
263 if (v != m_BackgroundValue)
269 while (!it.IsAtEndOfLine() && it.Get() == v)
275 m_TemporaryImages[threadId]->SetLine(idx, length, v);
276 currentLine.push_back(
RLE(idx, length, v));
286 if (currentLine.size() > 0)
289 this->ParseLine(currentLine, threadId);
290 this->ParseConsecutiveLines(previousLine, currentLine, threadId);
294 previousLine = currentLine;
299 template <
class TInputImage,
class TOutputImage>
307 for (
unsigned int i = 1; i < this->GetNumberOfThreads(); ++i)
309 typedef typename OutputImageType::LabelObjectVectorType LabelObjectVectorType;
310 const LabelObjectVectorType& labelObjectContainer = m_TemporaryImages[i]->GetLabelObjects();
312 for (
typename LabelObjectVectorType::const_iterator it = labelObjectContainer.begin(); it != labelObjectContainer.end(); ++it)
315 if (output->HasLabel(labelObject->GetLabel()))
319 typedef typename LabelObjectType::ConstLineIterator IteratorType;
321 typename LabelObjectType::LabelObjectType* dest = output->GetLabelObject(labelObject->GetLabel());
324 srcIt = IteratorType(labelObject);
330 while (!srcIt.IsAtEnd())
332 dest->AddLine(srcIt.GetLine());
339 output->AddLabelObject(labelObject);
348 for (itk::ThreadIdType threadId = 1; threadId < this->GetNumberOfThreads(); ++threadId)
351 for (
typename AdjacencyMapType::const_iterator mit = m_TemporaryAdjacencyMaps[threadId].begin(); mit != m_TemporaryAdjacencyMaps[threadId].end(); ++mit)
354 if (adjMap.find(mit->first) != adjMap.end())
359 std::vector<LabelType> mergedLabels(adjLabels1.size() + adjLabels2.size(), 0);
362 typename std::vector<LabelType>::const_iterator vend =
363 set_union(adjLabels1.begin(), adjLabels1.end(), adjLabels2.begin(), adjLabels2.end(), mergedLabels.begin());
367 for (
typename std::vector<LabelType>::const_iterator vit = mergedLabels.begin(); vit != vend; ++vit)
369 mergedLabelsSet.insert(*vit);
373 adjMap[mit->first] = mergedLabelsSet;
378 adjMap[mit->first] = mit->second;
384 output->SetAdjacencyMap(adjMap);
387 m_TemporaryImages.clear();
388 m_TemporaryAdjacencyMaps.clear();
392 template <
class TInputImage,
class TOutputImage>
395 Superclass::PrintSelf(os, indent);
397 os << indent <<
"BackgroundValue: " <<
static_cast<typename itk::NumericTraits<OutputImagePixelType>::PrintType
>(m_BackgroundValue) << std::endl;