OTB  9.0.0
Orfeo Toolbox
otbStatisticsAttributesLabelMapFilter.hxx
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1999-2011 Insight Software Consortium
3  * Copyright (C) 2005-2022 Centre National d'Etudes Spatiales (CNES)
4  *
5  * This file is part of Orfeo Toolbox
6  *
7  * https://www.orfeo-toolbox.org/
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21 
22 #ifndef otbStatisticsAttributesLabelMapFilter_hxx
23 #define otbStatisticsAttributesLabelMapFilter_hxx
24 
26 
27 #include "vnl/algo/vnl_real_eigensystem.h"
28 #include "vnl/algo/vnl_symmetric_eigensystem.h"
29 
30 namespace otb
31 {
32 namespace Functor
33 {
35 template <class TLabelObject, class TFeatureImage>
37  : m_FeatureName("Default"), m_FeatureImage(), m_ReducedAttributeSet(true)
38 {
39 }
40 
42 template <class TLabelObject, class TFeatureImage>
44 {
45 }
46 
48 template <class TLabelObject, class TFeatureImage>
50 {
51  // Initialize response
52  bool resp = true;
53 
54  resp = resp && (m_FeatureName != self.m_FeatureName);
55  resp = resp && (m_FeatureImage != self.m_FeatureImage);
56 
57  // Return
58  return resp;
59 }
60 
61 template <class TLabelObject, class TFeatureImage>
63 {
64  // Call the != implementation
65  return !(this != self);
66 }
67 
71 template <class TLabelObject, class TFeatureImage>
73 {
75  lit.GoToBegin();
77 
78  std::ostringstream oss;
79 
80  FeatureType min = itk::NumericTraits<FeatureType>::max();
81  FeatureType max = itk::NumericTraits<FeatureType>::NonpositiveMin();
82  double sum = 0;
83  double sum2 = 0;
84  double sum3 = 0;
85  double sum4 = 0;
86  unsigned int totalFreq = 0;
87  typename TFeatureImage::IndexType minIdx;
88  minIdx.Fill(0);
89  typename TFeatureImage::IndexType maxIdx;
90  maxIdx.Fill(0);
91  typename TFeatureImage::PointType centerOfGravity;
92  centerOfGravity.Fill(0);
93  MatrixType centralMoments;
94  centralMoments.Fill(0);
95  MatrixType principalAxes;
96  principalAxes.Fill(0);
97  VectorType principalMoments;
98  principalMoments.Fill(0);
99 
100  // iterate over all the lines
101  while (!lit.IsAtEnd())
102  {
103  const typename TFeatureImage::IndexType& firstIdx = lit.GetLine().GetIndex();
104  unsigned long length = lit.GetLine().GetLength();
105 
106  long endIdx0 = firstIdx[0] + length;
107  for (typename TFeatureImage::IndexType idx = firstIdx; idx[0] < endIdx0; idx[0]++)
108  {
109  const FeatureType& v = m_FeatureImage->GetPixel(idx);
110  ++totalFreq;
111 
112  // update min and max
113  if (v <= min)
114  {
115  min = v;
116  minIdx = idx;
117  }
118  if (v >= max)
119  {
120  max = v;
121  maxIdx = idx;
122  }
123 
124  // increase the sums
125  const double v2 = v * v;
126 
127  sum += v;
128  sum2 += v2;
129  sum3 += v2 * v;
130  sum4 += v2 * v2;
131 
132  if (!m_ReducedAttributeSet)
133  {
134  // moments
135  typename TFeatureImage::PointType physicalPosition;
136  m_FeatureImage->TransformIndexToPhysicalPoint(idx, physicalPosition);
137  for (unsigned int i = 0; i < TFeatureImage::ImageDimension; ++i)
138  {
139  centerOfGravity[i] += physicalPosition[i] * v;
140  centralMoments[i][i] += v * physicalPosition[i] * physicalPosition[i];
141  for (unsigned int j = i + 1; j < TFeatureImage::ImageDimension; ++j)
142  {
143  const double weight = v * physicalPosition[i] * physicalPosition[j];
144  centralMoments[i][j] += weight;
145  centralMoments[j][i] += weight;
146  }
147  }
148  }
149  }
150  ++lit;
151  }
152 
153  // final computations
154  const double mean = sum / totalFreq;
155  const double variance = (sum2 - (sum * sum / totalFreq)) / (totalFreq - 1);
156  const double sigma = std::sqrt(variance);
157  const double mean2 = mean * mean;
158  double skewness = 0;
159  double kurtosis = 0;
160 
161  const double epsilon = 1E-10;
162  if (std::abs(variance) > epsilon)
163  {
164  skewness = ((sum3 - 3.0 * mean * sum2) / totalFreq + 2.0 * mean * mean2) / (variance * sigma);
165  kurtosis = ((sum4 - 4.0 * mean * sum3 + 6.0 * mean2 * sum2) / totalFreq - 3.0 * mean2 * mean2) / (variance * variance) - 3.0;
166  }
167 
168  oss.str("");
169  oss << "STATS::" << m_FeatureName << "::Mean";
170  lo->SetAttribute(oss.str().c_str(), mean);
171 
172  oss.str("");
173  oss << "STATS::" << m_FeatureName << "::Variance";
174  lo->SetAttribute(oss.str().c_str(), variance);
175 
176  oss.str("");
177  oss << "STATS::" << m_FeatureName << "::Skewness";
178  lo->SetAttribute(oss.str().c_str(), skewness);
179 
180  oss.str("");
181  oss << "STATS::" << m_FeatureName << "::Kurtosis";
182  lo->SetAttribute(oss.str().c_str(), kurtosis);
183 
184  if (!m_ReducedAttributeSet)
185  {
186  double elongation = std::numeric_limits<double>::quiet_NaN();
187  if (sum != 0)
188  {
189  // Normalize using the total mass
190  for (unsigned int i = 0; i < TFeatureImage::ImageDimension; ++i)
191  {
192  centerOfGravity[i] /= sum;
193  for (unsigned int j = 0; j < TFeatureImage::ImageDimension; ++j)
194  {
195  centralMoments[i][j] /= sum;
196  }
197  }
198 
199  // Center the second order moments
200  for (unsigned int i = 0; i < TFeatureImage::ImageDimension; ++i)
201  {
202  for (unsigned int j = 0; j < TFeatureImage::ImageDimension; ++j)
203  {
204  centralMoments[i][j] -= centerOfGravity[i] * centerOfGravity[j];
205  }
206  }
207 
208  // Compute principal moments and axes
209  vnl_symmetric_eigensystem<double> eigen(centralMoments.GetVnlMatrix());
210  vnl_diag_matrix<double> pm = eigen.D;
211  for (unsigned int i = 0; i < TFeatureImage::ImageDimension; ++i)
212  {
213  // principalMoments[i] = 4 * std::sqrt( pm(i, i) );
214  principalMoments[i] = pm(i, i);
215  }
216  principalAxes = eigen.V.transpose();
217 
218  // Add a final reflection if needed for a proper rotation,
219  // by multiplying the last row by the determinant
220  vnl_real_eigensystem eigenrot(principalAxes.GetVnlMatrix());
221  vnl_diag_matrix<std::complex<double>> eigenval = eigenrot.D;
222  std::complex<double> det(1.0, 0.0);
223 
224  for (unsigned int i = 0; i < TFeatureImage::ImageDimension; ++i)
225  {
226  det *= eigenval(i, i);
227  }
228 
229  for (unsigned int i = 0; i < TFeatureImage::ImageDimension; ++i)
230  {
231  principalAxes[TFeatureImage::ImageDimension - 1][i] *= std::real(det);
232  }
233 
234  if (principalMoments[0] != 0)
235  {
236  // elongation = principalMoments[TFeatureImage::ImageDimension-1] / principalMoments[0];
237  elongation = std::sqrt(principalMoments[TFeatureImage::ImageDimension - 1] / principalMoments[0]);
238  }
239  }
240  else
241  {
242  // can't compute anything in that case - just set everything to a default value
243  // Normalize using the total mass
244  for (unsigned int i = 0; i < TFeatureImage::ImageDimension; ++i)
245  {
246  centerOfGravity[i] = 0;
247  principalMoments[i] = 0;
248  for (unsigned int j = 0; j < TFeatureImage::ImageDimension; ++j)
249  {
250  principalAxes[i][j] = 0;
251  }
252  }
253  }
254 
255 
256  oss.str("");
257  oss << "STATS::" << m_FeatureName << "::Elongation";
258  lo->SetAttribute(oss.str().c_str(), (double)elongation);
259 
260  oss.str("");
261  oss << "STATS::" << m_FeatureName << "::Minimum";
262  lo->SetAttribute(oss.str().c_str(), (double)min);
263 
264  oss.str("");
265  oss << "STATS::" << m_FeatureName << "::Maximum";
266  lo->SetAttribute(oss.str().c_str(), (double)max);
267 
268  oss.str("");
269  oss << "STATS::" << m_FeatureName << "::Sum";
270  lo->SetAttribute(oss.str().c_str(), sum);
271 
272  oss.str("");
273  oss << "STATS::" << m_FeatureName << "::Sigma";
274  lo->SetAttribute(oss.str().c_str(), sigma);
275 
276  for (unsigned int dim = 0; dim < TFeatureImage::ImageDimension; ++dim)
277  {
278  oss.str("");
279  oss << "STATS::" << m_FeatureName << "::CenterOfGravity" << dim;
280  lo->SetAttribute(oss.str().c_str(), centerOfGravity[dim]);
281 
282  oss.str("");
283  oss << "STATS::" << m_FeatureName << "::PrincipalMoments" << dim;
284  lo->SetAttribute(oss.str().c_str(), principalMoments[dim]);
285 
286  oss.str("");
287  oss << "STATS::" << m_FeatureName << "::FirstMinimumIndex" << dim;
288  lo->SetAttribute(oss.str().c_str(), minIdx[dim]);
289 
290  oss.str("");
291  oss << "STATS::" << m_FeatureName << "::FirstMaximumIndex" << dim;
292  lo->SetAttribute(oss.str().c_str(), maxIdx[dim]);
293 
294  for (unsigned int dim2 = 0; dim2 < TFeatureImage::ImageDimension; ++dim2)
295  {
296  oss.str("");
297  oss << "STATS::" << m_FeatureName << "::PrincipalAxis" << dim << dim2;
298  lo->SetAttribute(oss.str().c_str(), principalAxes(dim, dim2));
299  }
300  }
301  }
302 }
303 
304 
306 template <class TLabelObject, class TFeatureImage>
308 {
309  m_FeatureName = name;
310 }
311 
313 template <class TLabelObject, class TFeatureImage>
315 {
316  return m_FeatureName;
317 }
318 
320 template <class TLabelObject, class TFeatureImage>
322 {
323  m_FeatureImage = img;
324 }
325 
327 template <class TLabelObject, class TFeatureImage>
329 {
330  return m_FeatureImage;
331 }
332 
334 template <class TLabelObject, class TFeatureImage>
336 {
337  m_ReducedAttributeSet = flag;
338 }
339 
341 template <class TLabelObject, class TFeatureImage>
343 {
344  return m_ReducedAttributeSet;
345 }
346 
347 } // End namespace Functor
348 
349 template <class TImage, class TFeatureImage>
351 {
352 }
353 
354 template <class TImage, class TFeatureImage>
356 {
357 }
358 
360 template <class TImage, class TFeatureImage>
362 {
363  // Set the Nth input
364  this->SetNthInput(1, const_cast<TFeatureImage*>(input));
365 }
366 
368 template <class TImage, class TFeatureImage>
371 {
372  return static_cast<const TFeatureImage*>(this->itk::ProcessObject::GetInput(1));
373 }
374 
376 template <class TImage, class TFeatureImage>
378 {
379  this->SetInput(input);
380 }
381 
383 template <class TImage, class TFeatureImage>
385 {
386  return this->GetInput();
387 }
388 
390 template <class TImage, class TFeatureImage>
392 {
393  this->SetFeatureImage(input);
394 }
395 
397 template <class TImage, class TFeatureImage>
399 {
400  return this->GetFeatureImage();
401 }
402 
404 template <class TImage, class TFeatureImage>
405 
407 {
408  if (name != this->GetFunctor().GetFeatureName())
409  {
410  this->GetFunctor().SetFeatureName(name);
411  this->Modified();
412  }
413 }
414 
416 template <class TImage, class TFeatureImage>
417 
419 {
420  return this->GetFunctor().GetFeatureName();
421 }
422 
424 template <class TImage, class TFeatureImage>
425 
427 {
428  if (this->GetFunctor().GetReducedAttributeSet() != flag)
429  {
430  this->GetFunctor().SetReducedAttributeSet(flag);
431  this->Modified();
432  }
433 }
434 
436 template <class TImage, class TFeatureImage>
437 
439 {
440  return this->GetFunctor().GetReducedAttributeSet();
441 }
442 
443 template <class TImage, class TFeatureImage>
445 {
446  // First call superclass implementation
447  Superclass::BeforeThreadedGenerateData();
448 
449  // Set the feature image to the functor
450  this->GetFunctor().SetFeatureImage(this->GetFeatureImage());
451 }
452 
453 template <class TImage, class TFeatureImage>
454 void StatisticsAttributesLabelMapFilter<TImage, TFeatureImage>::PrintSelf(std::ostream& os, itk::Indent indent) const
455 {
456  Superclass::PrintSelf(os, indent);
457 }
458 
459 } // end namespace itk
460 #endif
otb::mean
Definition: otbParserXPlugins.h:261
otb::StatisticsAttributesLabelMapFilter::GetReducedAttributeSet
bool GetReducedAttributeSet() const
Definition: otbStatisticsAttributesLabelMapFilter.hxx:438
otb::StatisticsAttributesLabelMapFilter::SetFeatureName
void SetFeatureName(const std::string &name)
Definition: otbStatisticsAttributesLabelMapFilter.hxx:406
otb
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.
Definition: otbJoinContainer.h:32
otb::Functor::StatisticsAttributesLabelObjectFunctor< TImage::LabelObjectType, TFeatureImage >::LabelObjectType
TImage::LabelObjectType LabelObjectType
Typedef of the label object.
Definition: otbStatisticsAttributesLabelMapFilter.h:57
otbStatisticsAttributesLabelMapFilter.h
otb::Functor::StatisticsAttributesLabelObjectFunctor< TImage::LabelObjectType, TFeatureImage >::FeatureType
TFeatureImage::PixelType FeatureType
Typedef of the feature image type.
Definition: otbStatisticsAttributesLabelMapFilter.h:54
otb::operator==
constexpr bool operator==(extents< StaticExtentsL... > const &lhs, extents< StaticExtentsR... > const &rhs)
Definition: otbExtents.h:150
otb::StatisticsAttributesLabelMapFilter::GetFeatureName
const std::string & GetFeatureName() const
Definition: otbStatisticsAttributesLabelMapFilter.hxx:418
otb::Functor::StatisticsAttributesLabelObjectFunctor::StatisticsAttributesLabelObjectFunctor
StatisticsAttributesLabelObjectFunctor()
Definition: otbStatisticsAttributesLabelMapFilter.hxx:36
otb::StatisticsAttributesLabelMapFilter::FeatureImageType
TFeatureImage FeatureImageType
Definition: otbStatisticsAttributesLabelMapFilter.h:136
otb::StatisticsAttributesLabelMapFilter::SetReducedAttributeSet
void SetReducedAttributeSet(bool flag)
Definition: otbStatisticsAttributesLabelMapFilter.hxx:426
otb::Functor::StatisticsAttributesLabelObjectFunctor< TImage::LabelObjectType, TFeatureImage >::VectorType
itk::Vector< double, TFeatureImage::ImageDimension > VectorType
Definition: otbStatisticsAttributesLabelMapFilter.h:51
otb::operator!=
constexpr bool operator!=(extents< StaticExtentsL... > const &lhs, extents< StaticExtentsR... > const &rhs)
Definition: otbExtents.h:164
otb::Functor::StatisticsAttributesLabelObjectFunctor< TImage::LabelObjectType, TFeatureImage >::ConstLineIteratorType
LabelObjectType::ConstLineIterator ConstLineIteratorType
Definition: otbStatisticsAttributesLabelMapFilter.h:60
otb::StatisticsAttributesLabelMapFilter
This class is a fork of itk::StasticsLabelMapFilter to support AttributesMapLabelObject.
Definition: otbStatisticsAttributesLabelMapFilter.h:128
otb::Functor::StatisticsAttributesLabelObjectFunctor< TImage::LabelObjectType, TFeatureImage >::MatrixType
itk::Matrix< double, TFeatureImage::ImageDimension, TFeatureImage::ImageDimension > MatrixType
Definition: otbStatisticsAttributesLabelMapFilter.h:49
otb::Functor::StatisticsAttributesLabelObjectFunctor
Functor to compute statistics attributes of one LabelObject.
Definition: otbStatisticsAttributesLabelMapFilter.h:42