22 #ifndef otbLabelImageRegionPruningFilter_hxx
23 #define otbLabelImageRegionPruningFilter_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_NumberOfComponentsPerPixel = 0;
37 m_MinRegionSize = 100;
39 this->SetNumberOfRequiredInputs(2);
41 this->SetNumberOfRequiredOutputs(2);
42 this->SetNthOutput(0, OutputLabelImageType::New());
43 this->SetNthOutput(1, OutputClusteredImageType::New());
46 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
48 const TInputLabelImage* labelImage)
51 this->SetNthInput(0,
const_cast<TInputLabelImage*
>(labelImage));
54 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
56 const TInputSpectralImage* spectralImage)
59 this->SetNthInput(1,
const_cast<TInputSpectralImage*
>(spectralImage));
62 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
65 return dynamic_cast<TInputLabelImage*
>(itk::ProcessObject::GetInput(0));
68 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
71 return dynamic_cast<TInputSpectralImage*
>(itk::ProcessObject::GetInput(1));
75 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
80 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
83 if (this->GetNumberOfOutputs() < 1)
90 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
93 if (this->GetNumberOfOutputs() < 1)
97 return static_cast<OutputLabelImageType*
>(this->itk::ProcessObject::GetOutput(0));
100 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
104 if (this->GetNumberOfOutputs() < 2)
111 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
115 if (this->GetNumberOfOutputs() < 2)
119 return static_cast<OutputClusteredImageType*
>(this->itk::ProcessObject::GetOutput(1));
122 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
125 Superclass::GenerateOutputInformation();
127 unsigned int numberOfComponentsPerPixel = this->GetInputSpectralImage()->GetNumberOfComponentsPerPixel();
129 if (this->GetClusteredOutput())
131 this->GetClusteredOutput()->SetNumberOfComponentsPerPixel(numberOfComponentsPerPixel);
135 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
137 itk::DataObject* itkNotUsed(output))
140 for (
unsigned int j = 0; j < this->GetNumberOfOutputs(); j++)
142 if (this->itk::ProcessObject::GetOutput(j))
144 this->itk::ProcessObject::GetOutput(j)->SetRequestedRegionToLargestPossibleRegion();
149 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
152 typename InputSpectralImageType::Pointer spectralImage = this->GetInputSpectralImage();
153 typename InputLabelImageType::Pointer inputLabelImage = this->GetInputLabelImage();
154 typename OutputLabelImageType::Pointer outputLabelImage = this->GetLabelOutput();
155 typename OutputClusteredImageType::Pointer outputClusteredImage = this->GetClusteredOutput();
158 outputLabelImage->SetBufferedRegion(outputLabelImage->GetRequestedRegion());
159 outputLabelImage->Allocate();
160 outputClusteredImage->SetBufferedRegion(outputClusteredImage->GetRequestedRegion());
161 outputClusteredImage->Allocate();
163 m_NumberOfComponentsPerPixel = spectralImage->GetNumberOfComponentsPerPixel();
167 typename itk::ImageRegionConstIterator<InputLabelImageType> inputIt(inputLabelImage, outputLabelImage->GetRequestedRegion());
168 typename itk::ImageRegionIterator<OutputLabelImageType> outputIt(outputLabelImage, outputLabelImage->GetRequestedRegion());
170 outputIt.GoToBegin();
171 while (!inputIt.IsAtEnd())
173 outputIt.Set(inputIt.Get());
179 unsigned int regionCount = regionAdjacencyMap.size() - 1;
182 m_CanonicalLabels.clear();
183 m_CanonicalLabels.resize(regionCount + 1);
186 m_Modes.reserve(regionCount + 1);
187 for (
unsigned int i = 0; i < regionCount + 1; ++i)
192 m_PointCounts.clear();
193 m_PointCounts.resize(regionCount + 1);
197 typename itk::ImageRegionConstIterator<InputLabelImageType> inputItWithIndex(inputLabelImage, outputLabelImage->GetRequestedRegion());
198 inputItWithIndex.GoToBegin();
199 while (!inputItWithIndex.IsAtEnd())
201 LabelType label = inputItWithIndex.Get();
203 if (m_PointCounts[label] == 0)
206 m_Modes[label] = spectralImage->GetPixel(inputItWithIndex.GetIndex());
208 m_PointCounts[label]++;
213 bool finishedPruning =
false;
214 unsigned int pruneIterations = 0;
215 unsigned int minRegionCount = 0;
223 for (
LabelType curLabel = 1; curLabel <= regionCount; ++curLabel)
225 m_CanonicalLabels[curLabel] = curLabel;
234 for (
LabelType curLabel = 1; curLabel <= regionCount; ++curLabel)
237 if ((m_PointCounts[curLabel] == 0) || (m_PointCounts[curLabel] > m_MinRegionSize))
247 typename AdjacentLabelsContainerType::const_iterator adjIt = regionAdjacencyMap[curLabel].begin();
250 RealType bestNorm2 = itk::NumericTraits<float>::max();
252 while (adjIt != regionAdjacencyMap[curLabel].end())
255 assert(adjLabel <= regionCount);
263 for (
unsigned int comp = 0; comp < m_NumberOfComponentsPerPixel; ++comp)
266 e = (curSpectral[comp] - adjSpectral[comp]);
269 if (norm2 < bestNorm2)
272 neighborCandidate = adjLabel;
277 if (neighborCandidate != 0)
281 while (m_CanonicalLabels[curCanLabel] != curCanLabel)
283 curCanLabel = m_CanonicalLabels[curCanLabel];
287 LabelType adjCanLabel = neighborCandidate;
288 while (m_CanonicalLabels[adjCanLabel] != adjCanLabel)
290 adjCanLabel = m_CanonicalLabels[adjCanLabel];
294 if (curCanLabel < adjCanLabel)
296 m_CanonicalLabels[adjCanLabel] = curCanLabel;
300 m_CanonicalLabels[m_CanonicalLabels[curCanLabel]] = adjCanLabel;
301 m_CanonicalLabels[curCanLabel] = adjCanLabel;
310 for (
LabelType i = 1; i < regionCount + 1; ++i)
313 while (m_CanonicalLabels[can] != can)
315 can = m_CanonicalLabels[can];
317 m_CanonicalLabels[i] = can;
323 std::vector<SpectralPixelType> newModes;
324 newModes.reserve(regionCount + 1);
325 for (
unsigned int i = 0; i < regionCount + 1; ++i)
329 std::vector<unsigned int> newPointCounts(regionCount + 1);
331 for (
unsigned int i = 1; i < regionCount + 1; ++i)
334 newPointCounts[i] = 0;
337 for (
unsigned int i = 1; i < regionCount + 1; ++i)
339 LabelType canLabel = m_CanonicalLabels[i];
340 unsigned int nPoints = m_PointCounts[i];
341 for (
unsigned int comp = 0; comp < m_NumberOfComponentsPerPixel; ++comp)
343 newModes[canLabel][comp] += nPoints * m_Modes[i][comp];
345 newPointCounts[canLabel] += nPoints;
350 std::vector<LabelType> newLabels(regionCount + 1);
351 std::vector<bool> newLabelSet(regionCount + 1);
352 for (
unsigned int i = 1; i < regionCount + 1; ++i)
354 newLabelSet[i] =
false;
358 for (
unsigned int i = 1; i < regionCount + 1; ++i)
360 LabelType canLabel = m_CanonicalLabels[i];
361 if (newLabelSet[canLabel] ==
false)
363 newLabelSet[canLabel] =
true;
365 newLabels[canLabel] = label;
366 unsigned int nPoints = newPointCounts[canLabel];
367 for (
unsigned int comp = 0; comp < m_NumberOfComponentsPerPixel; ++comp)
369 m_Modes[label][comp] = newModes[canLabel][comp] / nPoints;
372 m_PointCounts[label] = newPointCounts[canLabel];
376 unsigned int oldRegionCount = regionCount;
381 outputIt.GoToBegin();
382 while (!outputIt.IsAtEnd())
387 itkAssertOrThrowMacro(m_CanonicalLabels[l] <= oldRegionCount,
"Found a label greater than region count") canLabel = newLabels[m_CanonicalLabels[l]];
388 outputIt.Set(canLabel);
393 finishedPruning = !minRegionCount || regionCount == 1 || pruneIterations >= 10;
397 if (!finishedPruning)
400 regionAdjacencyMap = LabelImageToRegionAdjacencyMap(outputLabelImage);
404 }
while (!finishedPruning);
411 itk::ImageRegionIterator<OutputClusteredImageType> outputClusteredIt(outputClusteredImage, outputClusteredImage->GetRequestedRegion());
412 outputClusteredIt.GoToBegin();
413 outputIt.GoToBegin();
414 while (!outputClusteredIt.IsAtEnd())
418 outputClusteredIt.Set(p);
424 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
426 itk::Indent indent)
const
428 Superclass::PrintSelf(os, indent);
429 os << indent <<
"Minimum Region Size: " << m_MinRegionSize << std::endl;
433 template <
class TInputLabelImage,
class TInputSpectralImage,
class TOutputLabelImage,
class TOutputClusteredImage>
436 typename OutputLabelImageType::Pointer labelImage)
442 itk::ImageRegionConstIterator<OutputLabelImageType> it(labelImage, labelImage->GetRequestedRegion());
445 while (!it.IsAtEnd())
448 maxLabel = std::max(maxLabel, label);
453 ram.resize(maxLabel + 1);
457 RegionType regionWithoutBottomRightBorders = labelImage->GetRequestedRegion();
458 SizeType size = regionWithoutBottomRightBorders.GetSize();
459 for (
unsigned int d = 0; d < ImageDimension; ++d)
461 regionWithoutBottomRightBorders.SetSize(size);
462 itk::ImageRegionConstIteratorWithIndex<OutputLabelImageType> inputIt(labelImage, regionWithoutBottomRightBorders);
465 while (!inputIt.IsAtEnd())
471 for (
unsigned int d = 0; d < ImageDimension; ++d)
476 LabelType neighborLabel = labelImage->GetPixel(neighborIndex);
479 if (neighborLabel != label)
481 ram[label].insert(neighborLabel);
482 ram[neighborLabel].insert(label);