NumCpp  2.9.0
A Templatized Header Only C++ Implementation of the Python NumPy Library
Centroid.hpp
Go to the documentation of this file.
1 #pragma once
29 
30 #include <cmath>
31 #include <iostream>
32 #include <string>
33 #include <type_traits>
34 
36 #include "NumCpp/Core/Types.hpp"
39 #include "NumCpp/NdArray.hpp"
41 #include "NumCpp/Utils/num2str.hpp"
42 
43 namespace nc
44 {
45  namespace imageProcessing
46  {
47  //================================================================================
48  // Class Description:
50  template<typename dtype>
51  class Centroid
52  {
53  private:
54  STATIC_ASSERT_ARITHMETIC(dtype);
55 
56  public:
57  using accumulator_t = typename std::conditional<std::is_integral<dtype>::value, int64, double>::type;
58 
59  //=============================================================================
60  // Description:
63  Centroid() = default;
64 
65  //=============================================================================
66  // Description:
71  explicit Centroid(const Cluster<dtype>& inCluster) :
72  intensity_(inCluster.intensity()),
73  eod_(inCluster.eod())
74  {
75  centerOfMass(inCluster);
76  setEllipseProperties(inCluster);
77  }
78 
79  //=============================================================================
80  // Description:
85  double row() const noexcept
86  {
87  return row_;
88  }
89 
90  //=============================================================================
91  // Description:
96  double col() const noexcept
97  {
98  return col_;
99  }
100 
101  //=============================================================================
102  // Description:
107  accumulator_t intensity() const noexcept
108  {
109  return intensity_;
110  }
111 
112  //=============================================================================
113  // Description:
118  double eod() const noexcept
119  {
120  return eod_;
121  }
122 
123  //=============================================================================
124  // Description:
129  double a() const noexcept
130  {
131  return a_;
132  }
133 
134  //=============================================================================
135 
136  // Description:
141  double b() const noexcept
142  {
143  return b_;
144  }
145 
146  //=============================================================================
147  // Description:
152  double eccentricity() const noexcept
153  {
154  return eccentricity_;
155  }
156 
157  //=============================================================================
158 
159  // Description:
164  double orientation() const noexcept
165  {
166  return orientation_;
167  }
168 
169  //=============================================================================
170  // Description:
175  std::string str() const
176  {
177  std::string out = "row = " + utils::num2str(row_) + " col = " + utils::num2str(col_) +
178  " intensity = " + utils::num2str(intensity_) + " eod = " + utils::num2str(eod_) +
179  " a = " + utils::num2str(a_) + " b = " + utils::num2str(b_) +
180  " eccentricity = " + utils::num2str(eccentricity_) +
181  " orientation = " + utils::num2str(orientation_) + '\n';
182 
183  return out;
184  }
185 
186  //============================================================================
190  void print() const
191  {
192  std::cout << *this;
193  }
194 
195  //=============================================================================
196  // Description:
203  bool operator==(const Centroid<dtype>& rhs) const noexcept
204  {
205  return (row_ == rhs.row_ && col_ == rhs.col_ && intensity_ == rhs.intensity_ &&
206  utils::essentiallyEqual(eod_, rhs.eod_) && utils::essentiallyEqual(a_, rhs.a_) &&
207  utils::essentiallyEqual(b_, rhs.b_) &&
208  utils::essentiallyEqual(eccentricity_, rhs.eccentricity_) &&
209  utils::essentiallyEqual(orientation_, rhs.orientation_));
210  }
211 
212  //=============================================================================
213  // Description:
220  bool operator!=(const Centroid<dtype>& rhs) const noexcept
221  {
222  return !(*this == rhs);
223  }
224 
225  //=============================================================================
226  // Description:
236  bool operator<(const Centroid<dtype>& rhs) const noexcept
237  {
238  return intensity_ < rhs.intensity_ ? false : true;
239  }
240 
241  //=============================================================================
242  // Description:
249  friend std::ostream& operator<<(std::ostream& inStream, const Centroid<dtype>& inCentriod)
250  {
251  inStream << inCentriod.str();
252  return inStream;
253  }
254 
255  private:
256  //==================================Attributes================================///
257  double row_{ 0. };
258  double col_{ 0. };
259  accumulator_t intensity_{ 0 };
260  double eod_{ 0. };
262  double a_;
264  double b_;
266  double eccentricity_;
268  double orientation_;
269 
270  //=============================================================================
271  // Description:
278  void centerOfMass(const Cluster<dtype>& inCluster)
279  {
280  const Shape clusterShape(inCluster.height(), inCluster.width());
281  NdArray<dtype> clusterArray(clusterShape);
282  clusterArray.zeros();
283 
284  const uint32 rowMin = inCluster.rowMin();
285  const uint32 colMin = inCluster.colMin();
286 
287  for (auto& pixel : inCluster)
288  {
289  clusterArray(pixel.row - rowMin, pixel.col - colMin) = pixel.intensity;
290  }
291 
292  const auto rowCol = nc::centerOfMass(clusterArray);
293  row_ = rowCol.front() + rowMin;
294  col_ = rowCol.back() + colMin;
295  }
296 
297  //=============================================================================
298  // Description:
303  void setEllipseProperties(const Cluster<dtype>& inCluster) noexcept
304  {
305  constexpr double two = static_cast<double>(2.);
306 
307  double m20 = static_cast<double>(0.);
308  double m02 = static_cast<double>(0.);
309  double m11 = static_cast<double>(0.);
310 
311  for (typename Cluster<dtype>::const_iterator iter = inCluster.begin(); iter != inCluster.end(); ++iter)
312  {
313  const auto& pixel = *iter;
314  const double deltaX = pixel.col - col_;
315  const double deltaY = pixel.row - row_;
316 
317  m11 += deltaX * deltaY;
318  m20 += utils::sqr(deltaX);
319  m02 += utils::sqr(deltaY);
320  }
321 
322  const double numPixels = static_cast<double>(inCluster.size());
323  m11 /= numPixels;
324  m20 /= numPixels;
325  m02 /= numPixels;
326 
327  double piece1 = m20 + m02;
328  piece1 /= two;
329 
330  double piece2 = std::sqrt(static_cast<double>(4.) * utils::sqr(m11) + utils::sqr(m20 - m02));
331  piece2 /= two;
332 
333  const double lambda1 = piece1 - piece2;
334  const double lambda2 = piece1 + piece2;
335 
336  eccentricity_ = std::sqrt(static_cast<double>(1.) - lambda1 / lambda2);
337  orientation_ = static_cast<double>(-0.5) * std::atan2(two * m11, m20 - m02);
338  a_ = two * std::sqrt(lambda2);
339  b_ = two * std::sqrt(lambda1);
340  }
341  };
342  } // namespace imageProcessing
343 } // namespace nc
holds the information for a centroid
Definition: Centroid.hpp:52
bool operator<(const Centroid< dtype > &rhs) const noexcept
Definition: Centroid.hpp:236
double eod() const noexcept
Definition: Centroid.hpp:118
double b() const noexcept
Definition: Centroid.hpp:141
void print() const
Definition: Centroid.hpp:190
accumulator_t intensity() const noexcept
Definition: Centroid.hpp:107
double col() const noexcept
Definition: Centroid.hpp:96
bool operator==(const Centroid< dtype > &rhs) const noexcept
Definition: Centroid.hpp:203
Centroid(const Cluster< dtype > &inCluster)
Definition: Centroid.hpp:71
friend std::ostream & operator<<(std::ostream &inStream, const Centroid< dtype > &inCentriod)
Definition: Centroid.hpp:249
double eccentricity() const noexcept
Definition: Centroid.hpp:152
bool operator!=(const Centroid< dtype > &rhs) const noexcept
Definition: Centroid.hpp:220
double row() const noexcept
Definition: Centroid.hpp:85
std::string str() const
Definition: Centroid.hpp:175
typename std::conditional< std::is_integral< dtype >::value, int64, double >::type accumulator_t
Definition: Centroid.hpp:57
double a() const noexcept
Definition: Centroid.hpp:129
double orientation() const noexcept
Definition: Centroid.hpp:164
Holds the information for a cluster of pixels.
Definition: Cluster.hpp:55
typename std::vector< Pixel< dtype > >::const_iterator const_iterator
Definition: Cluster.hpp:61
std::string num2str(dtype inNumber)
Definition: num2str.hpp:46
bool essentiallyEqual(dtype inValue1, dtype inValue2) noexcept
Definition: essentiallyEqual.hpp:51
constexpr dtype sqr(dtype inValue) noexcept
Definition: sqr.hpp:44
Definition: Coordinate.hpp:45
std::int64_t int64
Definition: Types.hpp:35
NdArray< double > centerOfMass(const NdArray< dtype > &inArray, Axis inAxis=Axis::NONE)
Definition: centerOfMass.hpp:47
auto sqrt(dtype inValue) noexcept
Definition: sqrt.hpp:48
std::uint32_t uint32
Definition: Types.hpp:40