Orfeo Toolbox  3.16
otbStreamingStatisticsVectorImageFilter.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: ORFEO Toolbox
4  Language: C++
5  Date: $Date$
6  Version: $Revision$
7 
8 
9  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
10  See OTBCopyright.txt for details.
11 
12 
13  This software is distributed WITHOUT ANY WARRANTY; without even
14  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  PURPOSE. See the above copyright notices for more information.
16 
17 =========================================================================*/
18 #ifndef __otbStreamingStatisticsVectorImageFilter_txx
19 #define __otbStreamingStatisticsVectorImageFilter_txx
21 
22 #include "itkImageRegionIterator.h"
24 #include "itkNumericTraits.h"
25 #include "itkProgressReporter.h"
26 #include "otbMacro.h"
27 
28 namespace otb
29 {
30 
31 template<class TInputImage, class TPrecision>
34  : m_EnableMinMax(true),
35  m_EnableFirstOrderStats(true),
36  m_EnableSecondOrderStats(true),
37  m_UseUnbiasedEstimator(true)
38 {
39  // first output is a copy of the image, DataObject created by
40  // superclass
41 
42  // allocate the data objects for the outputs which are
43  // just decorators around vector/matrix types
44  for (unsigned int i = 1; i < 10; ++i)
45  {
46  this->itk::ProcessObject::SetNthOutput(i, this->MakeOutput(i).GetPointer());
47  }
48 }
49 
50 template<class TInputImage, class TPrecision>
53 ::MakeOutput(unsigned int output)
54 {
55  switch (output)
56  {
57  case 0:
58  return static_cast<itk::DataObject*>(TInputImage::New().GetPointer());
59  break;
60  case 1:
61  case 2:
62  // min/max
63  return static_cast<itk::DataObject*>(PixelObjectType::New().GetPointer());
64  break;
65  case 3:
66  case 4:
67  // mean / sum
68  return static_cast<itk::DataObject*>(RealPixelObjectType::New().GetPointer());
69  break;
70  case 5:
71  case 6:
72  // covariance / correlation
73  return static_cast<itk::DataObject*>(MatrixObjectType::New().GetPointer());
74  break;
75  case 7:
76  case 8:
77  case 9:
78  // component mean, component covariance, component correlation
79  return static_cast<itk::DataObject*>(RealObjectType::New().GetPointer());
80  break;
81  default:
82  // might as well make an image
83  return static_cast<itk::DataObject*>(TInputImage::New().GetPointer());
84  break;
85  }
86 }
87 
88 template<class TInputImage, class TPrecision>
92 {
93  return static_cast<PixelObjectType*>(this->itk::ProcessObject::GetOutput(1));
94 }
95 
96 template<class TInputImage, class TPrecision>
100 {
101  return static_cast<const PixelObjectType*>(this->itk::ProcessObject::GetOutput(1));
102 }
103 
104 template<class TInputImage, class TPrecision>
108 {
109  return static_cast<PixelObjectType*>(this->itk::ProcessObject::GetOutput(2));
110 }
111 
112 template<class TInputImage, class TPrecision>
116 {
117  return static_cast<const PixelObjectType*>(this->itk::ProcessObject::GetOutput(2));
118 }
119 
120 template<class TInputImage, class TPrecision>
124 {
125  return static_cast<RealObjectType*>(this->itk::ProcessObject::GetOutput(7));
126 }
127 
128 template<class TInputImage, class TPrecision>
132 {
133  return static_cast<const RealObjectType*>(this->itk::ProcessObject::GetOutput(7));
134 }
135 
136 template<class TInputImage, class TPrecision>
140 {
141  return static_cast<RealObjectType*>(this->itk::ProcessObject::GetOutput(8));
142 }
143 
144 template<class TInputImage, class TPrecision>
148 {
149  return static_cast<const RealObjectType*>(this->itk::ProcessObject::GetOutput(8));
150 }
151 
152 
153 template<class TInputImage, class TPrecision>
157 {
158  return static_cast<RealObjectType*>(this->itk::ProcessObject::GetOutput(9));
159 }
160 
161 template<class TInputImage, class TPrecision>
165 {
166  return static_cast<const RealObjectType*>(this->itk::ProcessObject::GetOutput(9));
167 }
168 
169 template<class TInputImage, class TPrecision>
173 {
174  return static_cast<RealPixelObjectType*>(this->itk::ProcessObject::GetOutput(3));
175 }
176 
177 template<class TInputImage, class TPrecision>
181 {
182  return static_cast<const RealPixelObjectType*>(this->itk::ProcessObject::GetOutput(3));
183 }
184 
185 template<class TInputImage, class TPrecision>
189 {
190  return static_cast<RealPixelObjectType*>(this->itk::ProcessObject::GetOutput(4));
191 }
192 
193 template<class TInputImage, class TPrecision>
197 {
198  return static_cast<const RealPixelObjectType*>(this->itk::ProcessObject::GetOutput(4));
199 }
200 
201 template<class TInputImage, class TPrecision>
205 {
206  return static_cast<MatrixObjectType*>(this->itk::ProcessObject::GetOutput(5));
207 }
208 
209 template<class TInputImage, class TPrecision>
213 {
214  return static_cast<const MatrixObjectType*>(this->itk::ProcessObject::GetOutput(5));
215 }
216 
217 template<class TInputImage, class TPrecision>
221 {
222  return static_cast<MatrixObjectType*>(this->itk::ProcessObject::GetOutput(6));
223 }
224 
225 template<class TInputImage, class TPrecision>
229 {
230  return static_cast<const MatrixObjectType*>(this->itk::ProcessObject::GetOutput(6));
231 }
232 
233 template<class TInputImage, class TPrecision>
234 void
237 {
238  Superclass::GenerateOutputInformation();
239  if (this->GetInput())
240  {
241  this->GetOutput()->CopyInformation(this->GetInput());
242  this->GetOutput()->SetLargestPossibleRegion(this->GetInput()->GetLargestPossibleRegion());
243 
244  if (this->GetOutput()->GetRequestedRegion().GetNumberOfPixels() == 0)
245  {
246  this->GetOutput()->SetRequestedRegion(this->GetOutput()->GetLargestPossibleRegion());
247  }
248  }
249 }
250 
251 template<class TInputImage, class TPrecision>
252 void
255 {
256  // This is commented to prevent the streaming of the whole image for the first stream strip
257  // It shall not cause any problem because the output image of this filter is not intended to be used.
258  //InputImagePointer image = const_cast< TInputImage * >( this->GetInput() );
259  //this->GraftOutput( image );
260  // Nothing that needs to be allocated for the remaining outputs
261 }
262 
263 template<class TInputImage, class TPrecision>
264 void
267 {
268  TInputImage * inputPtr = const_cast<TInputImage *>(this->GetInput());
269  inputPtr->UpdateOutputInformation();
270 
271  unsigned int numberOfThreads = this->GetNumberOfThreads();
272  unsigned int numberOfComponent = inputPtr->GetNumberOfComponentsPerPixel();
273 
274  if (m_EnableMinMax)
275  {
276  PixelType tempPixel;
277  tempPixel.SetSize(numberOfComponent);
278 
279  tempPixel.Fill(itk::NumericTraits<InternalPixelType>::max());
280  this->GetMinimumOutput()->Set(tempPixel);
281 
282  tempPixel.Fill(itk::NumericTraits<InternalPixelType>::NonpositiveMin());
283  this->GetMaximumOutput()->Set(tempPixel);
284 
285  PixelType tempTemporiesPixel;
286  tempTemporiesPixel.SetSize(numberOfComponent);
287  tempTemporiesPixel.Fill(itk::NumericTraits<InternalPixelType>::max());
288  m_ThreadMin = std::vector<PixelType>(numberOfThreads, tempTemporiesPixel);
289 
290  tempTemporiesPixel.Fill(itk::NumericTraits<InternalPixelType>::NonpositiveMin());
291  m_ThreadMax = std::vector<PixelType>(numberOfThreads, tempTemporiesPixel);
292  }
293 
294  if (m_EnableSecondOrderStats)
295  {
296  m_EnableFirstOrderStats = true;
297  }
298 
299  if (m_EnableFirstOrderStats)
300  {
301  RealPixelType zeroRealPixel;
302  zeroRealPixel.SetSize(numberOfComponent);
303  zeroRealPixel.Fill(itk::NumericTraits<PrecisionType>::ZeroValue());
304  this->GetMeanOutput()->Set(zeroRealPixel);
305  this->GetSumOutput()->Set(zeroRealPixel);
306  m_ThreadFirstOrderAccumulators.resize(numberOfThreads);
307  std::fill(m_ThreadFirstOrderAccumulators.begin(), m_ThreadFirstOrderAccumulators.end(), zeroRealPixel);
308 
309  RealType zeroReal = itk::NumericTraits<RealType>::ZeroValue();
310  m_ThreadFirstOrderComponentAccumulators.resize(numberOfThreads);
311  std::fill(m_ThreadFirstOrderComponentAccumulators.begin(), m_ThreadFirstOrderComponentAccumulators.end(), zeroReal);
312 
313  }
314 
315  if (m_EnableSecondOrderStats)
316  {
317  MatrixType zeroMatrix;
318  zeroMatrix.SetSize(numberOfComponent, numberOfComponent);
319  zeroMatrix.Fill(itk::NumericTraits<PrecisionType>::Zero);
320  this->GetCovarianceOutput()->Set(zeroMatrix);
321  this->GetCorrelationOutput()->Set(zeroMatrix);
322 
323  m_ThreadSecondOrderAccumulators.resize(numberOfThreads);
324  std::fill(m_ThreadSecondOrderAccumulators.begin(), m_ThreadSecondOrderAccumulators.end(), zeroMatrix);
325 
326  RealType zeroReal = itk::NumericTraits<RealType>::ZeroValue();
327  m_ThreadSecondOrderComponentAccumulators.resize(numberOfThreads);
328  std::fill(m_ThreadSecondOrderComponentAccumulators.begin(), m_ThreadSecondOrderComponentAccumulators.end(), zeroReal);
329  }
330 
331 }
332 
333 template<class TInputImage, class TPrecision>
334 void
337 {
338  TInputImage * inputPtr = const_cast<TInputImage *>(this->GetInput());
339  const unsigned int nbPixels = inputPtr->GetLargestPossibleRegion().GetNumberOfPixels();
340  const unsigned int numberOfComponent = inputPtr->GetNumberOfComponentsPerPixel();
341 
342  PixelType minimum;
343  minimum.SetSize(numberOfComponent);
344  minimum.Fill(itk::NumericTraits<InternalPixelType>::max());
345  PixelType maximum;
346  maximum.SetSize(numberOfComponent);
347  maximum.Fill(itk::NumericTraits<InternalPixelType>::NonpositiveMin());
348 
349  RealPixelType streamFirstOrderAccumulator(numberOfComponent);
350  streamFirstOrderAccumulator.Fill(itk::NumericTraits<PrecisionType>::Zero);
351  MatrixType streamSecondOrderAccumulator(numberOfComponent, numberOfComponent);
352  streamSecondOrderAccumulator.Fill(itk::NumericTraits<PrecisionType>::Zero);
353 
354  RealType streamFirstOrderComponentAccumulator = itk::NumericTraits<RealType>::Zero;
355  RealType streamSecondOrderComponentAccumulator = itk::NumericTraits<RealType>::Zero;
356 
357  // Accumulate results from all threads
358  const unsigned int numberOfThreads = this->GetNumberOfThreads();
359  for (unsigned int threadId = 0; threadId < numberOfThreads; ++threadId)
360  {
361  if (m_EnableMinMax)
362  {
363  const PixelType& threadMin = m_ThreadMin [threadId];
364  const PixelType& threadMax = m_ThreadMax [threadId];
365 
366  for (unsigned int j = 0; j < numberOfComponent; ++j)
367  {
368  if (threadMin[j] < minimum[j])
369  {
370  minimum[j] = threadMin[j];
371  }
372  if (threadMax[j] > maximum[j])
373  {
374  maximum[j] = threadMax[j];
375  }
376  }
377  }
378 
379  if (m_EnableFirstOrderStats)
380  {
381  streamFirstOrderAccumulator += m_ThreadFirstOrderAccumulators[threadId];
382  streamFirstOrderComponentAccumulator += m_ThreadFirstOrderComponentAccumulators[threadId];
383  }
384 
385  if (m_EnableSecondOrderStats)
386  {
387  streamSecondOrderAccumulator += m_ThreadSecondOrderAccumulators[threadId];
388  streamSecondOrderComponentAccumulator += m_ThreadSecondOrderComponentAccumulators[threadId];
389  }
390  }
391 
392  // Final calculations
393  if (m_EnableMinMax)
394  {
395  this->GetMinimumOutput()->Set(minimum);
396  this->GetMaximumOutput()->Set(maximum);
397  }
398 
399  if (m_EnableFirstOrderStats)
400  {
401  this->GetComponentMeanOutput()->Set(streamFirstOrderComponentAccumulator / (nbPixels * numberOfComponent));
402 
403  this->GetMeanOutput()->Set(streamFirstOrderAccumulator / nbPixels);
404  this->GetSumOutput()->Set(streamFirstOrderAccumulator);
405  }
406 
407  if (m_EnableSecondOrderStats)
408  {
409 
410  MatrixType cor = streamSecondOrderAccumulator / nbPixels;
411  this->GetCorrelationOutput()->Set(cor);
412 
413  const RealPixelType& mean = this->GetMeanOutput()->Get();
414  double regul = static_cast<double>(nbPixels) / (nbPixels - 1);
415 
416  if (!m_UseUnbiasedEstimator)
417  {
418  regul = 1;
419  }
420 
421  MatrixType cov = cor;
422  for (unsigned int r = 0; r < numberOfComponent; ++r)
423  {
424  for (unsigned int c = 0; c < numberOfComponent; ++c)
425  {
426  cov(r, c) = regul * (cov(r, c) - mean[r] * mean[c]);
427  }
428  }
429  this->GetCovarianceOutput()->Set(cov);
430 
431  this->GetComponentMeanOutput()->Set(streamFirstOrderComponentAccumulator / (nbPixels * numberOfComponent));
432  this->GetComponentCorrelationOutput()->Set(streamSecondOrderComponentAccumulator / (nbPixels * numberOfComponent));
433  this->GetComponentCovarianceOutput()->Set(
434  (nbPixels * numberOfComponent) / (nbPixels * numberOfComponent - 1)
435  * (this->GetComponentCorrelation()
436  - (this->GetComponentMean() * this->GetComponentMean())));
437  }
438 }
439 
440 template<class TInputImage, class TPrecision>
441 void
443 ::ThreadedGenerateData(const RegionType& outputRegionForThread, int threadId)
444 {
445  // Support progress methods/callbacks
446  itk::ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
447 
448  // Grab the input
449  InputImagePointer inputPtr = const_cast<TInputImage *>(this->GetInput());
450  PixelType& threadMin = m_ThreadMin [threadId];
451  PixelType& threadMax = m_ThreadMax [threadId];
452 
453 
454  itk::ImageRegionConstIteratorWithIndex<TInputImage> it(inputPtr, outputRegionForThread);
455 
456  for (it.GoToBegin(); !it.IsAtEnd(); ++it, progress.CompletedPixel())
457  {
458  const PixelType& vectorValue = it.Get();
459 
460  if (m_EnableMinMax)
461  {
462  for (unsigned int j = 0; j < vectorValue.GetSize(); ++j)
463  {
464  if (vectorValue[j] < threadMin[j])
465  {
466  threadMin[j] = vectorValue[j];
467  }
468  if (vectorValue[j] > threadMax[j])
469  {
470  threadMax[j] = vectorValue[j];
471  }
472  }
473  }
474 
475  if (m_EnableFirstOrderStats)
476  {
477  RealPixelType& threadFirstOrder = m_ThreadFirstOrderAccumulators [threadId];
478  RealType& threadFirstOrderComponent = m_ThreadFirstOrderComponentAccumulators [threadId];
479 
480  threadFirstOrder += vectorValue;
481 
482  for (unsigned int i = 0; i < vectorValue.GetSize(); ++i)
483  {
484  threadFirstOrderComponent += vectorValue[i];
485  }
486  }
487 
488  if (m_EnableSecondOrderStats)
489  {
490  MatrixType& threadSecondOrder = m_ThreadSecondOrderAccumulators[threadId];
491  RealType& threadSecondOrderComponent = m_ThreadSecondOrderComponentAccumulators[threadId];
492 
493  for (unsigned int r = 0; r < threadSecondOrder.Rows(); ++r)
494  {
495  for (unsigned int c = 0; c < threadSecondOrder.Cols(); ++c)
496  {
497  threadSecondOrder(r, c) += vectorValue[r] * vectorValue[c];
498  }
499  }
500  threadSecondOrderComponent += vectorValue.GetSquaredNorm();
501  }
502 
503  }
504 }
505 
506 template <class TImage, class TPrecision>
507 void
509 ::PrintSelf(std::ostream& os, itk::Indent indent) const
510 {
511  Superclass::PrintSelf(os, indent);
512 
513  os << indent << "Min: " << this->GetMinimumOutput()->Get() << std::endl;
514  os << indent << "Max: " << this->GetMaximumOutput()->Get() << std::endl;
515  os << indent << "Mean: " << this->GetMeanOutput()->Get() << std::endl;
516  os << indent << "Covariance: " << this->GetCovarianceOutput()->Get() << std::endl;
517  os << indent << "Correlation: " << this->GetCorrelationOutput()->Get() << std::endl;
518  os << indent << "Component Mean: " << this->GetComponentMeanOutput()->Get() << std::endl;
519  os << indent << "Component Covariance: " << this->GetComponentCovarianceOutput()->Get() << std::endl;
520  os << indent << "Component Correlation: " << this->GetComponentCorrelationOutput()->Get() << std::endl;
521  os << indent << "UseUnbiasedEstimator: " << (this->m_UseUnbiasedEstimator ? "true" : "false") << std::endl;
522 }
523 
524 } // end namespace otb
525 #endif

Generated at Sun Feb 3 2013 00:49:40 for Orfeo Toolbox with doxygen 1.8.1.1