NumCpp  1.0
A C++ implementation of the Python Numpy library
generateThreshold.hpp
Go to the documentation of this file.
1 
30 #pragma once
31 
33 #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  int32 minValue = static_cast<int32>(std::floor(inImageArray.min().item()));
69  int32 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  else if (utils::essentiallyEqual(inRate, 1.0))
76  {
78  {
79  return static_cast<dtype>(minValue - 1);
80  }
81  else
82  {
83  return dtype{ 0 };
84  }
85  }
86 
87  const uint32 histSize = static_cast<uint32>(maxValue - minValue + 1);
88 
89  NdArray<double> histogram(1, histSize);
90  histogram.zeros();
91  for (auto intensity : inImageArray)
92  {
93  const uint32 bin = static_cast<uint32>(static_cast<int32>(std::floor(intensity)) - minValue);
94  ++histogram[bin];
95  }
96 
97  // integrate the normalized histogram from right to left to make a survival function (1 - CDF)
98  const double dNumPixels = static_cast<double>(inImageArray.size());
99  NdArray<double> survivalFunction(1, histSize + 1);
100  survivalFunction[-1] = 0.0;
101  for (int32 i = histSize - 1; i > -1; --i)
102  {
103  double histValue = histogram[i] / dNumPixels;
104  survivalFunction[i] = survivalFunction[i + 1] + histValue;
105  }
106 
107  // binary search through the survival function to find the rate
108  uint32 indexLow = 0;
109  uint32 indexHigh = histSize - 1;
110  uint32 index = indexHigh / 2; // integer division
111 
112  constexpr bool keepGoing = true;
113  while (keepGoing)
114  {
115  const double value = survivalFunction[index];
116  if (value < inRate)
117  {
118  indexHigh = index;
119  }
120  else if (value > inRate)
121  {
122  indexLow = index;
123  }
124  else
125  {
126  const int32 thresh = static_cast<int32>(index) + minValue - 1;
128  {
129  return static_cast<dtype>(thresh);
130  }
131  else
132  {
133  return thresh < 0 ? 0 : static_cast<dtype>(thresh);
134  }
135  }
136 
137  if (indexHigh - indexLow < 2)
138  {
139  return static_cast<dtype>(static_cast<int32>(indexHigh) + minValue - 1);
140  }
141 
142  index = indexLow + (indexHigh - indexLow) / 2;
143  }
144 
145  // shouldn't ever get here but stop the compiler from throwing a warning
146  return static_cast<dtype>(histSize - 1);
147  }
148 
149  }
150 }
StaticAsserts.hpp
nc::NdArray::item
value_type item() const
Definition: NdArrayCore.hpp:2950
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:2971
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:3027