NumCpp  2.11.0
A Templatized Header Only C++ Implementation of the Python NumPy Library
Cluster.hpp
Go to the documentation of this file.
1 
29 #pragma once
30 
31 #include <algorithm>
32 #include <iostream>
33 #include <limits>
34 #include <string>
35 #include <type_traits>
36 #include <utility>
37 #include <vector>
38 
42 #include "NumCpp/Core/Types.hpp"
44 #include "NumCpp/Utils/num2str.hpp"
45 
46 namespace nc::imageProcessing
47 {
48  //================================================================================
49  // Class Description:
51  template<typename dtype>
52  class Cluster
53  {
54  private:
55  STATIC_ASSERT_ARITHMETIC(dtype);
56 
57  public:
58  //================================Typedefs===============================
59  using const_iterator = typename std::vector<Pixel<dtype>>::const_iterator;
60  using accumulator_t = typename std::conditional<std::is_integral<dtype>::value, int64, double>::type;
61 
62  //=============================================================================
63  // Description:
66  Cluster() = default;
67 
68  //=============================================================================
69  // Description:
74  explicit Cluster(uint32 inClusterId) noexcept :
75  clusterId_(inClusterId)
76  {
77  }
78 
79  //=============================================================================
80  // Description:
87  bool operator==(const Cluster<dtype>& rhs) const noexcept
88  {
89  if (pixels_.size() != rhs.pixels_.size())
90  {
91  return false;
92  }
93 
94  return stl_algorithms::equal(begin(), end(), rhs.begin());
95  }
96 
97  //=============================================================================
98  // Description:
105  bool operator!=(const Cluster<dtype>& rhs) const noexcept
106  {
107  return !(*this == rhs);
108  }
109 
110  //=============================================================================
111  // Description:
118  const Pixel<dtype>& operator[](uint32 inIndex) const noexcept
119  {
120  return pixels_[inIndex];
121  }
122 
123  //=============================================================================
124  // Description:
131  [[nodiscard]] const Pixel<dtype>& at(uint32 inIndex) const
132  {
133  if (inIndex >= pixels_.size())
134  {
135  THROW_INVALID_ARGUMENT_ERROR("index exceeds cluster size.");
136  }
137  return pixels_[inIndex];
138  }
139 
140  //=============================================================================
141  // Description:
146  [[nodiscard]] const_iterator begin() const noexcept
147  {
148  return pixels_.cbegin();
149  }
150 
151  //=============================================================================
152  // Description:
157  [[nodiscard]] const_iterator end() const noexcept
158  {
159  return pixels_.cend();
160  }
161 
162  //=============================================================================
163  // Description:
168  [[nodiscard]] uint32 size() const noexcept
169  {
170  return static_cast<uint32>(pixels_.size());
171  }
172 
173  //=============================================================================
174  // Description:
179  [[nodiscard]] uint32 clusterId() const noexcept
180  {
181  return clusterId_;
182  }
183 
184  //=============================================================================
185  // Description:
190  [[nodiscard]] uint32 rowMin() const noexcept
191  {
192  return rowMin_;
193  }
194 
195  //=============================================================================
196  // Description:
201  [[nodiscard]] uint32 rowMax() const noexcept
202  {
203  return rowMax_;
204  }
205 
206  //=============================================================================
207  // Description:
212  [[nodiscard]] uint32 colMin() const noexcept
213  {
214  return colMin_;
215  }
216 
217  //=============================================================================
218  // Description:
223  [[nodiscard]] uint32 colMax() const noexcept
224  {
225  return colMax_;
226  }
227 
228  //=============================================================================
229  // Description:
234  [[nodiscard]] uint32 height() const noexcept
235  {
236  return rowMax_ - rowMin_ + 1;
237  }
238 
239  //=============================================================================
240  // Description:
245  [[nodiscard]] uint32 width() const noexcept
246  {
247  return colMax_ - colMin_ + 1;
248  }
249 
250  //=============================================================================
251  // Description:
256  [[nodiscard]] accumulator_t intensity() const noexcept
257  {
258  return intensity_;
259  }
260 
261  //=============================================================================
262  // Description:
267  [[nodiscard]] dtype peakPixelIntensity() const noexcept
268  {
269  return peakPixelIntensity_;
270  }
271 
272  //=============================================================================
273  // Description:
278  [[nodiscard]] double eod() const noexcept
279  {
280  return eod_;
281  }
282 
283  //=============================================================================
284  // Description:
289  void addPixel(const Pixel<dtype>& inPixel)
290  {
291  pixels_.push_back(inPixel);
292  intensity_ += static_cast<accumulator_t>(inPixel.intensity);
293 
294  // adjust the cluster bounds
295  rowMin_ = std::min(rowMin_, inPixel.row);
296  rowMax_ = std::max(rowMax_, inPixel.row);
297  colMin_ = std::min(colMin_, inPixel.col);
298  colMax_ = std::max(colMax_, inPixel.col);
299  peakPixelIntensity_ = std::max(peakPixelIntensity_, inPixel.intensity);
300 
301  // calculate the energy on detector estimate
302  eod_ = static_cast<double>(peakPixelIntensity_) / static_cast<double>(intensity_);
303  }
304 
305  //=============================================================================
306  // Description:
311  [[nodiscard]] std::string str() const
312  {
313  std::string out;
314  uint32 counter = 0;
316  end(),
317  [&](const Pixel<dtype>& pixel)
318  { out += "Pixel " + utils::num2str(counter++) + ":" + pixel.str(); });
319 
320  return out;
321  }
322 
323  //============================================================================
327  void print() const
328  {
329  std::cout << *this;
330  }
331 
332  //=============================================================================
333  // Description:
340  friend std::ostream& operator<<(std::ostream& inStream, const Cluster<dtype>& inCluster)
341  {
342  inStream << inCluster.str();
343  return inStream;
344  }
345 
346  private:
347  //================================Attributes===============================
349  int32 clusterId_{ -1 };
351  std::vector<Pixel<dtype>> pixels_{};
353  uint32 rowMin_{ std::numeric_limits<uint32>::max() }; // largest possible number
355  uint32 rowMax_{ 0 };
357  uint32 colMin_{ std::numeric_limits<uint32>::max() }; // largest possible number
359  uint32 colMax_{ 0 };
361  accumulator_t intensity_{ 0 };
363  dtype peakPixelIntensity_{ 0 };
365  dtype minPixel{};
367  dtype maxPixel{};
369  double eod_{ 1. };
370  };
371 } // namespace nc::imageProcessing
#define THROW_INVALID_ARGUMENT_ERROR(msg)
Definition: Error.hpp:37
Holds the information for a cluster of pixels.
Definition: Cluster.hpp:53
friend std::ostream & operator<<(std::ostream &inStream, const Cluster< dtype > &inCluster)
Definition: Cluster.hpp:340
typename std::conditional< std::is_integral< dtype >::value, int64, double >::type accumulator_t
Definition: Cluster.hpp:60
uint32 colMin() const noexcept
Definition: Cluster.hpp:212
const Pixel< dtype > & operator[](uint32 inIndex) const noexcept
Definition: Cluster.hpp:118
typename std::vector< Pixel< dtype > >::const_iterator const_iterator
Definition: Cluster.hpp:59
double eod() const noexcept
Definition: Cluster.hpp:278
uint32 rowMax() const noexcept
Definition: Cluster.hpp:201
const Pixel< dtype > & at(uint32 inIndex) const
Definition: Cluster.hpp:131
const_iterator begin() const noexcept
Definition: Cluster.hpp:146
uint32 height() const noexcept
Definition: Cluster.hpp:234
Cluster(uint32 inClusterId) noexcept
Definition: Cluster.hpp:74
bool operator==(const Cluster< dtype > &rhs) const noexcept
Definition: Cluster.hpp:87
uint32 colMax() const noexcept
Definition: Cluster.hpp:223
void addPixel(const Pixel< dtype > &inPixel)
Definition: Cluster.hpp:289
bool operator!=(const Cluster< dtype > &rhs) const noexcept
Definition: Cluster.hpp:105
std::string str() const
Definition: Cluster.hpp:311
dtype peakPixelIntensity() const noexcept
Definition: Cluster.hpp:267
uint32 clusterId() const noexcept
Definition: Cluster.hpp:179
accumulator_t intensity() const noexcept
Definition: Cluster.hpp:256
uint32 rowMin() const noexcept
Definition: Cluster.hpp:190
uint32 width() const noexcept
Definition: Cluster.hpp:245
uint32 size() const noexcept
Definition: Cluster.hpp:168
const_iterator end() const noexcept
Definition: Cluster.hpp:157
void print() const
Definition: Cluster.hpp:327
Holds the information for a single pixel.
Definition: Pixel.hpp:46
dtype intensity
Definition: Pixel.hpp:55
uint32 col
Definition: Pixel.hpp:54
uint32 row
Definition: Pixel.hpp:53
std::string str() const
Definition: Pixel.hpp:136
Definition: applyThreshold.hpp:34
void for_each(InputIt first, InputIt last, UnaryFunction f)
Definition: StlAlgorithms.hpp:225
bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2) noexcept
Definition: StlAlgorithms.hpp:140
std::string num2str(dtype inNumber)
Definition: num2str.hpp:44
NdArray< dtype > max(const NdArray< dtype > &inArray, Axis inAxis=Axis::NONE)
Definition: max.hpp:44
std::int64_t int64
Definition: Types.hpp:35
NdArray< dtype > min(const NdArray< dtype > &inArray, Axis inAxis=Axis::NONE)
Definition: min.hpp:44
std::int32_t int32
Definition: Types.hpp:36
std::uint32_t uint32
Definition: Types.hpp:40