21 #ifndef otbStreamingStatisticsVectorImageFilter_hxx
22 #define otbStreamingStatisticsVectorImageFilter_hxx
25 #include "itkImageRegionIterator.h"
26 #include "itkImageRegionConstIteratorWithIndex.h"
27 #include "itkProgressReporter.h"
33 template <
class TInputImage,
class TPrecision>
35 : m_EnableMinMax(true),
36 m_EnableFirstOrderStats(true),
37 m_EnableSecondOrderStats(true),
38 m_UseUnbiasedEstimator(true),
39 m_IgnoreInfiniteValues(true),
40 m_IgnoreUserDefinedValue(false),
48 for (
unsigned int i = 1; i < 11; ++i)
50 this->itk::ProcessObject::SetNthOutput(i, this->
MakeOutput(i).GetPointer());
57 template <
class TInputImage,
class TPrecision>
63 return static_cast<itk::DataObject*
>(TInputImage::New().GetPointer());
68 return static_cast<itk::DataObject*
>(PixelObjectType::New().GetPointer());
73 return static_cast<itk::DataObject*
>(RealPixelObjectType::New().GetPointer());
78 return static_cast<itk::DataObject*
>(MatrixObjectType::New().GetPointer());
84 return static_cast<itk::DataObject*
>(RealObjectType::New().GetPointer());
88 return static_cast<itk::DataObject*
>(CountObjectType::New().GetPointer());
91 return static_cast<itk::DataObject*
>(TInputImage::New().GetPointer());
96 template <
class TInputImage,
class TPrecision>
100 return static_cast<CountObjectType*
>(this->itk::ProcessObject::GetOutput(10));
103 template <
class TInputImage,
class TPrecision>
107 return static_cast<const CountObjectType*
>(this->itk::ProcessObject::GetOutput(10));
111 template <
class TInputImage,
class TPrecision>
115 return static_cast<PixelObjectType*
>(this->itk::ProcessObject::GetOutput(1));
118 template <
class TInputImage,
class TPrecision>
122 return static_cast<const PixelObjectType*
>(this->itk::ProcessObject::GetOutput(1));
125 template <
class TInputImage,
class TPrecision>
129 return static_cast<PixelObjectType*
>(this->itk::ProcessObject::GetOutput(2));
132 template <
class TInputImage,
class TPrecision>
136 return static_cast<const PixelObjectType*
>(this->itk::ProcessObject::GetOutput(2));
139 template <
class TInputImage,
class TPrecision>
143 return static_cast<RealObjectType*
>(this->itk::ProcessObject::GetOutput(7));
146 template <
class TInputImage,
class TPrecision>
150 return static_cast<const RealObjectType*
>(this->itk::ProcessObject::GetOutput(7));
153 template <
class TInputImage,
class TPrecision>
157 return static_cast<RealObjectType*
>(this->itk::ProcessObject::GetOutput(8));
160 template <
class TInputImage,
class TPrecision>
164 return static_cast<const RealObjectType*
>(this->itk::ProcessObject::GetOutput(8));
168 template <
class TInputImage,
class TPrecision>
172 return static_cast<RealObjectType*
>(this->itk::ProcessObject::GetOutput(9));
175 template <
class TInputImage,
class TPrecision>
179 return static_cast<const RealObjectType*
>(this->itk::ProcessObject::GetOutput(9));
182 template <
class TInputImage,
class TPrecision>
189 template <
class TInputImage,
class TPrecision>
193 return static_cast<const RealPixelObjectType*
>(this->itk::ProcessObject::GetOutput(3));
196 template <
class TInputImage,
class TPrecision>
203 template <
class TInputImage,
class TPrecision>
207 return static_cast<const RealPixelObjectType*
>(this->itk::ProcessObject::GetOutput(4));
210 template <
class TInputImage,
class TPrecision>
214 return static_cast<MatrixObjectType*
>(this->itk::ProcessObject::GetOutput(5));
217 template <
class TInputImage,
class TPrecision>
221 return static_cast<const MatrixObjectType*
>(this->itk::ProcessObject::GetOutput(5));
224 template <
class TInputImage,
class TPrecision>
228 return static_cast<MatrixObjectType*
>(this->itk::ProcessObject::GetOutput(6));
231 template <
class TInputImage,
class TPrecision>
235 return static_cast<const MatrixObjectType*
>(this->itk::ProcessObject::GetOutput(6));
238 template <
class TInputImage,
class TPrecision>
241 Superclass::GenerateOutputInformation();
242 if (this->GetInput())
244 this->GetOutput()->CopyInformation(this->GetInput());
245 this->GetOutput()->SetLargestPossibleRegion(this->GetInput()->GetLargestPossibleRegion());
247 if (this->GetOutput()->GetRequestedRegion().GetNumberOfPixels() == 0)
249 this->GetOutput()->SetRequestedRegion(this->GetOutput()->GetLargestPossibleRegion());
254 template <
class TInputImage,
class TPrecision>
264 template <
class TInputImage,
class TPrecision>
267 TInputImage* inputPtr =
const_cast<TInputImage*
>(this->GetInput());
268 inputPtr->UpdateOutputInformation();
270 unsigned int numberOfThreads = this->GetNumberOfThreads();
271 unsigned int numberOfComponent = inputPtr->GetNumberOfComponentsPerPixel();
276 tempPixel.SetSize(numberOfComponent);
278 tempPixel.Fill(itk::NumericTraits<InternalPixelType>::max());
279 this->GetMinimumOutput()->Set(tempPixel);
281 tempPixel.Fill(itk::NumericTraits<InternalPixelType>::NonpositiveMin());
282 this->GetMaximumOutput()->Set(tempPixel);
285 tempTemporariesPixel.SetSize(numberOfComponent);
286 tempTemporariesPixel.Fill(itk::NumericTraits<InternalPixelType>::max());
287 m_ThreadMin = std::vector<PixelType>(numberOfThreads, tempTemporariesPixel);
289 tempTemporariesPixel.Fill(itk::NumericTraits<InternalPixelType>::NonpositiveMin());
290 m_ThreadMax = std::vector<PixelType>(numberOfThreads, tempTemporariesPixel);
293 if (m_EnableSecondOrderStats)
295 m_EnableFirstOrderStats =
true;
298 if (m_EnableFirstOrderStats)
301 zeroRealPixel.SetSize(numberOfComponent);
302 zeroRealPixel.Fill(itk::NumericTraits<PrecisionType>::ZeroValue());
303 this->GetMeanOutput()->Set(zeroRealPixel);
304 this->GetSumOutput()->Set(zeroRealPixel);
305 m_ThreadFirstOrderAccumulators.resize(numberOfThreads);
306 std::fill(m_ThreadFirstOrderAccumulators.begin(), m_ThreadFirstOrderAccumulators.end(), zeroRealPixel);
308 RealType zeroReal = itk::NumericTraits<RealType>::ZeroValue();
309 m_ThreadFirstOrderComponentAccumulators.resize(numberOfThreads);
310 std::fill(m_ThreadFirstOrderComponentAccumulators.begin(), m_ThreadFirstOrderComponentAccumulators.end(), zeroReal);
313 if (m_EnableSecondOrderStats)
316 zeroMatrix.SetSize(numberOfComponent, numberOfComponent);
317 zeroMatrix.Fill(itk::NumericTraits<PrecisionType>::Zero);
318 this->GetCovarianceOutput()->Set(zeroMatrix);
319 this->GetCorrelationOutput()->Set(zeroMatrix);
321 m_ThreadSecondOrderAccumulators.resize(numberOfThreads);
322 std::fill(m_ThreadSecondOrderAccumulators.begin(), m_ThreadSecondOrderAccumulators.end(), zeroMatrix);
324 RealType zeroReal = itk::NumericTraits<RealType>::ZeroValue();
325 m_ThreadSecondOrderComponentAccumulators.resize(numberOfThreads);
326 std::fill(m_ThreadSecondOrderComponentAccumulators.begin(), m_ThreadSecondOrderComponentAccumulators.end(), zeroReal);
329 if (m_IgnoreInfiniteValues)
331 m_IgnoredInfinitePixelCount = std::vector<unsigned int>(numberOfThreads, 0);
334 if (m_IgnoreUserDefinedValue)
336 m_IgnoredUserPixelCount = std::vector<unsigned int>(this->GetNumberOfThreads(), 0);
340 template <
class TInputImage,
class TPrecision>
343 TInputImage* inputPtr =
const_cast<TInputImage*
>(this->GetInput());
344 const unsigned int nbPixels = inputPtr->GetLargestPossibleRegion().GetNumberOfPixels();
345 const unsigned int numberOfComponent = inputPtr->GetNumberOfComponentsPerPixel();
348 minimum.SetSize(numberOfComponent);
349 minimum.Fill(itk::NumericTraits<InternalPixelType>::max());
351 maximum.SetSize(numberOfComponent);
352 maximum.Fill(itk::NumericTraits<InternalPixelType>::NonpositiveMin());
354 RealPixelType streamFirstOrderAccumulator(numberOfComponent);
355 streamFirstOrderAccumulator.Fill(itk::NumericTraits<PrecisionType>::Zero);
356 MatrixType streamSecondOrderAccumulator(numberOfComponent, numberOfComponent);
357 streamSecondOrderAccumulator.Fill(itk::NumericTraits<PrecisionType>::Zero);
359 RealType streamFirstOrderComponentAccumulator = itk::NumericTraits<RealType>::Zero;
360 RealType streamSecondOrderComponentAccumulator = itk::NumericTraits<RealType>::Zero;
362 unsigned int ignoredInfinitePixelCount = 0;
363 unsigned int ignoredUserPixelCount = 0;
366 const itk::ThreadIdType numberOfThreads = this->GetNumberOfThreads();
367 for (itk::ThreadIdType threadId = 0; threadId < numberOfThreads; ++threadId)
371 const PixelType& threadMin = m_ThreadMin[threadId];
372 const PixelType& threadMax = m_ThreadMax[threadId];
374 for (
unsigned int j = 0; j < numberOfComponent; ++j)
376 if (threadMin[j] < minimum[j])
378 minimum[j] = threadMin[j];
380 if (threadMax[j] > maximum[j])
382 maximum[j] = threadMax[j];
387 if (m_EnableFirstOrderStats)
389 streamFirstOrderAccumulator += m_ThreadFirstOrderAccumulators[threadId];
390 streamFirstOrderComponentAccumulator += m_ThreadFirstOrderComponentAccumulators[threadId];
393 if (m_EnableSecondOrderStats)
395 streamSecondOrderAccumulator += m_ThreadSecondOrderAccumulators[threadId];
396 streamSecondOrderComponentAccumulator += m_ThreadSecondOrderComponentAccumulators[threadId];
399 ignoredInfinitePixelCount += m_IgnoredInfinitePixelCount[threadId];
401 ignoredUserPixelCount += m_IgnoredUserPixelCount[threadId];
405 assert(nbPixels >= ignoredInfinitePixelCount + ignoredUserPixelCount);
406 if (nbPixels < ignoredInfinitePixelCount + ignoredUserPixelCount)
408 itkExceptionMacro(
"nbPixels < ignoredInfinitePixelCount + ignoredUserPixelCount");
411 unsigned int nbRelevantPixel = nbPixels - (ignoredInfinitePixelCount + ignoredUserPixelCount);
413 CountType nbRelevantPixels(numberOfComponent);
414 nbRelevantPixels.Fill(nbRelevantPixel);
416 this->GetNbRelevantPixelsOutput()->Set(nbRelevantPixels);
418 if (nbRelevantPixel == 0)
420 itkExceptionMacro(
"Statistics cannot be calculated with zero relevant pixels.");
426 this->GetMinimumOutput()->Set(minimum);
427 this->GetMaximumOutput()->Set(maximum);
430 if (m_EnableFirstOrderStats)
432 this->GetComponentMeanOutput()->Set(streamFirstOrderComponentAccumulator / (nbRelevantPixel * numberOfComponent));
434 this->GetMeanOutput()->Set(streamFirstOrderAccumulator / nbRelevantPixel);
435 this->GetSumOutput()->Set(streamFirstOrderAccumulator);
438 if (m_EnableSecondOrderStats)
440 MatrixType cor = streamSecondOrderAccumulator / nbRelevantPixel;
441 this->GetCorrelationOutput()->Set(cor);
446 double regulComponent = 1.0;
448 if (m_UseUnbiasedEstimator && nbRelevantPixel > 1)
450 regul =
static_cast<double>(nbRelevantPixel) / (
static_cast<double>(nbRelevantPixel) - 1.0);
453 if (m_UseUnbiasedEstimator && (nbRelevantPixel * numberOfComponent) > 1)
455 regulComponent =
static_cast<double>(nbRelevantPixel * numberOfComponent) / (
static_cast<double>(nbRelevantPixel * numberOfComponent) - 1.0);
459 for (
unsigned int r = 0; r < numberOfComponent; ++r)
461 for (
unsigned int c = 0; c < numberOfComponent; ++c)
463 cov(r, c) = regul * (cov(r, c) -
mean[r] *
mean[c]);
466 this->GetCovarianceOutput()->Set(cov);
468 this->GetComponentMeanOutput()->Set(streamFirstOrderComponentAccumulator / (nbRelevantPixel * numberOfComponent));
469 this->GetComponentCorrelationOutput()->Set(streamSecondOrderComponentAccumulator / (nbRelevantPixel * numberOfComponent));
470 this->GetComponentCovarianceOutput()->Set(regulComponent * (this->GetComponentCorrelation() - (this->GetComponentMean() * this->GetComponentMean())));
474 template <
class TInputImage,
class TPrecision>
476 itk::ThreadIdType threadId)
479 itk::ProgressReporter progress(
this, threadId, outputRegionForThread.GetNumberOfPixels());
483 PixelType& threadMin = m_ThreadMin[threadId];
484 PixelType& threadMax = m_ThreadMax[threadId];
487 itk::ImageRegionConstIteratorWithIndex<TInputImage> it(inputPtr, outputRegionForThread);
489 for (it.GoToBegin(); !it.IsAtEnd(); ++it, progress.CompletedPixel())
493 float finiteProbe = 0.;
494 bool userProbe = m_IgnoreUserDefinedValue;
495 for (
unsigned int j = 0; j < vectorValue.GetSize(); ++j)
497 finiteProbe += (float)(vectorValue[j]);
498 userProbe = userProbe && (vectorValue[j] == m_UserIgnoredValue);
501 if (m_IgnoreInfiniteValues && !(vnl_math_isfinite(finiteProbe)))
503 m_IgnoredInfinitePixelCount[threadId]++;
509 m_IgnoredUserPixelCount[threadId]++;
515 for (
unsigned int j = 0; j < vectorValue.GetSize(); ++j)
517 if (vectorValue[j] < threadMin[j])
519 threadMin[j] = vectorValue[j];
521 if (vectorValue[j] > threadMax[j])
523 threadMax[j] = vectorValue[j];
528 if (m_EnableFirstOrderStats)
530 RealPixelType& threadFirstOrder = m_ThreadFirstOrderAccumulators[threadId];
531 RealType& threadFirstOrderComponent = m_ThreadFirstOrderComponentAccumulators[threadId];
533 threadFirstOrder += vectorValue;
535 for (
unsigned int i = 0; i < vectorValue.GetSize(); ++i)
537 threadFirstOrderComponent += vectorValue[i];
541 if (m_EnableSecondOrderStats)
543 MatrixType& threadSecondOrder = m_ThreadSecondOrderAccumulators[threadId];
544 RealType& threadSecondOrderComponent = m_ThreadSecondOrderComponentAccumulators[threadId];
546 for (
unsigned int r = 0; r < threadSecondOrder.Rows(); ++r)
548 for (
unsigned int c = 0; c < threadSecondOrder.Cols(); ++c)
553 threadSecondOrderComponent += vectorValue.GetSquaredNorm();
560 template <
class TImage,
class TPrecision>
563 Superclass::PrintSelf(os, indent);
565 os << indent <<
"Min: " << this->GetMinimumOutput()->Get() << std::endl;
566 os << indent <<
"Max: " << this->GetMaximumOutput()->Get() << std::endl;
567 os << indent <<
"Mean: " << this->GetMeanOutput()->Get() << std::endl;
568 os << indent <<
"Covariance: " << this->GetCovarianceOutput()->Get() << std::endl;
569 os << indent <<
"Correlation: " << this->GetCorrelationOutput()->Get() << std::endl;
570 os << indent <<
"Relevant pixel: " << this->GetNbRelevantPixelsOutput()->Get() << std::endl;
571 os << indent <<
"Component Mean: " << this->GetComponentMeanOutput()->Get() << std::endl;
572 os << indent <<
"Component Covariance: " << this->GetComponentCovarianceOutput()->Get() << std::endl;
573 os << indent <<
"Component Correlation: " << this->GetComponentCorrelationOutput()->Get() << std::endl;
574 os << indent <<
"UseUnbiasedEstimator: " << (this->m_UseUnbiasedEstimator ?
"true" :
"false") << std::endl;