OTB  9.0.0
Orfeo Toolbox
otbLabelImageSmallRegionMergingFilter.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2022 Centre National d'Etudes Spatiales (CNES)
3  *
4  * This file is part of Orfeo Toolbox
5  *
6  * https://www.orfeo-toolbox.org/
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 
22 #ifndef otbLabelImageSmallRegionMergingFilter_hxx
23 #define otbLabelImageSmallRegionMergingFilter_hxx
24 
26 #include "itkConstShapedNeighborhoodIterator.h"
27 #include "itkProgressReporter.h"
28 
29 namespace otb
30 {
31 template <class TInputLabelImage>
33 {
34 }
35 
36 template <class TInputLabelImage>
38 {
39  m_LabelPopulation = labelPopulation;
40 
41  // Initialize m_CorrespondingMap to the identity (i.e. m[label] = label)
42  for (auto label : m_LabelPopulation)
43  {
44  m_LUT[label.first] = label.first;
45  }
46 }
47 
48 template <class TInputLabelImage>
51 {
52  return m_LabelPopulation;
53 }
54 
55 
56 template <class TInputLabelImage>
58 {
59  m_LabelStatistic = labelStatistic;
60 }
61 
62 template <class TInputLabelImage>
65 {
66  return m_LabelStatistic;
67 }
68 
69 template <class TInputLabelImage>
72 {
73  return m_LUT;
74 }
75 
76 template <class TInputLabelImage>
78 {
79  m_NeighboursMapsTmp.clear();
80  m_NeighboursMapsTmp.resize(this->GetNumberOfThreads());
81 }
82 
83 template <class TInputLabelImage>
85 {
86  NeighboursMapType neighboursMap;
87 
88  // Merge the neighbours maps from all threads
89  for (unsigned int threadId = 0; threadId < this->GetNumberOfThreads(); threadId++)
90  {
91  for (auto const& neighbours : m_NeighboursMapsTmp[threadId])
92  {
93  neighboursMap[neighbours.first].insert(neighbours.second.begin(), neighbours.second.end());
94  }
95  }
96 
97  // For each label of the label map, find the "closest" connected label,
98  // according to the euclidean distance between the corresponding
99  // m_labelStatistic elements.
100  for (auto const& neighbours : neighboursMap)
101  {
102  double proximity = itk::NumericTraits<double>::max();
103  InputLabelType label = neighbours.first;
104  InputLabelType closestNeighbour = label;
105  auto const& statsLabel = m_LabelStatistic[label];
106 
107  for (auto const& neighbour : neighbours.second)
108  {
109  auto const& statsNeighbour = m_LabelStatistic[neighbour];
110  assert(statsLabel.Size() == statsNeighbour.Size());
111 
112  double distance = (statsLabel - statsNeighbour).GetSquaredNorm();
113  if (distance < proximity)
114  {
115  proximity = distance;
116  closestNeighbour = neighbour;
117  }
118  }
119 
120  auto curLabelLUT = FindCorrespondingLabel(label);
121  auto adjLabelLUT = FindCorrespondingLabel(closestNeighbour);
122 
123  // Keep the smallest label (this prevents infinite loop in the LUT
124  // (like LUT[i]=j and LUT[j]=i)
125  if (curLabelLUT < adjLabelLUT)
126  {
127  m_LUT[adjLabelLUT] = curLabelLUT;
128  }
129  else
130  {
131  m_LUT[curLabelLUT] = adjLabelLUT;
132  }
133  }
134 
135  // Update the LUT
136  for (auto& label : m_LUT)
137  {
138  label.second = FindCorrespondingLabel(label.first);
139  }
140 
141  // Update statistics : for each newly merged segments, sum the population, and
142  // recompute the mean.
143  for (auto const& label : m_LUT)
144  {
145  if ((label.second != label.first) && (m_LabelPopulation[label.first] != 0))
146  {
147  // Cache values to reduce number of lookups
148  auto const& populationFirst = m_LabelPopulation[label.first];
149  auto const& populationSecond = m_LabelPopulation[label.second];
150  auto const& statisticFirst = m_LabelStatistic[label.first];
151  auto const& statisticSecond = m_LabelStatistic[label.second];
152 
153  m_LabelStatistic[label.second] = ((statisticFirst * populationFirst) + (statisticSecond * populationSecond)) / (populationFirst + populationSecond);
154 
155  m_LabelPopulation[label.second] += populationFirst;
156 
157  // Do not use this label anymore
158  m_LabelPopulation[label.first] = 0;
159  }
160  }
161 }
162 
163 template <class TInputLabelImage>
167 {
168  auto correspondingLabel = m_LUT[label];
169  while (label != correspondingLabel)
170  {
171  label = correspondingLabel;
172  correspondingLabel = m_LUT[correspondingLabel];
173  }
174  return correspondingLabel;
175 }
176 
177 template <class TInputLabelImage>
179 {
180  // call the superclass' implementation of this method
181  Superclass::GenerateInputRequestedRegion();
182 
183  // get pointers to the input
184  auto inputPtr = const_cast<TInputLabelImage*>(this->GetInput());
185 
186 
187  // get a copy of the input requested region
188  auto inputRequestedRegion = inputPtr->GetRequestedRegion();
189 
190  // pad the input requested region by the operator radius
191  inputRequestedRegion.PadByRadius(1);
192  // crop the input requested region at the input's largest possible region
193  if (inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()))
194  {
195  inputPtr->SetRequestedRegion(inputRequestedRegion);
196  return;
197  }
198  else
199  {
200  // Couldn't crop the region (requested region is outside the largest
201  // possible region). Throw an exception.
202 
203  // store what we tried to request (prior to trying to crop)
204  inputPtr->SetRequestedRegion(inputRequestedRegion);
205 
206  // build an exception
207  itk::InvalidRequestedRegionError e(__FILE__, __LINE__);
208  e.SetLocation(ITK_LOCATION);
209  e.SetDescription(
210  "Requested region is (at least partially) outside the "
211  "largest possible region.");
212  e.SetDataObject(inputPtr);
213  throw e;
214  }
215 }
216 
217 template <class TInputLabelImage>
218 void PersistentLabelImageSmallRegionMergingFilter<TInputLabelImage>::ThreadedGenerateData(const RegionType& outputRegionForThread, itk::ThreadIdType threadId)
219 {
220  using IteratorType = itk::ImageRegionConstIterator<TInputLabelImage>;
221  using NeighborhoodIteratorType = itk::ConstShapedNeighborhoodIterator<TInputLabelImage>;
222 
223  typename NeighborhoodIteratorType::RadiusType radius;
224  radius.Fill(1);
225 
226  auto labelImage = this->GetInput();
227 
228  IteratorType it(labelImage, outputRegionForThread);
229  NeighborhoodIteratorType itN(radius, labelImage, outputRegionForThread);
230 
231  // 4 connected Neighborhood (top, bottom, left and right)
232  typename IteratorType::OffsetType top = {{0, -1}};
233  itN.ActivateOffset(top);
234  typename IteratorType::OffsetType bottom = {{0, 1}};
235  itN.ActivateOffset(bottom);
236  typename IteratorType::OffsetType right = {{1, 0}};
237  itN.ActivateOffset(right);
238  typename IteratorType::OffsetType left = {{-1, 0}};
239  itN.ActivateOffset(left);
240 
241  for (it.GoToBegin(); !it.IsAtEnd(); ++it, ++itN)
242  {
243  assert(!itN.IsAtEnd());
244  int currentLabel = m_LUT[it.Get()];
245 
246  if (m_LabelPopulation[currentLabel] == m_Size)
247  {
248  for (auto ci = itN.Begin(); !ci.IsAtEnd(); ci++)
249  {
250  int neighbourLabel = m_LUT[ci.Get()];
251  if (neighbourLabel != currentLabel)
252  m_NeighboursMapsTmp[threadId][currentLabel].insert(neighbourLabel);
253  }
254  }
255  }
256 }
257 
258 template <class TInputLabelImage>
260 {
261  Superclass::PrintSelf(os, indent);
262 }
263 
264 template <class TInputLabelImage>
266 {
268 }
269 
270 template <class TInputLabelImage>
272 {
273  m_SmallRegionMergingFilter->GetFilter()->SetInput(labelImage);
274 }
275 
276 template <class TInputLabelImage>
278 {
279  m_SmallRegionMergingFilter->GetFilter()->SetLabelPopulation(labelPopulation);
280 }
281 
282 template <class TInputLabelImage>
285 {
286  return m_SmallRegionMergingFilter->GetFilter()->GetLabelPopulation();
287 }
288 
289 template <class TInputLabelImage>
291 {
292  m_SmallRegionMergingFilter->GetFilter()->SetLabelStatistic(labelStatistic);
293 }
294 
295 template <class TInputLabelImage>
298 {
299  return m_SmallRegionMergingFilter->GetFilter()->GetLabelStatistic();
300 }
301 
302 template <class TInputLabelImage>
304 {
305  return m_SmallRegionMergingFilter->GetFilter()->GetLUT();
306 }
307 
308 template <class TInputLabelImage>
310 {
311  this->GenerateData();
312 }
313 
314 template <class TInputLabelImage>
316 {
317  this->SetProgress(0.0);
318 
319  // Update the filter for all sizes.
320  for (unsigned int size = 1; size < m_MinSize; size++)
321  {
322  m_SmallRegionMergingFilter->GetFilter()->SetSize(size);
323  m_SmallRegionMergingFilter->Update();
324  this->UpdateProgress(static_cast<double>(size + 1) / m_MinSize);
325  }
326 }
327 
328 
329 } // end namespace otb
330 
331 #endif
otb::PersistentLabelImageSmallRegionMergingFilter::SetLabelStatistic
void SetLabelStatistic(LabelStatisticType const &labelStatistic)
Definition: otbLabelImageSmallRegionMergingFilter.hxx:57
otb::PersistentLabelImageSmallRegionMergingFilter::NeighboursMapType
std::unordered_map< InputLabelType, std::set< InputLabelType > > NeighboursMapType
Definition: otbLabelImageSmallRegionMergingFilter.h:76
otb::LabelImageSmallRegionMergingFilter::GetLUT
LUTType const & GetLUT() const
Definition: otbLabelImageSmallRegionMergingFilter.hxx:303
otb::LabelImageSmallRegionMergingFilter::LabelPopulationType
PersistentLabelImageSmallRegionMergingFilterType::LabelPopulationType LabelPopulationType
Definition: otbLabelImageSmallRegionMergingFilter.h:184
otb::LabelImageSmallRegionMergingFilter::LabelImageSmallRegionMergingFilter
LabelImageSmallRegionMergingFilter()
Definition: otbLabelImageSmallRegionMergingFilter.hxx:265
otb::LabelImageSmallRegionMergingFilter::LUTType
PersistentLabelImageSmallRegionMergingFilterType::LUTType LUTType
Definition: otbLabelImageSmallRegionMergingFilter.h:188
otb::LabelImageSmallRegionMergingFilter::LabelStatisticType
PersistentLabelImageSmallRegionMergingFilterType::LabelStatisticType LabelStatisticType
Definition: otbLabelImageSmallRegionMergingFilter.h:186
otb::PersistentLabelImageSmallRegionMergingFilter::GetLabelPopulation
LabelPopulationType const & GetLabelPopulation() const
Definition: otbLabelImageSmallRegionMergingFilter.hxx:50
otb::PersistentLabelImageSmallRegionMergingFilter::LUTType
std::unordered_map< InputLabelType, InputLabelType > LUTType
Definition: otbLabelImageSmallRegionMergingFilter.h:80
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::PersistentLabelImageSmallRegionMergingFilter::FindCorrespondingLabel
InputLabelType FindCorrespondingLabel(InputLabelType label)
Definition: otbLabelImageSmallRegionMergingFilter.hxx:165
otb::PersistentLabelImageSmallRegionMergingFilter::GenerateInputRequestedRegion
void GenerateInputRequestedRegion() override
Definition: otbLabelImageSmallRegionMergingFilter.hxx:178
otb::LabelImageSmallRegionMergingFilter::SetInputLabelImage
void SetInputLabelImage(const TInputLabelImage *labelImage)
Definition: otbLabelImageSmallRegionMergingFilter.hxx:271
otb::LabelImageSmallRegionMergingFilter::GetLabelPopulation
LabelPopulationType const & GetLabelPopulation() const
Definition: otbLabelImageSmallRegionMergingFilter.hxx:284
otb::PersistentLabelImageSmallRegionMergingFilter::GetLabelStatistic
LabelStatisticType const & GetLabelStatistic() const
Definition: otbLabelImageSmallRegionMergingFilter.hxx:64
otb::LabelImageSmallRegionMergingFilter::m_SmallRegionMergingFilter
LabelImageSmallRegionMergingFilterType::Pointer m_SmallRegionMergingFilter
Definition: otbLabelImageSmallRegionMergingFilter.h:233
otb::PersistentLabelImageSmallRegionMergingFilter::RegionType
InputImageType::RegionType RegionType
Definition: otbLabelImageSmallRegionMergingFilter.h:72
otbLabelImageSmallRegionMergingFilter.h
otb::PersistentFilterStreamingDecorator::New
static Pointer New()
otb::PersistentLabelImageSmallRegionMergingFilter::InputLabelType
InputImageType::PixelType InputLabelType
Definition: otbLabelImageSmallRegionMergingFilter.h:69
otb::PersistentLabelImageSmallRegionMergingFilter::Reset
virtual void Reset(void) override
Definition: otbLabelImageSmallRegionMergingFilter.hxx:77
otb::LabelImageSmallRegionMergingFilter::GetLabelStatistic
LabelStatisticType const & GetLabelStatistic() const
Definition: otbLabelImageSmallRegionMergingFilter.hxx:297
otb::PersistentLabelImageSmallRegionMergingFilter::PersistentLabelImageSmallRegionMergingFilter
PersistentLabelImageSmallRegionMergingFilter()
Definition: otbLabelImageSmallRegionMergingFilter.hxx:32
otb::PersistentLabelImageSmallRegionMergingFilter::Synthetize
virtual void Synthetize(void) override
Definition: otbLabelImageSmallRegionMergingFilter.hxx:84
otb::LabelImageSmallRegionMergingFilter::SetLabelPopulation
void SetLabelPopulation(LabelPopulationType const &labelPopulation)
Definition: otbLabelImageSmallRegionMergingFilter.hxx:277
otb::PersistentLabelImageSmallRegionMergingFilter::LabelPopulationType
std::unordered_map< InputLabelType, double > LabelPopulationType
Definition: otbLabelImageSmallRegionMergingFilter.h:79
otb::LabelImageSmallRegionMergingFilter::SetLabelStatistic
void SetLabelStatistic(LabelStatisticType const &labelStatistic)
Definition: otbLabelImageSmallRegionMergingFilter.hxx:290
otb::LabelImageSmallRegionMergingFilter::Update
void Update() override
Definition: otbLabelImageSmallRegionMergingFilter.hxx:309
otb::PersistentLabelImageSmallRegionMergingFilter::ThreadedGenerateData
void ThreadedGenerateData(const RegionType &outputRegionForThread, itk::ThreadIdType threadId) override
Definition: otbLabelImageSmallRegionMergingFilter.hxx:218
otb::PersistentLabelImageSmallRegionMergingFilter::PrintSelf
void PrintSelf(std::ostream &os, itk::Indent indent) const override
Definition: otbLabelImageSmallRegionMergingFilter.hxx:259
otb::PersistentLabelImageSmallRegionMergingFilter::LabelStatisticType
std::unordered_map< InputLabelType, RealVectorPixelType > LabelStatisticType
Definition: otbLabelImageSmallRegionMergingFilter.h:78
otb::LabelImageSmallRegionMergingFilter::GenerateData
void GenerateData() override
Definition: otbLabelImageSmallRegionMergingFilter.hxx:315
otb::PersistentLabelImageSmallRegionMergingFilter::SetLabelPopulation
void SetLabelPopulation(LabelPopulationType const &labelPopulation)
Definition: otbLabelImageSmallRegionMergingFilter.hxx:37
otb::PersistentLabelImageSmallRegionMergingFilter::GetLUT
LUTType const & GetLUT() const
Definition: otbLabelImageSmallRegionMergingFilter.hxx:71