File: otbStreamingStatisticsMapFromLabelImageFilter.h

package info (click to toggle)
otb 7.2.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 1,005,476 kB
  • sloc: cpp: 270,143; xml: 128,722; ansic: 4,367; sh: 1,768; python: 1,084; perl: 92; makefile: 72
file content (470 lines) | stat: -rw-r--r-- 16,806 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
/*
 * Copyright (C) 1999-2011 Insight Software Consortium
 * Copyright (C) 2005-2020 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef otbStreamingStatisticsMapFromLabelImageFilter_h
#define otbStreamingStatisticsMapFromLabelImageFilter_h

#include "otbPersistentImageFilter.h"
#include "itkNumericTraits.h"
#include "itkArray.h"
#include "itkSimpleDataObjectDecorator.h"
#include "otbPersistentFilterStreamingDecorator.h"
#include <unordered_map>

namespace otb
{

/** \class StatisticsMapAccumulator
 * \brief Holds statistics for each label of a label image
 *
 * Intended to store and update the following statistics:
 * -count
 * -sum of values
 * -sum of squared values
 * -min
 * -max
 *
 * TODO:
 * -Better architecture?
 * -Enrich with other statistics?
 * -Move this class in a dedicated source to enable its use by other otbStatistics stuff?
 *
 * \ingroup OTBStatistics
 */
template <class TRealVectorPixelType>
class StatisticsAccumulator
{
public:
  typedef typename TRealVectorPixelType::ValueType  RealValueType;
  typedef uint64_t                                  PixelCountType;
  typedef itk::VariableLengthVector<PixelCountType> PixelCountVectorType;

  // Constructor (default)
  StatisticsAccumulator() : m_Count(), m_NoDataValue(), m_UseNoDataValue()
  {
  }

  // Constructor (initialize the accumulator with the given pixel)
  StatisticsAccumulator(RealValueType noDataValue, bool useNoDataValue, const TRealVectorPixelType& pixel)
    : m_NoDataValue(noDataValue), m_Count(1), m_UseNoDataValue(useNoDataValue)
  {
    m_Count = 1;
    m_BandCount.SetSize(pixel.GetSize());
    m_Sum.SetSize(pixel.GetSize());
    m_Min.SetSize(pixel.GetSize());
    m_Max.SetSize(pixel.GetSize());
    m_SqSum.SetSize(pixel.GetSize());
    for (unsigned int band = 0; band < pixel.GetSize(); band++)
    {
      auto val = pixel[band];
      if (!m_UseNoDataValue || val != m_NoDataValue)
      {
        m_BandCount[band] = 1;
        m_Sum[band]       = val;
        m_Min[band]       = val;
        m_Max[band]       = val;
        m_SqSum[band]     = val * val;
      }
      else
      {
        m_BandCount[band] = 0;
        m_Sum[band]       = itk::NumericTraits<RealValueType>::ZeroValue();
        m_Min[band]       = itk::NumericTraits<RealValueType>::max();
        m_Max[band]       = itk::NumericTraits<RealValueType>::min();
        m_SqSum[band]     = itk::NumericTraits<RealValueType>::ZeroValue();
      }
    }
  }

  // Function update (pixel)
  void Update(const TRealVectorPixelType& pixel)
  {
    m_Count++;
    const unsigned int nBands = pixel.GetSize();
    for (unsigned int band = 0; band < nBands; band++)
    {
      const RealValueType value   = pixel[band];
      const RealValueType sqValue = value * value;

      if (!m_UseNoDataValue || value != m_NoDataValue)
      {
        UpdateValues(1, value, sqValue, value, value, m_BandCount[band], m_Sum[band], m_SqSum[band], m_Min[band], m_Max[band]);
      }
    }
  }

  // Function update (self)
  void Update(const StatisticsAccumulator& other)
  {
    m_Count += other.m_Count;
    const unsigned int nBands = other.m_Sum.GetSize();
    for (unsigned int band = 0; band < nBands; band++)
    {
      UpdateValues(other.m_BandCount[band], other.m_Sum[band], other.m_SqSum[band], other.m_Min[band], other.m_Max[band], m_BandCount[band], m_Sum[band],
                   m_SqSum[band], m_Min[band], m_Max[band]);
    }
  }

