21 #ifndef otbStreamingStatisticsVectorImageFilter_hxx
22 #define otbStreamingStatisticsVectorImageFilter_hxx
25 #include "itkImageRegionIterator.h"
26 #include "itkImageRegionConstIteratorWithIndex.h"
27 #include "itkProgressReporter.h"
29 #include "vcl_legacy_aliases.h"
35 template <
class TInputImage,
class TPrecision>
37 : m_EnableMinMax(true),
38 m_EnableFirstOrderStats(true),
39 m_EnableSecondOrderStats(true),
40 m_UseUnbiasedEstimator(true),
41 m_IgnoreInfiniteValues(true),
42 m_IgnoreUserDefinedValue(false),
45 this->DynamicMultiThreadingOff();
51 for (
unsigned int i = 1; i < 11; ++i)
53 this->itk::ProcessObject::SetNthOutput(i, this->
MakeOutput(i).GetPointer());
60 template <
class TInputImage,
class TPrecision>
66 return static_cast<itk::DataObject*
>(TInputImage::New().GetPointer());
71 return static_cast<itk::DataObject*
>(PixelObjectType::New().GetPointer());
76 return static_cast<itk::DataObject*
>(RealPixelObjectType::New().GetPointer());
81 return static_cast<itk::DataObject*
>(MatrixObjectType::New().GetPointer());
87 return static_cast<itk::DataObject*
>(RealObjectType::New().GetPointer());
91 return static_cast<itk::DataObject*
>(CountObjectType::New().GetPointer());
94 return static_cast<itk::DataObject*
>(TInputImage::New().GetPointer());
99 template <
class TInputImage,
class TPrecision>
103 return static_cast<CountObjectType*
>(this->itk::ProcessObject::GetOutput(10));
106 template <
class TInputImage,
class TPrecision>
110 return static_cast<const CountObjectType*
>(this->itk::ProcessObject::GetOutput(10));
114 template <
class TInputImage,
class TPrecision>
118 return static_cast<PixelObjectType*
>(this->itk::ProcessObject::GetOutput(1));
121 template <
class TInputImage,
class TPrecision>
125 return static_cast<const PixelObjectType*
>(this->itk::ProcessObject::GetOutput(1));
128 template <
class TInputImage,
class TPrecision>
132 return static_cast<PixelObjectType*
>(this->itk::ProcessObject::GetOutput(2));
135 template <
class TInputImage,
class TPrecision>
139 return static_cast<const PixelObjectType*
>(this->itk::ProcessObject::GetOutput(2));
142 template <
class TInputImage,
class TPrecision>
146 return static_cast<RealObjectType*
>(this->itk::ProcessObject::GetOutput(7));
149 template <
class TInputImage,
class TPrecision>
153 return static_cast<const RealObjectType*
>(this->itk::ProcessObject::GetOutput(7));
156 template <
class TInputImage,
class TPrecision>
160 return static_cast<RealObjectType*
>(this->itk::ProcessObject::GetOutput(8));
163 template <
class TInputImage,
class TPrecision>
167 return static_cast<const RealObjectType*
>(this->itk::ProcessObject::GetOutput(8));
171 template <
class TInputImage,
class TPrecision>
175 return static_cast<RealObjectType*
>(this->itk::ProcessObject::GetOutput(9));
178 template <
class TInputImage,
class TPrecision>
182 return static_cast<const RealObjectType*
>(this->itk::ProcessObject::GetOutput(9));
185 template <
class TInputImage,
class TPrecision>
192 template <
class TInputImage,
class TPrecision>
199 template <
class TInputImage,
class TPrecision>
206 template <
class TInputImage,
class TPrecision>
213 template <
class TInputImage,
class TPrecision>
217 return static_cast<MatrixObjectType*
>(this->itk::ProcessObject::GetOutput(5));
220 template <
class TInputImage,
class TPrecision>
224 return static_cast<const MatrixObjectType*
>(this->itk::ProcessObject::GetOutput(5));
227 template <
class TInputImage,
class TPrecision>
231 return static_cast<MatrixObjectType*
>(this->itk::ProcessObject::GetOutput(6));
234 template <
class TInputImage,
class TPrecision>
238 return static_cast<const MatrixObjectType*
>(this->itk::ProcessObject::GetOutput(6));
241 template <
class TInputImage,
class TPrecision>
244 Superclass::GenerateOutputInformation();
245 if (this->GetInput())
247 this->GetOutput()->CopyInformation(this->GetInput());
248 this->GetOutput()->SetLargestPossibleRegion(this->GetInput()->GetLargestPossibleRegion());
250 if (this->GetOutput()->GetRequestedRegion().GetNumberOfPixels() == 0)
252 this->GetOutput()->SetRequestedRegion(this->GetOutput()->GetLargestPossibleRegion());
257 template <
class TInputImage,
class TPrecision>
267 template <
class TInputImage,
class TPrecision>
270 TInputImage* inputPtr =
const_cast<TInputImage*
>(this->GetInput());
271 inputPtr->UpdateOutputInformation();
273 unsigned int numberOfThreads = this->GetNumberOfWorkUnits();
274 unsigned int numberOfComponent = inputPtr->GetNumberOfComponentsPerPixel();
279 tempPixel.SetSize(numberOfComponent);
281 tempPixel.Fill(itk::NumericTraits<InternalPixelType>::max());
282 this->GetMinimumOutput()->Set(tempPixel);
284 tempPixel.Fill(itk::NumericTraits<InternalPixelType>::NonpositiveMin());
285 this->GetMaximumOutput()->Set(tempPixel);
288 tempTemporariesPixel.SetSize(numberOfComponent);
289 tempTemporariesPixel.Fill(itk::NumericTraits<InternalPixelType>::max());
290 m_ThreadMin = std::vector<PixelType>(numberOfThreads, tempTemporariesPixel);
292 tempTemporariesPixel.Fill(itk::NumericTraits<InternalPixelType>::NonpositiveMin());
293 m_ThreadMax = std::vector<PixelType>(numberOfThreads, tempTemporariesPixel);
296 if (m_EnableSecondOrderStats)
298 m_EnableFirstOrderStats =
true;
301 if (m_EnableFirstOrderStats)
304 zeroRealPixel.SetSize(numberOfComponent);
305 zeroRealPixel.Fill(itk::NumericTraits<PrecisionType>::ZeroValue());
306 this->GetMeanOutput()->Set(zeroRealPixel);
307 this->GetSumOutput()->Set(zeroRealPixel);
308 m_ThreadFirstOrderAccumulators.resize(numberOfThreads);
309 std::fill(m_ThreadFirstOrderAccumulators.begin(), m_ThreadFirstOrderAccumulators.end(), zeroRealPixel);
311 RealType zeroReal = itk::NumericTraits<RealType>::ZeroValue();
312 m_ThreadFirstOrderComponentAccumulators.resize(numberOfThreads);
313 std::fill(m_ThreadFirstOrderComponentAccumulators.begin(), m_ThreadFirstOrderComponentAccumulators.end(), zeroReal);
316 if (m_EnableSecondOrderStats)
319 zeroMatrix.SetSize(numberOfComponent, numberOfComponent);
320 zeroMatrix.Fill(itk::NumericTraits<PrecisionType>::Zero);
321 this->GetCovarianceOutput()->Set(zeroMatrix);
322 this->GetCorrelationOutput()->Set(zeroMatrix);
324 m_ThreadSecondOrderAccumulators.resize(numberOfThreads);
325 std::fill(m_ThreadSecondOrderAccumulators.begin(), m_ThreadSecondOrderAccumulators.end(), zeroMatrix);
327 RealType zeroReal = itk::NumericTraits<RealType>::ZeroValue();
328 m_ThreadSecondOrderComponentAccumulators.resize(numberOfThreads);
329 std::fill(m_ThreadSecondOrderComponentAccumulators.begin(), m_ThreadSecondOrderComponentAccumulators.end(), zeroReal);
332 if (m_IgnoreInfiniteValues)
334 m_IgnoredInfinitePixelCount.clear();
335 m_IgnoredInfinitePixelCount.resize(numberOfThreads,0);
338 if (m_IgnoreUserDefinedValue)
340 m_IgnoredUserPixelCount.clear();
341 m_IgnoredUserPixelCount.resize(this->GetNumberOfWorkUnits(),0);
345 template <
class TInputImage,
class TPrecision>
348 TInputImage* inputPtr =
const_cast<TInputImage*
>(this->GetInput());
349 const unsigned int nbPixels = inputPtr->GetLargestPossibleRegion().GetNumberOfPixels();
350 const unsigned int numberOfComponent = inputPtr->GetNumberOfComponentsPerPixel();
353 minimum.SetSize(numberOfComponent);
354 minimum.Fill(itk::NumericTraits<InternalPixelType>::max());
356 maximum.SetSize(numberOfComponent);
357 maximum.Fill(itk::NumericTraits<InternalPixelType>::NonpositiveMin());
359 RealPixelType streamFirstOrderAccumulator(numberOfComponent);
360 streamFirstOrderAccumulator.Fill(itk::NumericTraits<PrecisionType>::Zero);
361 MatrixType streamSecondOrderAccumulator(numberOfComponent, numberOfComponent);
362 streamSecondOrderAccumulator.Fill(itk::NumericTraits<PrecisionType>::Zero);
364 RealType streamFirstOrderComponentAccumulator = itk::NumericTraits<RealType>::Zero;
365 RealType streamSecondOrderComponentAccumulator = itk::NumericTraits<RealType>::Zero;
367 unsigned int ignoredInfinitePixelCount = 0;
368 unsigned int ignoredUserPixelCount = 0;
371 const itk::ThreadIdType numberOfThreads = this->GetNumberOfWorkUnits();
372 for (itk::ThreadIdType threadId = 0; threadId < numberOfThreads; ++threadId)
376 const PixelType& threadMin = m_ThreadMin[threadId];
377 const PixelType& threadMax = m_ThreadMax[threadId];
379 for (
unsigned int j = 0; j < numberOfComponent; ++j)
381 if (threadMin[j] < minimum[j])
383 minimum[j] = threadMin[j];
385 if (threadMax[j] > maximum[j])
387 maximum[j] = threadMax[j];
392 if (m_EnableFirstOrderStats)
394 streamFirstOrderAccumulator += m_ThreadFirstOrderAccumulators[threadId];
395 streamFirstOrderComponentAccumulator += m_ThreadFirstOrderComponentAccumulators[threadId];
398 if (m_EnableSecondOrderStats)
400 streamSecondOrderAccumulator += m_ThreadSecondOrderAccumulators[threadId];
401 streamSecondOrderComponentAccumulator += m_ThreadSecondOrderComponentAccumulators[threadId];
404 ignoredInfinitePixelCount += m_IgnoredInfinitePixelCount[threadId];
406 ignoredUserPixelCount += m_IgnoredUserPixelCount[threadId];
410 assert(nbPixels >= ignoredInfinitePixelCount + ignoredUserPixelCount);
411 if (nbPixels < ignoredInfinitePixelCount + ignoredUserPixelCount)
413 itkExceptionMacro(
"nbPixels < ignoredInfinitePixelCount + ignoredUserPixelCount");
416 unsigned int nbRelevantPixel = nbPixels - (ignoredInfinitePixelCount + ignoredUserPixelCount);
418 CountType nbRelevantPixels(numberOfComponent);
419 nbRelevantPixels.Fill(nbRelevantPixel);
421 this->GetNbRelevantPixelsOutput()->Set(nbRelevantPixels);
423 if (nbRelevantPixel == 0)
425 itkExceptionMacro(
"Statistics cannot be calculated with zero relevant pixels.");
431 this->GetMinimumOutput()->Set(minimum);
432 this->GetMaximumOutput()->Set(maximum);
435 if (m_EnableFirstOrderStats)
437 this->GetComponentMeanOutput()->Set(streamFirstOrderComponentAccumulator / (nbRelevantPixel * numberOfComponent));
439 this->GetMeanOutput()->Set(streamFirstOrderAccumulator / nbRelevantPixel);
440 this->GetSumOutput()->Set(streamFirstOrderAccumulator);
443 if (m_EnableSecondOrderStats)
445 MatrixType cor = streamSecondOrderAccumulator / nbRelevantPixel;
446 this->GetCorrelationOutput()->Set(cor);
451 double regulComponent = 1.0;
453 if (m_UseUnbiasedEstimator && nbRelevantPixel > 1)
455 regul =
static_cast<double>(nbRelevantPixel) / (
static_cast<double>(nbRelevantPixel) - 1.0);
458 if (m_UseUnbiasedEstimator && (nbRelevantPixel * numberOfComponent) > 1)
460 regulComponent =
static_cast<double>(nbRelevantPixel * numberOfComponent) / (
static_cast<double>(nbRelevantPixel * numberOfComponent) - 1.0);
464 for (
unsigned int r = 0; r < numberOfComponent; ++r)
466 for (
unsigned int c = 0; c < numberOfComponent; ++c)
468 cov(r, c) = regul * (cov(r, c) -
mean[r] *
mean[c]);
471 this->GetCovarianceOutput()->Set(cov);
473 this->GetComponentMeanOutput()->Set(streamFirstOrderComponentAccumulator / (nbRelevantPixel * numberOfComponent));
474 this->GetComponentCorrelationOutput()->Set(streamSecondOrderComponentAccumulator / (nbRelevantPixel * numberOfComponent));
475 this->GetComponentCovarianceOutput()->Set(regulComponent * (this->GetComponentCorrelation() - (this->GetComponentMean() * this->GetComponentMean())));
479 template <
class TInputImage,
class TPrecision>
481 itk::ThreadIdType threadId)
484 itk::ProgressReporter progress(
this, threadId, outputRegionForThread.GetNumberOfPixels());
488 PixelType& threadMin = m_ThreadMin[threadId];
489 PixelType& threadMax = m_ThreadMax[threadId];
492 itk::ImageRegionConstIteratorWithIndex<TInputImage> it(inputPtr, outputRegionForThread);
494 for (it.GoToBegin(); !it.IsAtEnd(); ++it, progress.CompletedPixel())
498 float finiteProbe = 0.;
499 bool userProbe = m_IgnoreUserDefinedValue;
500 for (
unsigned int j = 0; j < vectorValue.GetSize(); ++j)
502 finiteProbe += (float)(vectorValue[j]);
503 userProbe = userProbe && (vectorValue[j] == m_UserIgnoredValue);
506 if (m_IgnoreInfiniteValues && !(vnl_math_isfinite(finiteProbe)))
508 m_IgnoredInfinitePixelCount[threadId]++;
514 m_IgnoredUserPixelCount[threadId]++;
520 for (
unsigned int j = 0; j < vectorValue.GetSize(); ++j)
522 if (vectorValue[j] < threadMin[j])
524 threadMin[j] = vectorValue[j];
526 if (vectorValue[j] > threadMax[j])
528 threadMax[j] = vectorValue[j];
533 if (m_EnableFirstOrderStats)
535 RealPixelType& threadFirstOrder = m_ThreadFirstOrderAccumulators[threadId];
536 RealType& threadFirstOrderComponent = m_ThreadFirstOrderComponentAccumulators[threadId];
538 threadFirstOrder += vectorValue;
540 for (
unsigned int i = 0; i < vectorValue.GetSize(); ++i)
542 threadFirstOrderComponent += vectorValue[i];
546 if (m_EnableSecondOrderStats)
548 MatrixType& threadSecondOrder = m_ThreadSecondOrderAccumulators[threadId];
549 RealType& threadSecondOrderComponent = m_ThreadSecondOrderComponentAccumulators[threadId];
551 for (
unsigned int r = 0; r < threadSecondOrder.Rows(); ++r)
553 for (
unsigned int c = 0; c < threadSecondOrder.Cols(); ++c)
558 threadSecondOrderComponent += vectorValue.GetSquaredNorm();
565 template <
class TImage,
class TPrecision>
568 Superclass::PrintSelf(os, indent);
570 os << indent <<
"Min: " << this->GetMinimumOutput()->Get() << std::endl;
571 os << indent <<
"Max: " << this->GetMaximumOutput()->Get() << std::endl;
572 os << indent <<
"Mean: " << this->GetMeanOutput()->Get() << std::endl;
573 os << indent <<
"Covariance: " << this->GetCovarianceOutput()->Get() << std::endl;
574 os << indent <<
"Correlation: " << this->GetCorrelationOutput()->Get() << std::endl;
575 os << indent <<
"Relevant pixel: " << this->GetNbRelevantPixelsOutput()->Get() << std::endl;
576 os << indent <<
"Component Mean: " << this->GetComponentMeanOutput()->Get() << std::endl;
577 os << indent <<
"Component Covariance: " << this->GetComponentCovarianceOutput()->Get() << std::endl;
578 os << indent <<
"Component Correlation: " << this->GetComponentCorrelationOutput()->Get() << std::endl;
579 os << indent <<
"UseUnbiasedEstimator: " << (this->m_UseUnbiasedEstimator ?
"true" :
"false") << std::endl;
std::vector< unsigned int > m_IgnoredUserPixelCount
RealObjectType * GetComponentMeanOutput()
MatrixObjectType * GetCorrelationOutput()
void Synthetize(void) override
ImageType::Pointer InputImagePointer
void Reset(void) override
itk::SimpleDataObjectDecorator< CountType > CountObjectType
void PrintSelf(std::ostream &os, itk::Indent indent) const override
PersistentStreamingStatisticsVectorImageFilter()
itk::SimpleDataObjectDecorator< MatrixType > MatrixObjectType
RealPixelObjectType * GetSumOutput()
itk::VariableLengthVector< PrecisionType > RealPixelType
CountObjectType * GetNbRelevantPixelsOutput()
itk::SimpleDataObjectDecorator< RealPixelType > RealPixelObjectType
std::vector< unsigned int > m_IgnoredInfinitePixelCount
ImageType::InternalPixelType InternalPixelType
ImageType::PixelType PixelType
DataObjectPointer MakeOutput(DataObjectPointerArraySizeType idx) override
itk::VariableLengthVector< unsigned long > CountType
itk::VariableSizeMatrix< PrecisionType > MatrixType
RealObjectType * GetComponentCovarianceOutput()
ImageType::RegionType RegionType
void GenerateOutputInformation() override
PixelObjectType * GetMinimumOutput()
RealPixelObjectType * GetMeanOutput()
void AllocateOutputs() override
itk::ProcessObject::DataObjectPointerArraySizeType DataObjectPointerArraySizeType
MatrixObjectType * GetCovarianceOutput()
RealObjectType * GetComponentCorrelationOutput()
itk::SimpleDataObjectDecorator< PixelType > PixelObjectType
PixelObjectType * GetMaximumOutput()
void ThreadedGenerateData(const RegionType &outputRegionForThread, itk::ThreadIdType threadId) override
itk::SimpleDataObjectDecorator< RealType > RealObjectType
The "otb" namespace contains all Orfeo Toolbox (OTB) classes.