NumCpp  2.14.0
A Templatized Header Only C++ Implementation of the Python NumPy Library
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Centroid.hpp
Go to the documentation of this file.
1
28#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"
42
43namespace nc::imageProcessing
44{
45 //================================================================================
46 // Class Description:
48 template<typename dtype>
50 {
51 private:
53
54 public:
55 using accumulator_t = typename std::conditional<std::is_integral<dtype>::value, int64, double>::type;
56
57 //=============================================================================
58 // Description:
61 Centroid() = default;
62
63 //=============================================================================
64 // Description:
70 intensity_(inCluster.intensity()),
71 eod_(inCluster.eod())
72 {
73 centerOfMass(inCluster);
74 setEllipseProperties(inCluster);
75 }
76
77 //=============================================================================
78 // Description:
84 {
85 return row_;
86 }
87
88 //=============================================================================
89 // Description:
95 {
96 return col_;
97 }
98
99 //=============================================================================
100 // Description:
106 {
107 return intensity_;
108 }
109
110 //=============================================================================
111 // Description:
117 {
118 return eod_;
119 }
120
121 //=============================================================================
122 // Description:
128 {
129 return a_;
130 }
131
132 //=============================================================================
133
134 // Description:
140 {
141 return b_;
142 }
143
144 //=============================================================================
145 // Description:
151 {
152 return eccentricity_;
153 }
154
155 //=============================================================================
156
157 // Description:
163 {
164 return orientation_;
165 }
166
167 //=============================================================================
168 // Description:
173 [[nodiscard]] std::string str() const
174 {
175 std::string out = "row = " + utils::num2str(row_) + " col = " + utils::num2str(col_) +
176 " intensity = " + utils::num2str(intensity_) + " eod = " + utils::num2str(eod_) +
177 " a = " + utils::num2str(a_) + " b = " + utils::num2str(b_) +
178 " eccentricity = " + utils::num2str(eccentricity_) +
179 " orientation = " + utils::num2str(orientation_) + '\n';
180
181 return out;
182 }
183
184 //============================================================================
188 void print() const
189 {
190 std::cout << *this;
191 }
192
193 //=============================================================================
194 // Description:
201 bool operator==(const Centroid<dtype>& rhs) const noexcept
202 {
203 return (utils::essentiallyEqual(row_, rhs.row_) && utils::essentiallyEqual(col_, rhs.col_) &&
204 utils::essentiallyEqual(intensity_, rhs.intensity_) && utils::essentiallyEqual(eod_, rhs.eod_) &&
206 utils::essentiallyEqual(eccentricity_, rhs.eccentricity_) &&
207 utils::essentiallyEqual(orientation_, rhs.orientation_));
208 }
209
210 //=============================================================================
211 // Description:
218 bool operator!=(const Centroid<dtype>& rhs) const noexcept
219 {
220 return !(*this == rhs);
221 }
222
223 //=============================================================================
224 // Description:
234 bool operator<(const Centroid<dtype>& rhs) const noexcept
235 {
236 return intensity_ < rhs.intensity_ ? false : true;
237 }
238
239 //=============================================================================
240 // Description:
247 friend std::ostream& operator<<(std::ostream& inStream, const Centroid<dtype>& inCentriod)
248 {
249 inStream << inCentriod.str();
250 return inStream;
251 }
252
253 private:
254 //==================================Attributes================================///
255 double row_{ 0. };
256 double col_{ 0. };
257 accumulator_t intensity_{ 0 };
258 double eod_{ 0. };
260 double a_{};
262 double b_{};
264 double eccentricity_{};
266 double orientation_{};
267
268 //=============================================================================
269 // Description:
276 void centerOfMass(const Cluster<dtype>& inCluster)
277 {
278 const Shape clusterShape(inCluster.height(), inCluster.width());
280 clusterArray.zeros();
281
282 const uint32 rowMin = inCluster.rowMin();
283 const uint32 colMin = inCluster.colMin();
284
285 for (auto& pixel : inCluster)
286 {
287 clusterArray(pixel.row - rowMin, pixel.col - colMin) = pixel.intensity;
288 }
289
291 row_ = rowCol.front() + rowMin;
292 col_ = rowCol.back() + colMin;
293 }
294
295 //=============================================================================
296 // Description:
301 void setEllipseProperties(const Cluster<dtype>& inCluster) noexcept
302 {
303 constexpr auto two = static_cast<double>(2.);
304
305 auto m20 = static_cast<double>(0.);
306 auto m02 = static_cast<double>(0.);
307 auto m11 = static_cast<double>(0.);
308
309 for (typename Cluster<dtype>::const_iterator iter = inCluster.begin(); iter != inCluster.end(); ++iter)
310 {
311 const auto& pixel = *iter;
312 const double deltaX = pixel.col - col_;
313 const double deltaY = pixel.row - row_;
314
315 m11 += deltaX * deltaY;
318 }
319
320 const auto numPixels = static_cast<double>(inCluster.size());
321 m11 /= numPixels;
322 m20 /= numPixels;
323 m02 /= numPixels;
324
325 double piece1 = m20 + m02;
326 piece1 /= two;
327
328 double piece2 = std::sqrt(static_cast<double>(4.) * utils::sqr(m11) + utils::sqr(m20 - m02));
329 piece2 /= two;
330
331 const double lambda1 = piece1 - piece2;
332 const double lambda2 = piece1 + piece2;
333
334 eccentricity_ = std::sqrt(static_cast<double>(1.) - lambda1 / lambda2);
335 orientation_ = static_cast<double>(-0.5) * std::atan2(two * m11, m20 - m02);
336 a_ = two * std::sqrt(lambda2);
337 b_ = two * std::sqrt(lambda1);
338 }
339 };
340} // namespace nc::imageProcessing
#define STATIC_ASSERT_ARITHMETIC(dtype)
Definition StaticAsserts.hpp:39
holds the information for a centroid
Definition Centroid.hpp:50
bool operator<(const Centroid< dtype > &rhs) const noexcept
Definition Centroid.hpp:234
double eod() const noexcept
Definition Centroid.hpp:116
friend std::ostream & operator<<(std::ostream &inStream, const Centroid< dtype > &inCentriod)
Definition Centroid.hpp:247
double b() const noexcept
Definition Centroid.hpp:139
void print() const
Definition Centroid.hpp:188
accumulator_t intensity() const noexcept
Definition Centroid.hpp:105
double col() const noexcept
Definition Centroid.hpp:94
bool operator==(const Centroid< dtype > &rhs) const noexcept
Definition Centroid.hpp:201
Centroid(const Cluster< dtype > &inCluster)
Definition Centroid.hpp:69
double eccentricity() const noexcept
Definition Centroid.hpp:150
bool operator!=(const Centroid< dtype > &rhs) const noexcept
Definition Centroid.hpp:218
double row() const noexcept
Definition Centroid.hpp:83
std::string str() const
Definition Centroid.hpp:173
typename std::conditional< std::is_integral< dtype >::value, int64, double >::type accumulator_t
Definition Centroid.hpp:55
double a() const noexcept
Definition Centroid.hpp:127
double orientation() const noexcept
Definition Centroid.hpp:162
Holds the information for a cluster of pixels.
Definition Cluster.hpp:53
typename std::vector< Pixel< dtype > >::const_iterator const_iterator
Definition Cluster.hpp:59
Definition applyThreshold.hpp:34
std::string num2str(dtype inNumber)
Definition num2str.hpp:44
bool essentiallyEqual(dtype inValue1, dtype inValue2) noexcept
Definition essentiallyEqual.hpp:49
constexpr dtype sqr(dtype inValue) noexcept
Definition sqr.hpp:42
std::int64_t int64
Definition Types.hpp:35
NdArray< double > centerOfMass(const NdArray< dtype > &inArray, Axis inAxis=Axis::NONE)
Definition centerOfMass.hpp:47
NdArray< dtype > arange(dtype inStart, dtype inStop, dtype inStep=1)
Definition arange.hpp:59
std::uint32_t uint32
Definition Types.hpp:40