  // Accessors
  itkGetMacro(BandCount, PixelCountVectorType);
  itkGetMacro(Sum, TRealVectorPixelType);
  itkGetMacro(SqSum, TRealVectorPixelType);
  itkGetMacro(Min, TRealVectorPixelType);
  itkGetMacro(Max, TRealVectorPixelType);
  itkGetMacro(Count, double);

private:
  void UpdateValues(PixelCountType otherCount, RealValueType otherSum, RealValueType otherSqSum, RealValueType otherMin, RealValueType otherMax,
                    PixelCountType& count, RealValueType& sum, RealValueType& sqSum, RealValueType& min, RealValueType& max)
  {
    count += otherCount;
    sum += otherSum;
    sqSum += otherSqSum;
    if (otherMin < min)
      min = otherMin;
    if (otherMax > max)
      max = otherMax;
  }

protected:
  PixelCountVectorType m_BandCount;
  TRealVectorPixelType m_Sum;
  TRealVectorPixelType m_SqSum;
  TRealVectorPixelType m_Min;
  TRealVectorPixelType m_Max;
  RealValueType        m_NoDataValue;
  PixelCountType       m_Count;
  bool                 m_UseNoDataValue;
};

/** \class PersistentStreamingStatisticsMapFromLabelImageFilter
 * \brief Computes mean radiometric value for each label of a label image, based on a support VectorImage
 *
 * This filter persists its temporary data. It means that if you Update it n times on n different
 * requested regions, the output statistics will be the statitics of the whole set of n regions.
 *
 * To reset the temporary data, one should call the Reset() function.
 *
 * To get the statistics once the regions have been processed via the pipeline, use the Synthetize() method.
 *
 *
 * \sa StreamingStatisticsMapFromLabelImageFilter
 * \ingroup Streamed
 * \ingroup Multithreaded
 * \ingroup MathematicalStatisticsImageFilters
 *
 * \ingroup OTBStatistics
 */
template <class TInputVectorImage, class TLabelImage>
class ITK_EXPORT PersistentStreamingStatisticsMapFromLabelImageFilter : public PersistentImageFilter<TInputVectorImage, TInputVectorImage>
{
public:
  /** Standard Self typedef */
  typedef PersistentStreamingStatisticsMapFromLabelImageFilter        Self;
  typedef PersistentImageFilter<TInputVectorImage, TInputVectorImage> Superclass;
  typedef itk::SmartPointer<Self>                                     Pointer;
  typedef itk::SmartPointer<const Self>                               ConstPointer;

  /** Method for creation through the object factory. */
  itkNewMacro(Self);

  /** Runtime information support. */
  itkTypeMacro(PersistentStreamingStatisticsMapFromLabelImageFilter, PersistentImageFilter);

  /** Image related typedefs. */
  typedef TInputVectorImage                   VectorImageType;
  typedef typename TInputVectorImage::Pointer InputVectorImagePointer;
  typedef TLabelImage                         LabelImageType;
  typedef typename TLabelImage::Pointer       LabelImagePointer;

  typedef typename VectorImageType::RegionType                    RegionType;
  typedef typename VectorImageType::PixelType                     VectorPixelType;
  typedef typename VectorImageType::PixelType::ValueType          VectorPixelValueType;
  typedef typename LabelImageType::PixelType                      LabelPixelType;
  typedef itk::VariableLengthVector<double>                       RealVectorPixelType;
  typedef StatisticsAccumulator<RealVectorPixelType>              AccumulatorType;
  typedef std::unordered_map<LabelPixelType, AccumulatorType>     AccumulatorMapType;
  typedef std::vector<AccumulatorMapType>                         AccumulatorMapCollectionType;
  typedef std::unordered_map<LabelPixelType, RealVectorPixelType> PixelValueMapType;
  typedef std::unordered_map<LabelPixelType, double>              LabelPopulationMapType;

  itkStaticConstMacro(InputImageDimension, unsigned int, TInputVectorImage::ImageDimension);

  /** Image related typedefs. */
  itkStaticConstMacro(ImageDimension, unsigned int, TInputVectorImage::ImageDimension);

  itkGetMacro(NoDataValue, VectorPixelValueType);
  itkSetMacro(NoDataValue, VectorPixelValueType);
  itkGetMacro(UseNoDataValue, bool);
  itkSetMacro(UseNoDataValue, bool);

  /** Smart Pointer type to a DataObject. */
  typedef typename itk::DataObject::Pointer                  DataObjectPointer;
  typedef itk::ProcessObject::DataObjectPointerArraySizeType DataObjectPointerArraySizeType;

