22 #ifndef otbLabelImageToLabelMapWithAdjacencyFilter_hxx
23 #define otbLabelImageToLabelMapWithAdjacencyFilter_hxx
27 #include "itkNumericTraits.h"
28 #include "itkProgressReporter.h"
29 #include "itkImageLinearConstIteratorWithIndex.h"
30 #include "itkImageRegionConstIteratorWithIndex.h"
35 template <
class TInputImage,
class TOutputImage>
38 this->DynamicMultiThreadingOff();
39 m_BackgroundValue = itk::NumericTraits<OutputImagePixelType>::NonpositiveMin();
42 template <
class TInputImage,
class TOutputImage>
45 for (
unsigned int idx = 0; idx < this->GetNumberOfInputs(); ++idx)
50 input->SetRequestedRegionToLargestPossibleRegion();
63 this->CallCopyOutputRegionToInputRegion(inputRegion, this->GetOutput()->GetRequestedRegion());
64 input->SetRequestedRegion(inputRegion);
70 template <
class TInputImage,
class TOutputImage>
76 template <
class TInputImage,
class TOutputImage>
80 m_TemporaryImages.resize(this->GetNumberOfWorkUnits());
82 m_TemporaryAdjacencyMaps.resize(this->GetNumberOfWorkUnits());
84 for (
unsigned int i = 0; i < this->GetNumberOfWorkUnits(); ++i)
89 m_TemporaryImages[0] = this->GetOutput();
94 m_TemporaryImages[i] = OutputImageType::New();
98 m_TemporaryImages[i]->SetBackgroundValue(m_BackgroundValue);
103 template <
class TInputImage,
class TOutputImage>
107 if (m_TemporaryAdjacencyMaps[threadId].
find(label2) != m_TemporaryAdjacencyMaps[threadId].end())
109 m_TemporaryAdjacencyMaps[threadId][label2].insert(label1);
114 newContainer.insert(label1);
115 m_TemporaryAdjacencyMaps[threadId][label2] = newContainer;
118 if (m_TemporaryAdjacencyMaps[threadId].
find(label1) != m_TemporaryAdjacencyMaps[threadId].end())
120 m_TemporaryAdjacencyMaps[threadId][label1].insert(label2);
125 newContainer.insert(label2);
126 m_TemporaryAdjacencyMaps[threadId][label1] = newContainer;
130 template <
class TInputImage,
class TOutputImage>
134 typename RLEVectorType::const_iterator it = line.begin();
139 while (it != line.end())
145 this->AddAdjacency(previousLabel, nextLabel, threadId);
148 previousLabel = nextLabel;
153 template <
class TInputImage,
class TOutputImage>
155 itk::ThreadIdType threadId)
161 for (
typename RLEVectorType::const_iterator it1 = line1.begin(); it1 != line1.end(); ++it1)
164 long start1 = it1->where[0];
165 long end1 = start1 + it1->length - 1;
169 for (
typename RLEVectorType::const_iterator it2 = line2.begin(); it2 != line2.end(); ++it2)
172 long start2 = it2->where[0];
173 long end2 = start2 + it2->length - 1;
177 if (label1 != label2)
180 if (((start1 >= start2 - offset) && (start1 <= end2 + offset)) || ((end1 >= start2 - offset) && (end1 <= end2 + offset)) ||
181 ((start2 >= start1 - offset) && (start2 <= end1 + offset)) || ((end2 >= start1 - offset) && (end2 <= end1 + offset)))
184 this->AddAdjacency(label1, label2, threadId);
191 template <
class TInputImage,
class TOutputImage>
193 itk::ThreadIdType threadId)
195 itk::ProgressReporter progress(
this, threadId, regionForThread.GetNumberOfPixels());
197 typedef itk::ImageLinearConstIteratorWithIndex<InputImageType> InputLineIteratorType;
199 InputLineIteratorType it(this->GetInput(), regionForThread);
206 typename InputImageType::RegionType previousLineRegion;
207 typename InputImageType::SizeType previousLineRegionSize;
208 typename InputImageType::IndexType previousLineRegionIndex;
210 previousLineRegionIndex = regionForThread.GetIndex();
211 previousLineRegionIndex[1]--;
213 previousLineRegionSize = regionForThread.GetSize();
214 previousLineRegionSize[1] = 1;
216 previousLineRegion.SetIndex(previousLineRegionIndex);
217 previousLineRegion.SetSize(previousLineRegionSize);
220 if (previousLineRegion.Crop(this->GetInput()->GetRequestedRegion()))
223 itk::ImageRegionConstIteratorWithIndex<InputImageType> pIt(this->GetInput(), previousLineRegion);
227 while (!pIt.IsAtEnd())
231 if (v != m_BackgroundValue)
237 while (!pIt.IsAtEnd() && pIt.Get() == v)
242 previousLine.push_back(
RLE(idx, length, v));
252 for (it.GoToBegin(); !it.IsAtEnd(); it.NextLine())
255 it.GoToBeginOfLine();
261 while (!it.IsAtEndOfLine())
265 if (v != m_BackgroundValue)
271 while (!it.IsAtEndOfLine() && it.Get() == v)
277 m_TemporaryImages[threadId]->SetLine(idx, length, v);
278 currentLine.push_back(
RLE(idx, length, v));
288 if (currentLine.size() > 0)
291 this->ParseLine(currentLine, threadId);
292 this->ParseConsecutiveLines(previousLine, currentLine, threadId);
296 previousLine = currentLine;
301 template <
class TInputImage,
class TOutputImage>
309 for (
unsigned int i = 1; i < this->GetNumberOfWorkUnits(); ++i)
311 typedef typename OutputImageType::LabelObjectVectorType LabelObjectVectorType;
312 const LabelObjectVectorType& labelObjectContainer = m_TemporaryImages[i]->GetLabelObjects();
314 for (
typename LabelObjectVectorType::const_iterator it = labelObjectContainer.begin(); it != labelObjectContainer.end(); ++it)
317 if (output->HasLabel(labelObject->GetLabel()))
321 typedef typename LabelObjectType::ConstLineIterator IteratorType;
323 typename LabelObjectType::LabelObjectType* dest = output->GetLabelObject(labelObject->GetLabel());
326 srcIt = IteratorType(labelObject);
332 while (!srcIt.IsAtEnd())
334 dest->AddLine(srcIt.GetLine());
341 output->AddLabelObject(labelObject);
350 for (itk::ThreadIdType threadId = 1; threadId < this->GetNumberOfWorkUnits(); ++threadId)
353 for (
typename AdjacencyMapType::const_iterator mit = m_TemporaryAdjacencyMaps[threadId].begin(); mit != m_TemporaryAdjacencyMaps[threadId].end(); ++mit)
356 if (adjMap.find(mit->first) != adjMap.end())
361 std::vector<LabelType> mergedLabels(adjLabels1.size() + adjLabels2.size(), 0);
364 typename std::vector<LabelType>::const_iterator vend =
365 set_union(adjLabels1.begin(), adjLabels1.end(), adjLabels2.begin(), adjLabels2.end(), mergedLabels.begin());
369 for (
typename std::vector<LabelType>::const_iterator vit = mergedLabels.begin(); vit != vend; ++vit)
371 mergedLabelsSet.insert(*vit);
375 adjMap[mit->first] = mergedLabelsSet;
380 adjMap[mit->first] = mit->second;
386 output->SetAdjacencyMap(adjMap);
389 m_TemporaryImages.clear();
390 m_TemporaryAdjacencyMaps.clear();
394 template <
class TInputImage,
class TOutputImage>
397 Superclass::PrintSelf(os, indent);
399 os << indent <<
"BackgroundValue: " <<
static_cast<typename itk::NumericTraits<OutputImagePixelType>::PrintType
>(m_BackgroundValue) << std::endl;
InputImageType::PixelType InputImagePixelType
void BeforeThreadedGenerateData() override
void GenerateInputRequestedRegion() override
OutputImageType::LabelObjectType LabelObjectType
void AddAdjacency(LabelType label1, LabelType label2, itk::ThreadIdType threadId)
OutputImageType::LabelType LabelType
LabelImageToLabelMapWithAdjacencyFilter()
InputImageType::IndexType IndexType
OutputImageType::RegionType OutputImageRegionType
void AfterThreadedGenerateData() override
void EnlargeOutputRequestedRegion(itk::DataObject *) override
void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, itk::ThreadIdType threadId) override
InputImageType::RegionType InputImageRegionType
TInputImage InputImageType
void PrintSelf(std::ostream &os, itk::Indent indent) const override
void ParseConsecutiveLines(const RLEVectorType &line1, const RLEVectorType &line2, itk::ThreadIdType threadId)
OutputImageType::AdjacentLabelsContainerType AdjacentLabelsContainerType
void ParseLine(const RLEVectorType &line, itk::ThreadIdType threadId)
OutputImageType::AdjacencyMapType AdjacencyMapType
std::vector< RLE > RLEVectorType
TOutputImage OutputImageType
InputImageType::Pointer InputImagePointer
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
string_view find(string_view const &haystack, string_view const &needle)