File: thresholdtools.h

package info (click to toggle)
aoflagger 3.5.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,000 kB
  • sloc: cpp: 67,891; python: 497; sh: 242; makefile: 22
file content (130 lines) | stat: -rw-r--r-- 5,127 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
#ifndef THRESHOLDTOOLS_H
#define THRESHOLDTOOLS_H

#include <vector>
#include <cmath>
#include <complex>

#include "../structures/image2d.h"
#include "../structures/mask2d.h"

namespace algorithms {

class ThresholdTools {
 public:
  static void MeanAndStdDev(const Image2D* image, const Mask2D* mask,
                            num_t& mean, num_t& stddev);
  static numl_t Sum(const Image2D* image, const Mask2D* mask);
  static numl_t RMS(const Image2D* image, const Mask2D* mask);
  static num_t Mode(const Image2D* input, const Mask2D* mask);
  static num_t WinsorizedMode(const Image2D* image, const Mask2D* mask);
  static num_t WinsorizedMode(const Image2D* image, const Mask2D* maskA,
                              const Mask2D* maskB);
  static num_t WinsorizedMode(const Image2D* image);
  template <typename T>
  static void TrimmedMeanAndStdDev(const std::vector<T>& input, T& mean,
                                   T& stddev);
  template <typename T>
  static void WinsorizedMeanAndStdDev(const std::vector<T>& input, T& mean,
                                      T& stddev);
  static void WinsorizedMeanAndStdDev(const Image2D* image, const Mask2D* mask,
                                      num_t& mean, num_t& stddev);
  static void WinsorizedMeanAndStdDev(const Image2D* image, const Mask2D* maskA,
                                      const Mask2D* maskB, num_t& mean,
                                      num_t& stddev);
  static void WinsorizedMeanAndStdDev(const Image2D* image, num_t& mean,
                                      num_t& stddev);

  template <typename T>
  static double WinsorizedRMS(const std::vector<std::complex<T>>& input);
  template <typename T>
  static double WinsorizedRMS(const std::vector<T>& input);

  static num_t MinValue(const Image2D* image, const Mask2D* mask);
  static num_t MaxValue(const Image2D* image, const Mask2D* mask);
  static void SetFlaggedValuesToZero(Image2D* dest, const Mask2D* mask);
  static void CountMaskLengths(const Mask2D* mask, int* lengths,
                               size_t lengthsSize);

  static void FilterConnectedSamples(Mask2D* mask,
                                     size_t minConnectedSampleArea,
                                     bool eightConnected = true);
  static void FilterConnectedSample(Mask2D* mask, size_t x, size_t y,
                                    size_t minConnectedSampleArea,
                                    bool eightConnected = true);
  static void UnrollPhase(Image2D* image);
  static Image2DPtr ShrinkHorizontally(size_t factor, const Image2D* input,
                                       const Mask2D* mask);
  static Image2DPtr ShrinkVertically(size_t factor, const Image2D* input,
                                     const Mask2D* mask);

  static Image2DPtr FrequencyRectangularConvolution(const Image2D* source,
                                                    size_t convolutionSize) {
    Image2DPtr image(new Image2D(*source));
    const size_t upperWindowHalf = (convolutionSize + 1) / 2;
    for (size_t x = 0; x < image->Width(); ++x) {
      num_t sum = 0.0;
      for (size_t y = 0; y < upperWindowHalf; ++y) sum += image->Value(x, y);
      for (size_t y = upperWindowHalf; y < convolutionSize; ++y) {
        image->SetValue(x, y - upperWindowHalf, sum / (num_t)y);
        sum += image->Value(x, y);
      }
      size_t count = convolutionSize;
      for (size_t y = convolutionSize; y != image->Height(); ++y) {
        image->SetValue(x, y - upperWindowHalf, sum / (num_t)count);
        sum += image->Value(x, y) - image->Value(x, y - convolutionSize);
      }
      for (size_t y = image->Height(); y != image->Height() + upperWindowHalf;
           ++y) {
        image->SetValue(x, y - upperWindowHalf, sum / (num_t)count);
        sum -= image->Value(x, y - convolutionSize);
        --count;
      }
    }
    return image;
  }

  static Mask2DPtr Threshold(const Image2D* image, num_t threshold) {
    Mask2DPtr mask =
        Mask2D::CreateUnsetMaskPtr(image->Width(), image->Height());
    for (size_t y = 0; y < image->Height(); ++y) {
      for (size_t x = 0; x < image->Width(); ++x) {
        mask->SetValue(x, y, image->Value(x, y) >= threshold);
      }
    }
    return mask;
  }

 private:
  ThresholdTools() {}

  // We need this less than operator, because the normal operator
  // does not enforce a strictly ordered set, because a<b != !(b<a) in the case
  // of nans/infs.
  template <typename T>
  static bool numLessThanOperator(const T& a, const T& b) {
    if (std::isfinite(a)) {
      if (std::isfinite(b))
        return a < b;
      else
        return true;
    }
    return false;
  }

  template <typename T>
  static bool complexLessThanOperator(const std::complex<T>& a,
                                      const std::complex<T>& b) {
    if (std::isfinite(a.real()) && std::isfinite(a.imag())) {
      if (std::isfinite(b.real()) && std::isfinite(b.imag()))
        return (a * std::conj(a)).real() < (b * std::conj(b)).real();
      else
        return true;
    }
    return false;
  }
};

}  // namespace algorithms

#endif