OpenEV
Extending OpenCV to event-based vision
Loading...
Searching...
No Matches
stats_container.hpp
Go to the documentation of this file.
1
6#ifndef OPENEV_CONTAINERS_STATS_CONTAINER_HPP
7#define OPENEV_CONTAINERS_STATS_CONTAINER_HPP
8
10#include "openev/core/types.hpp"
11#include <algorithm>
12#include <array>
13#include <cmath>
14#include <cstddef>
15#include <cstdint>
16#include <opencv2/core/matx.hpp>
17#include <opencv2/core/types.hpp>
18#include <type_traits>
19#include <vector>
20
21namespace ev {
22[[maybe_unused]] constexpr bool USING_STATS_CONTAINER_HPP = true;
23
25namespace stats {
26constexpr std::size_t TABULATED = 4096;
27constexpr int GROWTH_NUM = 3;
28constexpr int GROWTH_DEN = 2;
29
30inline double cLog2C(const uint32_t c) {
31 static const std::array<double, TABULATED> table = [] {
32 std::array<double, TABULATED> t{};
33 for(std::size_t i = 1; i < TABULATED; i++) {
34 t[i] = static_cast<double>(i) * std::log2(static_cast<double>(i));
35 }
36 return t;
37 }();
38 return c < TABULATED ? table[c] : static_cast<double>(c) * std::log2(static_cast<double>(c));
39}
40} // namespace stats
42
55template <typename T>
56class StatsContainer_ : public Stats_<StatsContainer_<T>> {
57public:
58 using value_type = Event_<T>;
59
64 inline void push(const Event_<T> &e) {
65 int x = 0;
66 int y = 0;
67 if constexpr(std::is_floating_point_v<T>) {
68 x = round_(e.x);
69 y = round_(e.y);
70 } else {
71 x = static_cast<int>(e.x);
72 y = static_cast<int>(e.y);
73 }
74
75 if(a_.n == 0) {
76 a_.first = e.t;
77 }
78 a_.last = e.t;
79 a_.n++;
80 a_.sum += cv::Point2d(e.x, e.y);
81 a_.st += e.t;
82 a_.sp += e.p;
83 a_.squares += cv::Vec3d(static_cast<double>(e.x) * static_cast<double>(e.x), static_cast<double>(e.y) * static_cast<double>(e.y), static_cast<double>(e.x) * static_cast<double>(e.y));
84 a_.bounds |= cv::Rect(x, y, 1, 1);
85
86 if(static_cast<unsigned>(x - box_.x) >= static_cast<unsigned>(box_.width) || static_cast<unsigned>(y - box_.y) >= static_cast<unsigned>(box_.height)) {
87 grow_(x, y);
88 }
89 uint32_t &c = counts_[(static_cast<std::size_t>(y - box_.y) * static_cast<std::size_t>(box_.width)) + static_cast<std::size_t>(x - box_.x)];
90 a_.active += static_cast<std::size_t>(c == 0);
91 a_.sumCLogC += stats::cLog2C(c + 1) - stats::cLog2C(c);
92 c++;
93 a_.peak = std::max(a_.peak, c);
94 }
95
100 [[nodiscard]] inline std::size_t size() const {
101 return a_.n;
102 }
103
108 [[nodiscard]] inline bool empty() const {
109 return a_.n == 0;
110 }
111
112 [[nodiscard]] inline TimeType firstTimestamp() const { return a_.first; }
113 [[nodiscard]] inline TimeType lastTimestamp() const { return a_.last; }
114 [[nodiscard]] inline cv::Point2d sum() const { return a_.sum; }
115 [[nodiscard]] inline double sumT() const { return a_.st; }
116 [[nodiscard]] inline double sumP() const { return a_.sp; }
117 [[nodiscard]] inline cv::Vec3d squares() const { return a_.squares; }
118 [[nodiscard]] inline cv::Rect bounds() const { return a_.bounds; }
119 [[nodiscard]] inline std::size_t activeCount() const { return a_.active; }
120 [[nodiscard]] inline std::size_t peakCount() const { return a_.peak; }
121 [[nodiscard]] inline double sumCLogC() const { return a_.sumCLogC; }
122
126 inline void clear() {
127 a_ = Accumulators_();
128 std::fill(counts_.begin(), counts_.end(), 0);
129 }
130
131private:
132 cv::Rect box_;
133 std::vector<uint32_t> counts_;
134 struct Accumulators_ {
135 std::size_t n{0};
136 TimeType first{0};
137 TimeType last{0};
138 cv::Point2d sum;
139 double st{0};
140 double sp{0};
141 cv::Vec3d squares;
142 cv::Rect bounds;
143 std::size_t active{0};
144 uint32_t peak{0};
145 double sumCLogC{0};
146 };
147 Accumulators_ a_;
148
149 void grow_(const int x, const int y) {
150 if(box_.empty()) {
151 box_ = {x, y, 1, 1};
152 counts_.assign(1, 0);
153 return;
154 }
155 int x0 = std::min(box_.x, x);
156 int y0 = std::min(box_.y, y);
157 const int x1 = std::max(box_.x + box_.width, x + 1);
158 const int y1 = std::max(box_.y + box_.height, y + 1);
159 int width = x1 - x0;
160 int height = y1 - y0;
161 if(width > box_.width) {
162 width = std::max(width, (box_.width * stats::GROWTH_NUM) / stats::GROWTH_DEN);
163 }
164 if(height > box_.height) {
165 height = std::max(height, (box_.height * stats::GROWTH_NUM) / stats::GROWTH_DEN);
166 }
167 if(x < box_.x) {
168 x0 = x1 - width;
169 }
170 if(y < box_.y) {
171 y0 = y1 - height;
172 }
173
174 std::vector<uint32_t> next(static_cast<std::size_t>(width) * static_cast<std::size_t>(height), 0);
175 for(int r = 0; r < box_.height; r++) {
176 std::copy_n(counts_.begin() + static_cast<std::ptrdiff_t>(r) * box_.width, box_.width, next.begin() + (static_cast<std::ptrdiff_t>(r + box_.y - y0) * width) + (box_.x - x0));
177 }
178 counts_.swap(next);
179 box_ = {x0, y0, width, height};
180 }
181};
182
188} // namespace ev
189
190#endif // OPENEV_CONTAINERS_STATS_CONTAINER_HPP
This class extends cv::Point_<T> for event data. For more information, please refer here.
Definition types.hpp:86
PolarityType p
Definition types.hpp:91
TimeType t
Definition types.hpp:90
This class keeps the ingredients of the statistics of Stats_ up to date without storing the events.
Definition stats_container.hpp:56
double sumP() const
Definition stats_container.hpp:116
TimeType firstTimestamp() const
Definition stats_container.hpp:112
void push(const Event_< T > &e)
Account for an event.
Definition stats_container.hpp:64
std::size_t activeCount() const
Definition stats_container.hpp:119
cv::Vec3d squares() const
Definition stats_container.hpp:117
cv::Rect bounds() const
Definition stats_container.hpp:118
cv::Point2d sum() const
Definition stats_container.hpp:114
void clear()
Forget every event. The per-pixel count keeps its extent, so accounting for a similar stream again do...
Definition stats_container.hpp:126
double sumT() const
Definition stats_container.hpp:115
TimeType lastTimestamp() const
Definition stats_container.hpp:113
double sumCLogC() const
Definition stats_container.hpp:121
std::size_t peakCount() const
Definition stats_container.hpp:120
bool empty() const
Check whether no event was accounted for.
Definition stats_container.hpp:108
std::size_t size() const
Number of events accounted for.
Definition stats_container.hpp:100
This is an auxiliary class. This class cannot be instanced.
Definition stats.hpp:51
Statistics shared by everything that accounts for events.
StatsContainer_< long > StatsContainerl
Definition stats_container.hpp:184
StatsContainer_< double > StatsContainerd
Definition stats_container.hpp:186
StatsContaineri StatsContainer
Definition stats_container.hpp:187
StatsContainer_< float > StatsContainerf
Definition stats_container.hpp:185
StatsContainer_< int > StatsContaineri
Definition stats_container.hpp:183
Basic event-based vision structures based on OpenCV components.