OpenEV
Extending OpenCV to event-based vision
Loading...
Searching...
No Matches
abstract-container.hpp
Go to the documentation of this file.
1
6#ifndef OPENEV_CONTAINERS_ABSTRACT_CONTAINER_HPP
7#define OPENEV_CONTAINERS_ABSTRACT_CONTAINER_HPP
8
10#include <algorithm>
11#include <climits>
12#include <cmath>
13#include <cstddef>
14#include <cstdint>
15#include <opencv2/core/base.hpp>
16#include <opencv2/core/types.hpp>
17#include <type_traits>
18#include <vector>
19
20namespace ev {
30template <typename Container, typename T>
32public:
33 using ResultType = TimeType;
34
39 [[nodiscard]] inline ResultType duration() const {
40 check_("duration");
41 return self_().back().t - self_().front().t;
42 }
43
48 [[nodiscard]] inline ResultType rate() const {
49 check_("rate");
50 const ResultType span = duration();
51 if(span == 0) {
52 CV_Error(cv::Error::StsDivByZero, "ev::AbstractContainer_::rate: the events span no time.");
53 }
54 return static_cast<ResultType>(self_().size()) / span;
55 }
56
61 [[nodiscard]] inline ResultType midTime() const {
62 check_("midTime");
63 return 0.5 * (self_().front().t + self_().back().t);
64 }
65
70 [[nodiscard]] inline Event_<ResultType> mean() const {
71 check_("mean");
72 ResultType x{0};
73 ResultType y{0};
74 ResultType t{0};
75 ResultType p{0};
76 for(const Event_<T> &e : self_()) {
77 x += e.x;
78 y += e.y;
79 t += e.t;
80 p += e.p;
81 }
82 const auto n = static_cast<ResultType>(self_().size());
83 return {x / n, y / n, t / n, p / n > 0.5};
84 }
85
90 [[nodiscard]] inline cv::Point_<ResultType> meanPoint() const {
91 check_("meanPoint");
92 ResultType x{0};
93 ResultType y{0};
94 for(const Event_<T> &e : self_()) {
95 x += e.x;
96 y += e.y;
97 }
98 const auto n = static_cast<ResultType>(self_().size());
99 return {x / n, y / n};
100 }
101
106 [[nodiscard]] inline ResultType meanTime() const {
107 check_("meanTime");
108 ResultType t{0};
109 for(const Event_<T> &e : self_()) {
110 t += e.t;
111 }
112 return t / static_cast<ResultType>(self_().size());
113 }
114
120 [[nodiscard]] inline ResultType entropy() const {
121 check_("entropy");
122 std::vector<cv::Point> pixels;
123 pixels.reserve(self_().size());
124 for(const Event_<T> &e : self_()) {
125 pixels.push_back(pixel_(e));
126 }
127 return entropy_(pixels);
128 }
129
130protected:
132 [[nodiscard]] inline const Container &self_() const {
133 return static_cast<const Container &>(*this);
134 }
135
136 inline void check_(const char *statistic) const {
137 if(self_().empty()) {
138 CV_Error(cv::Error::StsError, std::string("ev::AbstractContainer_::") + statistic + ": the container is empty.");
139 }
140 }
141
142 [[nodiscard]] inline static cv::Point pixel_(const Event_<T> &e) {
143 if constexpr(std::is_floating_point_v<T>) {
144 return {static_cast<int>(std::lround(e.x)), static_cast<int>(std::lround(e.y))};
145 } else {
146 return {static_cast<int>(e.x), static_cast<int>(e.y)};
147 }
148 }
149
150 [[nodiscard]] inline static ResultType entropy_(const std::vector<cv::Point> &pixels) {
151 constexpr uint64_t MAX_AREA_PER_EVENT = 32;
152 const ResultType n = static_cast<ResultType>(pixels.size());
153
154 int left = INT_MAX;
155 int right = INT_MIN;
156 int top = INT_MAX;
157 int bottom = INT_MIN;
158 for(const cv::Point &pixel : pixels) {
159 left = std::min(left, pixel.x);
160 right = std::max(right, pixel.x);
161 top = std::min(top, pixel.y);
162 bottom = std::max(bottom, pixel.y);
163 }
164
165 const auto width = static_cast<uint64_t>(static_cast<int64_t>(right) - static_cast<int64_t>(left) + 1);
166 const auto height = static_cast<uint64_t>(static_cast<int64_t>(bottom) - static_cast<int64_t>(top) + 1);
167
168 ResultType h{0};
169 if(width <= (MAX_AREA_PER_EVENT * pixels.size()) / height) {
170 std::vector<uint32_t> counts(width * height, 0);
171 for(const cv::Point &pixel : pixels) {
172 counts[(static_cast<uint64_t>(pixel.y - top) * width) + static_cast<uint64_t>(pixel.x - left)]++;
173 }
174 for(const uint32_t count : counts) {
175 if(count > 0) {
176 const ResultType p = static_cast<ResultType>(count) / n;
177 h -= p * std::log2(p);
178 }
179 }
180 } else {
181 std::vector<uint64_t> keys;
182 keys.reserve(pixels.size());
183 for(const cv::Point &pixel : pixels) {
184 keys.push_back((static_cast<uint64_t>(static_cast<uint32_t>(pixel.y)) << 32U) | static_cast<uint32_t>(pixel.x));
185 }
186 std::sort(keys.begin(), keys.end());
187
188 std::size_t run = 1;
189 for(std::size_t i = 1; i <= keys.size(); i++) {
190 if(i == keys.size() || keys[i] != keys[i - 1]) {
191 const ResultType p = static_cast<ResultType>(run) / n;
192 h -= p * std::log2(p);
193 run = 1;
194 } else {
195 run++;
196 }
197 }
198 }
199 return h;
200 }
202};
203} // namespace ev
204
205#endif // OPENEV_CONTAINERS_ABSTRACT_CONTAINER_HPP
This is an auxiliary class. This class cannot be instanced.
Definition abstract-container.hpp:31
cv::Point_< ResultType > meanPoint() const
Compute the mean x,y point of the events.
Definition abstract-container.hpp:90
Event_< ResultType > mean() const
Compute the mean of the events.
Definition abstract-container.hpp:70
ResultType rate() const
Compute event rate as the ratio between the number of events and the time difference between the last...
Definition abstract-container.hpp:48
ResultType entropy() const
Compute the Shannon entropy of the spatial distribution of the events.
Definition abstract-container.hpp:120
ResultType duration() const
Time difference between the last and the first event.
Definition abstract-container.hpp:39
ResultType midTime() const
Calculate the midpoint time between the oldest and the newest event.
Definition abstract-container.hpp:61
ResultType meanTime() const
Compute the mean time of the events.
Definition abstract-container.hpp:106
This class extends cv::Point_<T> for event data. For more information, please refer here.
Definition types.hpp:78
Basic event-based vision structures based on OpenCV components.