22 #ifndef otbLabelImageRegionMergingFilter_hxx
23 #define otbLabelImageRegionMergingFilter_hxx
26 #include "itkImageRegionConstIteratorWithIndex.h"
27 #include "itkImageRegionIterator.h"
28 #include "itkProgressReporter.h"
33 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
36 m_RangeBandwidth = 1.0;
37 m_NumberOfComponentsPerPixel = 0;
38 this->SetNumberOfRequiredInputs(2);
40 this->SetNumberOfRequiredOutputs(2);
41 this->SetNthOutput(0, OutputLabelImageType::New());
42 this->SetNthOutput(1, OutputClusteredImageType::New());
45 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
47 const TInputLabelImage* labelImage)
50 this->SetNthInput(0,
const_cast<TInputLabelImage*
>(labelImage));
53 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
55 const TInputSpectralImage* spectralImage)
58 this->SetNthInput(1,
const_cast<TInputSpectralImage*
>(spectralImage));
61 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
64 return dynamic_cast<TInputLabelImage*
>(itk::ProcessObject::GetInput(0));
67 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
70 return dynamic_cast<TInputSpectralImage*
>(itk::ProcessObject::GetInput(1));
74 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
79 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
82 if (this->GetNumberOfOutputs() < 1)
89 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
92 if (this->GetNumberOfOutputs() < 1)
96 return static_cast<OutputLabelImageType*
>(this->itk::ProcessObject::GetOutput(0));
99 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
103 if (this->GetNumberOfOutputs() < 2)
110 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
114 if (this->GetNumberOfOutputs() < 2)
118 return static_cast<OutputClusteredImageType*
>(this->itk::ProcessObject::GetOutput(1));
121 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
124 Superclass::GenerateOutputInformation();
126 unsigned int numberOfComponentsPerPixel = this->GetInputSpectralImage()->GetNumberOfComponentsPerPixel();
128 if (this->GetClusteredOutput())
130 this->GetClusteredOutput()->SetNumberOfComponentsPerPixel(numberOfComponentsPerPixel);
134 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
136 itk::DataObject* itkNotUsed(output))
139 for (
unsigned int j = 0; j < this->GetNumberOfOutputs(); j++)
141 if (this->itk::ProcessObject::GetOutput(j))
143 this->itk::ProcessObject::GetOutput(j)->SetRequestedRegionToLargestPossibleRegion();
148 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
151 typename InputSpectralImageType::Pointer spectralImage = this->GetInputSpectralImage();
152 typename InputLabelImageType::Pointer inputLabelImage = this->GetInputLabelImage();
153 typename OutputLabelImageType::Pointer outputLabelImage = this->GetLabelOutput();
154 typename OutputClusteredImageType::Pointer outputClusteredImage = this->GetClusteredOutput();
157 outputLabelImage->SetBufferedRegion(outputLabelImage->GetRequestedRegion());
158 outputLabelImage->Allocate();
159 outputClusteredImage->SetBufferedRegion(outputClusteredImage->GetRequestedRegion());
160 outputClusteredImage->Allocate();
162 m_NumberOfComponentsPerPixel = spectralImage->GetNumberOfComponentsPerPixel();
166 typename itk::ImageRegionConstIterator<InputLabelImageType> inputIt(inputLabelImage, outputLabelImage->GetRequestedRegion());
167 typename itk::ImageRegionIterator<OutputLabelImageType> outputIt(outputLabelImage, outputLabelImage->GetRequestedRegion());
169 outputIt.GoToBegin();
170 while (!inputIt.IsAtEnd())
172 outputIt.Set(inputIt.Get());
178 unsigned int regionCount = regionAdjacencyMap.size() - 1;
181 m_CanonicalLabels.clear();
182 m_CanonicalLabels.resize(regionCount + 1);
185 m_Modes.reserve(regionCount + 1);
186 for (
unsigned int i = 0; i < regionCount + 1; ++i)
191 m_PointCounts.clear();
192 m_PointCounts.resize(regionCount + 1);
196 typename itk::ImageRegionConstIterator<InputLabelImageType> inputItWithIndex(inputLabelImage, outputLabelImage->GetRequestedRegion());
197 inputItWithIndex.GoToBegin();
198 while (!inputItWithIndex.IsAtEnd())
200 LabelType label = inputItWithIndex.Get();
202 if (m_PointCounts[label] == 0)
205 m_Modes[label] = spectralImage->GetPixel(inputItWithIndex.GetIndex());
207 m_PointCounts[label]++;
212 bool finishedMerging =
false;
213 unsigned int mergeIterations = 0;
219 while (!finishedMerging)
223 for (
LabelType curLabel = 1; curLabel <= regionCount; ++curLabel)
224 m_CanonicalLabels[curLabel] = curLabel;
228 for (
LabelType curLabel = 1; curLabel <= regionCount; ++curLabel)
231 if (m_PointCounts[curLabel] == 0)
240 typename AdjacentLabelsContainerType::const_iterator adjIt = regionAdjacencyMap[curLabel].begin();
241 while (adjIt != regionAdjacencyMap[curLabel].end())
244 assert(adjLabel <= regionCount);
247 bool isSimilar =
true;
249 for (
unsigned int comp = 0; comp < m_NumberOfComponentsPerPixel; ++comp)
252 e = (curSpectral[comp] - adjSpectral[comp]) / m_RangeBandwidth;
255 isSimilar = norm2 < 0.25;
261 while (m_CanonicalLabels[curCanLabel] != curCanLabel)
263 curCanLabel = m_CanonicalLabels[curCanLabel];
268 while (m_CanonicalLabels[adjCanLabel] != adjCanLabel)
270 adjCanLabel = m_CanonicalLabels[adjCanLabel];
274 if (curCanLabel < adjCanLabel)
276 m_CanonicalLabels[adjCanLabel] = curCanLabel;
280 m_CanonicalLabels[m_CanonicalLabels[curCanLabel]] = adjCanLabel;
281 m_CanonicalLabels[curCanLabel] = adjCanLabel;
290 for (
LabelType i = 1; i < regionCount + 1; ++i)
293 while (m_CanonicalLabels[can] != can)
295 can = m_CanonicalLabels[can];
297 m_CanonicalLabels[i] = can;
303 std::vector<SpectralPixelType> newModes;
304 newModes.reserve(regionCount + 1);
305 for (
unsigned int i = 0; i < regionCount + 1; ++i)
309 std::vector<unsigned int> newPointCounts(regionCount + 1);
311 for (
unsigned int i = 1; i < regionCount + 1; ++i)
314 newPointCounts[i] = 0;
317 for (
unsigned int i = 1; i < regionCount + 1; ++i)
319 LabelType canLabel = m_CanonicalLabels[i];
320 unsigned int nPoints = m_PointCounts[i];
321 for (
unsigned int comp = 0; comp < m_NumberOfComponentsPerPixel; ++comp)
323 newModes[canLabel][comp] += nPoints * m_Modes[i][comp];
325 newPointCounts[canLabel] += nPoints;
330 std::vector<LabelType> newLabels(regionCount + 1);
331 std::vector<bool> newLabelSet(regionCount + 1);
332 for (
unsigned int i = 1; i < regionCount + 1; ++i)
334 newLabelSet[i] =
false;
338 for (
unsigned int i = 1; i < regionCount + 1; ++i)
340 LabelType canLabel = m_CanonicalLabels[i];
341 if (newLabelSet[canLabel] ==
false)
343 newLabelSet[canLabel] =
true;
345 newLabels[canLabel] = label;
346 unsigned int nPoints = newPointCounts[canLabel];
347 for (
unsigned int comp = 0; comp < m_NumberOfComponentsPerPixel; ++comp)
349 m_Modes[label][comp] = newModes[canLabel][comp] / nPoints;
352 m_PointCounts[label] = newPointCounts[canLabel];
356 unsigned int oldRegionCount = regionCount;
360 outputIt.GoToBegin();
361 while (!outputIt.IsAtEnd())
366 assert(m_CanonicalLabels[l] <= oldRegionCount);
367 canLabel = newLabels[m_CanonicalLabels[l]];
368 outputIt.Set(canLabel);
373 finishedMerging = oldRegionCount == regionCount || mergeIterations >= 10 || regionCount == 1;
377 if (!finishedMerging)
380 regionAdjacencyMap = LabelImageToRegionAdjacencyMap(outputLabelImage);
389 itk::ImageRegionIterator<OutputClusteredImageType> outputClusteredIt(outputClusteredImage, outputClusteredImage->GetRequestedRegion());
390 outputClusteredIt.GoToBegin();
391 outputIt.GoToBegin();
392 while (!outputClusteredIt.IsAtEnd())
396 outputClusteredIt.Set(p);
402 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
404 itk::Indent indent)
const
406 Superclass::PrintSelf(os, indent);
407 os << indent <<
"Range bandwidth: " << m_RangeBandwidth << std::endl;
411 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
414 typename OutputLabelImageType::Pointer labelImage)
420 itk::ImageRegionConstIterator<OutputLabelImageType> it(labelImage, labelImage->GetRequestedRegion());
423 while (!it.IsAtEnd())
426 maxLabel = std::max(maxLabel, label);
431 ram.resize(maxLabel + 1);
435 RegionType regionWithoutBottomRightBorders = labelImage->GetRequestedRegion();
436 SizeType size = regionWithoutBottomRightBorders.GetSize();
437 for (
unsigned int d = 0; d < ImageDimension; ++d)
439 regionWithoutBottomRightBorders.SetSize(size);
440 itk::ImageRegionConstIteratorWithIndex<OutputLabelImageType> inputIt(labelImage, regionWithoutBottomRightBorders);
443 while (!inputIt.IsAtEnd())
449 for (
unsigned int d = 0; d < ImageDimension; ++d)
454 LabelType neighborLabel = labelImage->GetPixel(neighborIndex);
457 if (neighborLabel != label)
459 ram[label].insert(neighborLabel);
460 ram[neighborLabel].insert(label);