  typedef itk::ImageBase<InputImageDimension> ImageBaseType;
  typedef typename ImageBaseType::RegionType  InputImageRegionType;

  /** Type of DataObjects used for scalar outputs */
  typedef itk::SimpleDataObjectDecorator<PixelValueMapType> PixelValueMapObjectType;

  /** Set input label image */
  virtual void SetInputLabelImage(const LabelImageType* image);

  /** Get input label image */
  virtual const LabelImageType* GetInputLabelImage();

  /** Return the computed Mean for each label in the input label image */
  PixelValueMapType GetMeanValueMap() const;

  /** Return the computed Standard Deviation for each label in the input label image */
  PixelValueMapType GetStandardDeviationValueMap() const;

  /** Return the computed Min for each label in the input label image */
  PixelValueMapType GetMinValueMap() const;

  /** Return the computed Max for each label in the input label image */
  PixelValueMapType GetMaxValueMap() const;

  /** Return the computed number of labeled pixels for each label in the input label image */
  LabelPopulationMapType GetLabelPopulationMap() const;

  /** Make a DataObject of the correct type to be used as the specified
   * output. */
  DataObjectPointer MakeOutput(DataObjectPointerArraySizeType idx) override;
  using Superclass::MakeOutput;

  /** Pass the input through unmodified. Do this by Grafting in the
   *  AllocateOutputs method.
   */
  void AllocateOutputs() override;

  void GenerateOutputInformation() override;

  void Synthetize(void) override;

  void Reset(void) override;

  /** Due to heterogeneous input template GenerateInputRequestedRegion must be reimplemented using explicit cast **/
  /** This new implementation is inspired by the one of itk::ImageToImageFilter **/
  void GenerateInputRequestedRegion() override;

protected:
  PersistentStreamingStatisticsMapFromLabelImageFilter();
  ~PersistentStreamingStatisticsMapFromLabelImageFilter() override
  {
  }
  void PrintSelf(std::ostream& os, itk::Indent indent) const override;

  void ThreadedGenerateData(const RegionType& outputRegionForThread, itk::ThreadIdType threadId) override;

private:
  PersistentStreamingStatisticsMapFromLabelImageFilter(const Self&) = delete;
  void operator=(const Self&) = delete;

  VectorPixelValueType m_NoDataValue;
  bool                 m_UseNoDataValue;

  AccumulatorMapCollectionType m_AccumulatorMaps;

  PixelValueMapType m_MeanRadiometricValue;
  PixelValueMapType m_StDevRadiometricValue;
  PixelValueMapType m_MinRadiometricValue;
  PixelValueMapType m_MaxRadiometricValue;

  LabelPopulationMapType m_LabelPopulation;

}; // end of class PersistentStreamingStatisticsMapFromLabelImageFilter


/*===========================================================================*/

/** \class StreamingStatisticsMapFromLabelImageFilter
 * \brief Computes mean radiometric value for each label of a label image, based on a support VectorImage
 *
 * Currently the class only computes the mean value.
 *
 * This class streams the whole input image through the PersistentStreamingStatisticsMapFromLabelImageFilter.
 *
 * This way, it allows computing the first order global statistics of this image.
 * It calls the Reset() method of the PersistentStatisticsImageFilter before streaming
 * the image and the Synthetize() method of the PersistentStatisticsImageFilter
 * after having streamed the image to compute the statistics.
 * The accessor on the results are wrapping the accessors of the
 * internal PersistentStatisticsImageFilter.
 *
 * This filter can be used as:
 * \code
 * typedef otb::StreamingStatisticsMapFromLabelImageFilter<ImageType> StatisticsType;
 * StatisticsType::Pointer statistics = StatisticsType::New();
 * statistics->SetInput(reader->GetOutput());
 * statistics->Update();
 * StatisticsType::PixelValueMapType meanValueMap = statistics->GetMeanValueMap();
 * StatisticsType::PixelValueMapType::const_iterator end = meanValueMap();
 * for (StatisticsType::PixelValueMapType::const_iterator it = meanValueMap.begin(); it != end; ++it)
 * {
 *       std::cout << "label : " << it->first << " , ";
 *                 << "mean value : " << it->second << std::endl;
 * }
 * \endcode
 *
 *
 * \sa PersistentStatisticsImageFilter
 * \sa PersistentImageFilter
 * \sa PersistentFilterStreamingDecorator
 * \sa StreamingImageVirtualWriter
 *
 * \ingroup Streamed
 * \ingroup Multithreaded
 * \ingroup MathematicalStatisticsImageFilters
 *
 * \ingroup OTBStatistics
 */

