22 #ifndef otbStatisticsAttributesLabelMapFilter_hxx
23 #define otbStatisticsAttributesLabelMapFilter_hxx
27 #include "vnl/algo/vnl_real_eigensystem.h"
28 #include "vnl/algo/vnl_symmetric_eigensystem.h"
35 template <
class TLabelObject,
class TFeatureImage>
37 : m_FeatureName(
"Default"), m_FeatureImage(), m_ReducedAttributeSet(true)
42 template <
class TLabelObject,
class TFeatureImage>
48 template <
class TLabelObject,
class TFeatureImage>
54 resp = resp && (m_FeatureName !=
self.m_FeatureName);
55 resp = resp && (m_FeatureImage !=
self.m_FeatureImage);
61 template <
class TLabelObject,
class TFeatureImage>
65 return !(
this !=
self);
71 template <
class TLabelObject,
class TFeatureImage>
78 std::ostringstream oss;
80 FeatureType min = itk::NumericTraits<FeatureType>::max();
81 FeatureType max = itk::NumericTraits<FeatureType>::NonpositiveMin();
86 unsigned int totalFreq = 0;
87 typename TFeatureImage::IndexType minIdx;
89 typename TFeatureImage::IndexType maxIdx;
91 typename TFeatureImage::PointType centerOfGravity;
92 centerOfGravity.Fill(0);
94 centralMoments.Fill(0);
96 principalAxes.Fill(0);
98 principalMoments.Fill(0);
101 while (!lit.IsAtEnd())
103 const typename TFeatureImage::IndexType& firstIdx = lit.GetLine().GetIndex();
104 unsigned long length = lit.GetLine().GetLength();
106 long endIdx0 = firstIdx[0] + length;
107 for (
typename TFeatureImage::IndexType idx = firstIdx; idx[0] < endIdx0; idx[0]++)
109 const FeatureType& v = m_FeatureImage->GetPixel(idx);
125 const double v2 = v * v;
132 if (!m_ReducedAttributeSet)
135 typename TFeatureImage::PointType physicalPosition;
136 m_FeatureImage->TransformIndexToPhysicalPoint(idx, physicalPosition);
137 for (
unsigned int i = 0; i < TFeatureImage::ImageDimension; ++i)
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)
143 const double weight = v * physicalPosition[i] * physicalPosition[j];
144 centralMoments[i][j] += weight;
145 centralMoments[j][i] += weight;
154 const double mean = sum / totalFreq;
155 const double variance = (sum2 - (sum * sum / totalFreq)) / (totalFreq - 1);
156 const double sigma = std::sqrt(variance);
161 const double epsilon = 1E-10;
162 if (std::abs(variance) > epsilon)
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;
169 oss <<
"STATS::" << m_FeatureName <<
"::Mean";
170 lo->SetAttribute(oss.str().c_str(),
mean);
173 oss <<
"STATS::" << m_FeatureName <<
"::Variance";
174 lo->SetAttribute(oss.str().c_str(), variance);
177 oss <<
"STATS::" << m_FeatureName <<
"::Skewness";
178 lo->SetAttribute(oss.str().c_str(), skewness);
181 oss <<
"STATS::" << m_FeatureName <<
"::Kurtosis";
182 lo->SetAttribute(oss.str().c_str(), kurtosis);
184 if (!m_ReducedAttributeSet)
186 double elongation = std::numeric_limits<double>::quiet_NaN();
190 for (
unsigned int i = 0; i < TFeatureImage::ImageDimension; ++i)
192 centerOfGravity[i] /= sum;
193 for (
unsigned int j = 0; j < TFeatureImage::ImageDimension; ++j)
195 centralMoments[i][j] /= sum;
200 for (
unsigned int i = 0; i < TFeatureImage::ImageDimension; ++i)
202 for (
unsigned int j = 0; j < TFeatureImage::ImageDimension; ++j)
204 centralMoments[i][j] -= centerOfGravity[i] * centerOfGravity[j];
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)
214 principalMoments[i] = pm(i, i);
216 principalAxes = eigen.V.transpose();
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);
224 for (
unsigned int i = 0; i < TFeatureImage::ImageDimension; ++i)
226 det *= eigenval(i, i);
229 for (
unsigned int i = 0; i < TFeatureImage::ImageDimension; ++i)
231 principalAxes[TFeatureImage::ImageDimension - 1][i] *= std::real(det);
234 if (principalMoments[0] != 0)
237 elongation = std::sqrt(principalMoments[TFeatureImage::ImageDimension - 1] / principalMoments[0]);
244 for (
unsigned int i = 0; i < TFeatureImage::ImageDimension; ++i)
246 centerOfGravity[i] = 0;
247 principalMoments[i] = 0;
248 for (
unsigned int j = 0; j < TFeatureImage::ImageDimension; ++j)
250 principalAxes[i][j] = 0;
257 oss <<
"STATS::" << m_FeatureName <<
"::Elongation";
258 lo->SetAttribute(oss.str().c_str(), (
double)elongation);
261 oss <<
"STATS::" << m_FeatureName <<
"::Minimum";
262 lo->SetAttribute(oss.str().c_str(), (
double)min);
265 oss <<
"STATS::" << m_FeatureName <<
"::Maximum";
266 lo->SetAttribute(oss.str().c_str(), (
double)max);
269 oss <<
"STATS::" << m_FeatureName <<
"::Sum";
270 lo->SetAttribute(oss.str().c_str(), sum);
273 oss <<
"STATS::" << m_FeatureName <<
"::Sigma";
274 lo->SetAttribute(oss.str().c_str(), sigma);
276 for (
unsigned int dim = 0; dim < TFeatureImage::ImageDimension; ++dim)
279 oss <<
"STATS::" << m_FeatureName <<
"::CenterOfGravity" << dim;
280 lo->SetAttribute(oss.str().c_str(), centerOfGravity[dim]);
283 oss <<
"STATS::" << m_FeatureName <<
"::PrincipalMoments" << dim;
284 lo->SetAttribute(oss.str().c_str(), principalMoments[dim]);
287 oss <<
"STATS::" << m_FeatureName <<
"::FirstMinimumIndex" << dim;
288 lo->SetAttribute(oss.str().c_str(), minIdx[dim]);
291 oss <<
"STATS::" << m_FeatureName <<
"::FirstMaximumIndex" << dim;
292 lo->SetAttribute(oss.str().c_str(), maxIdx[dim]);
294 for (
unsigned int dim2 = 0; dim2 < TFeatureImage::ImageDimension; ++dim2)
297 oss <<
"STATS::" << m_FeatureName <<
"::PrincipalAxis" << dim << dim2;
298 lo->SetAttribute(oss.str().c_str(), principalAxes(dim, dim2));
306 template <
class TLabelObject,
class TFeatureImage>
309 m_FeatureName = name;
313 template <
class TLabelObject,
class TFeatureImage>
316 return m_FeatureName;
320 template <
class TLabelObject,
class TFeatureImage>
323 m_FeatureImage = img;
327 template <
class TLabelObject,
class TFeatureImage>
330 return m_FeatureImage;
334 template <
class TLabelObject,
class TFeatureImage>
337 m_ReducedAttributeSet = flag;
341 template <
class TLabelObject,
class TFeatureImage>
344 return m_ReducedAttributeSet;
349 template <
class TImage,
class TFeatureImage>
354 template <
class TImage,
class TFeatureImage>
360 template <
class TImage,
class TFeatureImage>
364 this->SetNthInput(1,
const_cast<TFeatureImage*
>(input));
368 template <
class TImage,
class TFeatureImage>
372 return static_cast<const TFeatureImage*
>(this->itk::ProcessObject::GetInput(1));
376 template <
class TImage,
class TFeatureImage>
379 this->SetInput(input);
383 template <
class TImage,
class TFeatureImage>
386 return this->GetInput();
390 template <
class TImage,
class TFeatureImage>
393 this->SetFeatureImage(input);
397 template <
class TImage,
class TFeatureImage>
400 return this->GetFeatureImage();
404 template <
class TImage,
class TFeatureImage>
408 if (name != this->GetFunctor().GetFeatureName())
416 template <
class TImage,
class TFeatureImage>
424 template <
class TImage,
class TFeatureImage>
428 if (this->GetFunctor().GetReducedAttributeSet() != flag)
436 template <
class TImage,
class TFeatureImage>
443 template <
class TImage,
class TFeatureImage>
447 Superclass::BeforeThreadedGenerateData();
450 this->GetFunctor().SetFeatureImage(this->GetFeatureImage());
453 template <
class TImage,
class TFeatureImage>
456 Superclass::PrintSelf(os, indent);