NumCpp  2.1.0
A C++ implementation of the Python Numpy library
generateThreshold.hpp
Go to the documentation of this file.
1 
30 #pragma once
31 
35 #include "NumCpp/Core/Types.hpp"
36 #include "NumCpp/NdArray.hpp"
38 
39 #include <cmath>
40 #include <string>
41 
42 namespace nc
43 {
44  namespace imageProcessing
45  {
46  //============================================================================
47  // Method Description:
57  template<typename dtype>
58  dtype generateThreshold(const NdArray<dtype>& inImageArray, double inRate)
59  {
61 
62  if (inRate < 0.0 || inRate > 1.0)
63  {
64  THROW_INVALID_ARGUMENT_ERROR("input rate must be of the range [0, 1]");
65  }
66 
67  // first build a histogram
68  auto minValue = static_cast<int32>(std::floor(inImageArray.min().item()));
69  auto maxValue = static_cast<int32>(std::floor(inImageArray.max().item()));
70 
71  if (utils::essentiallyEqual(inRate, 0.0))
72  {
73  return static_cast<dtype>(maxValue);
74  }
75 
76  if (utils::essentiallyEqual(inRate, 1.0))
77  {
79  {
80  return static_cast<dtype>(minValue - 1);
81  }
82 
83  return dtype{ 0 };
84  }
85 
86  const auto histSize = static_cast<uint32>(maxValue - minValue + 1);
87 
88  NdArray<double> histogram(1, histSize);
89  histogram.zeros();
90  for (auto intensity : inImageArray)
91  {
92  const auto bin = static_cast<uint32>(static_cast<int32>(std::floor(intensity)) - minValue);
93  ++histogram[bin];
94  }
95 
96  // integrate the normalized histogram from right to left to make a survival function (1 - CDF)
97  const auto dNumPixels = static_cast<double>(inImageArray.size());
98  NdArray<double> survivalFunction(1, histSize + 1);
99  survivalFunction[-1] = 0.0;
100  for (int32 i = histSize - 1; i > -1; --i)
101  {
102  double histValue = histogram[i] / dNumPixels;
103  survivalFunction[i] = survivalFunction[i + 1] + histValue;
104  }
105 
106  // binary search through the survival function to find the rate
107  uint32 indexLow = 0;
108  uint32 indexHigh = histSize - 1;
109  uint32 index = indexHigh / 2; // integer division
110 
111  constexpr bool keepGoing = true;
112  while (keepGoing)
113  {
114  const double value = survivalFunction[index];
115  if (value < inRate)
116  {
117  indexHigh = index;
118  }
119  else if (value > inRate)
120  {
121  indexLow = index;
122  }
123  else
124  {
125  const int32 thresh = static_cast<int32>(index) + minValue - 1;
127  {
128  return static_cast<dtype>(thresh);
129  }
130 
131  return thresh < 0 ? 0 : static_cast<dtype>(thresh);
132  }
133 
134  if (indexHigh - indexLow < 2)
135  {
136  return static_cast<dtype>(static_cast<int32>(indexHigh) + minValue - 1);
137  }
138 
139  index = indexLow + (indexHigh - indexLow) / 2;
140  }
141 
142  // shouldn't ever get here but stop the compiler from throwing a warning
143  return static_cast<dtype>(histSize - 1);
144  }
145 
146  } // namespace imageProcessing
147 } // namespace nc
StaticAsserts.hpp
nc::NdArray::item
value_type item() const
Definition: NdArrayCore.hpp:2958
nc::int32
std::int32_t int32
Definition: Types.hpp:37
Error.hpp
STATIC_ASSERT_ARITHMETIC
#define STATIC_ASSERT_ARITHMETIC(dtype)
Definition: StaticAsserts.hpp:38
nc::utils::essentiallyEqual
bool essentiallyEqual(dtype inValue1, dtype inValue2) noexcept
Definition: essentiallyEqual.hpp:53
nc::imageProcessing::generateThreshold
dtype generateThreshold(const NdArray< dtype > &inImageArray, double inRate)
Definition: generateThreshold.hpp:58
nc::NdArray::max
NdArray< dtype > max(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:2979
nc::NdArray< dtype >
nc::uint32
std::uint32_t uint32
Definition: Types.hpp:41
nc::floor
dtype floor(dtype inValue) noexcept
Definition: floor.hpp:49
NdArray.hpp
nc
Definition: Coordinate.hpp:45
nc::DtypeInfo
Holds info about the dtype.
Definition: DtypeInfo.hpp:41
DtypeInfo.hpp
essentiallyEqual.hpp
THROW_INVALID_ARGUMENT_ERROR
#define THROW_INVALID_ARGUMENT_ERROR(msg)
Definition: Error.hpp:37
Types.hpp
nc::histogram
std::pair< NdArray< uint32 >, NdArray< double > > histogram(const NdArray< dtype > &inArray, uint32 inNumBins=10)
Definition: histogram.hpp:57
nc::NdArray::min
NdArray< dtype > min(Axis inAxis=Axis::NONE) const
Definition: NdArrayCore.hpp:3036