template <class TInputVectorImage, class TLabelImage>
class ITK_EXPORT StreamingStatisticsMapFromLabelImageFilter
  : public PersistentFilterStreamingDecorator<PersistentStreamingStatisticsMapFromLabelImageFilter<TInputVectorImage, TLabelImage>>
{
public:
  /** Standard Self typedef */
  typedef StreamingStatisticsMapFromLabelImageFilter                                                                               Self;
  typedef PersistentFilterStreamingDecorator<PersistentStreamingStatisticsMapFromLabelImageFilter<TInputVectorImage, TLabelImage>> Superclass;
  typedef itk::SmartPointer<Self>                                                                                                  Pointer;
  typedef itk::SmartPointer<const Self>                                                                                            ConstPointer;

  /** Type macro */
  itkNewMacro(Self);

  /** Creation through object factory macro */
  itkTypeMacro(StreamingStatisticsMapFromLabelImageFilter, PersistentFilterStreamingDecorator);

  typedef TInputVectorImage VectorImageType;
  typedef TLabelImage       LabelImageType;

  typedef typename VectorImageType::PixelType            VectorPixelType;
  typedef typename VectorImageType::PixelType::ValueType VectorPixelValueType;

  typedef typename Superclass::FilterType::PixelValueMapType       PixelValueMapType;
  typedef typename Superclass::FilterType::PixelValueMapObjectType PixelValueMapObjectType;

  typedef typename Superclass::FilterType::LabelPopulationMapType LabelPopulationMapType;

  /** Set input multispectral image */
  using Superclass::SetInput;
  void SetInput(const VectorImageType* input)
  {
    this->GetFilter()->SetInput(input);
  }

  /** Get input multispectral image */
  const VectorImageType* GetInput()
  {
    return this->GetFilter()->GetInput();
  }

  /** Set input label image (monoband) */
  void SetInputLabelImage(const LabelImageType* input)
  {
    this->GetFilter()->SetInputLabelImage(input);
  }

  /** Get input label image (monoband) */
  const LabelImageType* GetInputLabelImage()
  {
    return this->GetFilter()->GetInputLabelImage();
  }

  /** Return the computed Mean for each label */
  PixelValueMapType GetMeanValueMap() const
  {
    return this->GetFilter()->GetMeanValueMap();
  }

  /** Return the computed Standard Deviation for each label */
  PixelValueMapType GetStandardDeviationValueMap() const
  {
    return this->GetFilter()->GetStandardDeviationValueMap();
  }

  /** Return the computed Min for each label */
  PixelValueMapType GetMinValueMap() const
  {
    return this->GetFilter()->GetMinValueMap();
  }

  /** Return the computed Max for each label */
  PixelValueMapType GetMaxValueMap() const
  {
    return this->GetFilter()->GetMaxValueMap();
  }

  /** Return the computed number of labeled pixels for each label */
  LabelPopulationMapType GetLabelPopulationMap() const
  {
    return this->GetFilter()->GetLabelPopulationMap();
  }

  /** Set the no data value */
  void SetNoDataValue(VectorPixelValueType value)
  {
    this->GetFilter()->SetNoDataValue(value);
  }

  /** Return the no data value */
  VectorPixelValueType GetNoDataValue() const
  {
    return this->GetFilter()->GetNoDataValue();
  }

  /** Configure whether no data pixels ignored, treating each band independently */
  void SetUseNoDataValue(bool useNoDataValue)
  {
    this->GetFilter()->SetUseNoDataValue(useNoDataValue);
  }

  /** Return whether no data pixels are ignored */
  bool GetUseNoDataValue() const
  {
    return this->GetFilter()->GetUseNoDataValue();
  }

protected:
  /** Constructor */
  StreamingStatisticsMapFromLabelImageFilter()
  {
  }
  /** Destructor */
  ~StreamingStatisticsMapFromLabelImageFilter() override
  {
  }

private:
  StreamingStatisticsMapFromLabelImageFilter(const Self&) = delete;
  void operator=(const Self&) = delete;
};

} // end namespace otb

#ifndef OTB_MANUAL_INSTANTIATION
#include "otbStreamingStatisticsMapFromLabelImageFilter.hxx"
#endif

#endif