6#ifndef OPENEV_CORE_STATS_HPP
7#define OPENEV_CORE_STATS_HPP
15#include <opencv2/core/matx.hpp>
16#include <opencv2/core/types.hpp>
22[[maybe_unused]]
constexpr bool USING_STATS_HPP =
true;
25#define OPENEV_HAS_GETTER_(name) \
26 template <typename C, typename = void> \
27 struct has_##name##_ : std::false_type {}; \
28 template <typename C> \
29 struct has_##name##_<C, std::void_t<decltype(std::declval<const C &>().name())>> : std::true_type {};
31OPENEV_HAS_GETTER_(count)
32OPENEV_HAS_GETTER_(firstTimestamp)
33OPENEV_HAS_GETTER_(lastTimestamp)
34OPENEV_HAS_GETTER_(sum)
35OPENEV_HAS_GETTER_(sumT)
36OPENEV_HAS_GETTER_(sumP)
37OPENEV_HAS_GETTER_(squares)
38OPENEV_HAS_GETTER_(bounds)
39OPENEV_HAS_GETTER_(activeCount)
40OPENEV_HAS_GETTER_(peakCount)
41OPENEV_HAS_GETTER_(sumCLogC)
42#undef OPENEV_HAS_GETTER_
50template <
typename Derived>
53 using ResultType = TimeType;
59 [[nodiscard]]
inline ResultType
duration()
const {
60 if constexpr(has_firstTimestamp_<Derived>::value && has_lastTimestamp_<Derived>::value) {
61 return self_().lastTimestamp() - self_().firstTimestamp();
63 return self_().back().t - self_().front().t;
71 [[nodiscard]]
inline ResultType
rate()
const {
73 return static_cast<ResultType
>(count_()) / span;
81 [[nodiscard]]
inline ResultType
density(
const cv::Size size)
const {
82 return static_cast<ResultType
>(count_()) / (
static_cast<ResultType
>(size.width) *
static_cast<ResultType
>(size.height));
90 if constexpr(has_activeCount_<Derived>::value) {
91 return self_().activeCount();
93 std::size_t active = 0;
94 forEachPixelCount_([&active](
const uint32_t) { active++; });
104 [[nodiscard]]
inline ResultType
fillRatio(
const cv::Size size)
const {
105 return static_cast<ResultType
>(
activePixels()) / (
static_cast<ResultType
>(size.width) *
static_cast<ResultType
>(size.height));
114 if constexpr(has_sumP_<Derived>::value) {
115 const ResultType positive = self_().sumP() /
static_cast<ResultType
>(count_());
116 return p ? positive : 1 - positive;
118 std::size_t matching = 0;
119 for(
const auto &e : self_()) {
120 matching += e.p == p ? 1 : 0;
122 return static_cast<ResultType
>(matching) /
static_cast<ResultType
>(count_());
131 if constexpr(has_sum_<Derived>::value && has_sumT_<Derived>::value && has_sumP_<Derived>::value) {
132 const auto n =
static_cast<ResultType
>(count_());
133 return {self_().sum().x / n, self_().sum().y / n, self_().sumT() / n, self_().sumP() / n > 0.5};
139 for(
const auto &e : self_()) {
145 const auto n =
static_cast<ResultType
>(count_());
146 return {x / n, y / n, t / n, p / n > 0.5};
154 [[nodiscard]]
inline cv::Point_<ResultType>
meanPoint()
const {
155 if constexpr(has_sum_<Derived>::value) {
156 return self_().sum() /
static_cast<ResultType
>(count_());
160 for(
const auto &e : self_()) {
164 const auto n =
static_cast<ResultType
>(count_());
165 return {x / n, y / n};
173 [[nodiscard]]
inline cv::Matx<ResultType, 2, 2>
covariance()
const {
174 if constexpr(has_sum_<Derived>::value && has_squares_<Derived>::value) {
175 const auto n =
static_cast<ResultType
>(count_());
176 const cv::Point_<ResultType>
mean = self_().sum() / n;
177 const cv::Vec<ResultType, 3> squares = self_().squares() / n;
178 const ResultType xy = squares[2] -
mean.x *
mean.y;
179 return {squares[0] -
mean.x *
mean.x, xy, xy, squares[1] -
mean.y *
mean.y};
185 for(
const auto &e : self_()) {
186 const ResultType dx = e.x -
mean.x;
187 const ResultType dy = e.y -
mean.y;
192 const auto n =
static_cast<ResultType
>(count_());
193 return {xx / n, xy / n, xy / n, yy / n};
202 if constexpr(has_bounds_<Derived>::value) {
203 return self_().bounds();
214 if constexpr(has_sumT_<Derived>::value) {
215 return self_().sumT() /
static_cast<ResultType
>(count_());
218 for(
const auto &e : self_()) {
221 return t /
static_cast<ResultType
>(count_());
229 [[nodiscard]]
inline ResultType
midTime()
const {
230 if constexpr(has_firstTimestamp_<Derived>::value && has_lastTimestamp_<Derived>::value) {
231 return 0.5 * (self_().firstTimestamp() + self_().lastTimestamp());
233 return 0.5 * (self_().front().t + self_().back().t);
241 [[nodiscard]]
inline std::size_t
peak()
const {
242 if constexpr(has_peakCount_<Derived>::value) {
243 return self_().peakCount();
246 forEachPixelCount_([&
peak](
const uint32_t count) {
peak = std::max(
peak, count); });
256 [[nodiscard]]
inline ResultType
entropy()
const {
257 const auto n =
static_cast<ResultType
>(count_());
258 if constexpr(has_sumCLogC_<Derived>::value) {
259 const ResultType h = std::log2(n) - self_().sumCLogC() / n;
260 return h < 0 ? 0 : h;
263 forEachPixelCount_([&h, n](
const uint32_t count) {
264 const ResultType p =
static_cast<ResultType
>(count) / n;
265 h -= p * std::log2(p);
273 [[nodiscard]]
inline const Derived &self_()
const {
274 return static_cast<const Derived &
>(*this);
277 [[nodiscard]]
inline std::size_t count_()
const {
278 if constexpr(has_count_<Derived>::value) {
279 return static_cast<std::size_t
>(self_().count());
281 return self_().size();
285 template <
typename E>
286 [[nodiscard]]
inline static cv::Point pixel_(
const E &e) {
287 if constexpr(std::is_floating_point_v<
decltype(e.x)>) {
288 return {round_(e.x), round_(e.y)};
290 return {
static_cast<int>(e.x),
static_cast<int>(e.y)};
294 [[nodiscard]]
inline cv::Rect bounds_()
const {
298 int bottom = INT_MIN;
299 for(
const auto &e : self_()) {
300 const cv::Point pixel = pixel_(e);
301 left = std::min(left, pixel.x);
302 right = std::max(right, pixel.x);
303 top = std::min(top, pixel.y);
304 bottom = std::max(bottom, pixel.y);
306 return {left, top, right - left + 1, bottom - top + 1};
309 template <
typename Fn>
310 inline void forEachPixelCount_(Fn fn)
const {
311 constexpr uint64_t MAX_AREA_PER_EVENT = 32;
313 const auto width =
static_cast<uint64_t
>(bounds.width);
314 const auto height =
static_cast<uint64_t
>(bounds.height);
316 if(width <= (MAX_AREA_PER_EVENT * count_()) / height) {
317 std::vector<uint32_t> counts(width * height, 0);
318 for(
const auto &e : self_()) {
319 const cv::Point pixel = pixel_(e);
320 counts[(
static_cast<uint64_t
>(pixel.y - bounds.y) * width) +
static_cast<uint64_t
>(pixel.x - bounds.x)]++;
322 for(
const uint32_t count : counts) {
328 std::vector<uint64_t> keys;
329 keys.reserve(count_());
330 for(
const auto &e : self_()) {
331 const cv::Point pixel = pixel_(e);
332 keys.push_back((
static_cast<uint64_t
>(
static_cast<uint32_t
>(pixel.y)) << 32U) |
static_cast<uint32_t
>(pixel.x));
334 std::sort(keys.begin(), keys.end());
336 for(std::size_t i = 1; i <= keys.size(); i++) {
337 if(i == keys.size() || keys[i] != keys[i - 1]) {
This class extends cv::Point_<T> for event data. For more information, please refer here.
Definition types.hpp:86
This is an auxiliary class. This class cannot be instanced.
Definition stats.hpp:51
ResultType midTime() const
Calculate the midpoint time between the oldest and the newest event.
Definition stats.hpp:229
ResultType fillRatio(const cv::Size size) const
Compute fill ratio as the fraction of pixels with at least one event.
Definition stats.hpp:104
ResultType duration() const
Time difference between the last and the first event.
Definition stats.hpp:59
cv::Point_< ResultType > meanPoint() const
Compute the mean x,y point of the events.
Definition stats.hpp:154
Event_< ResultType > mean() const
Compute the mean of the events.
Definition stats.hpp:130
std::size_t peak() const
Find the largest number of events on a single pixel.
Definition stats.hpp:241
ResultType density(const cv::Size size) const
Compute event density as the ratio between the number of events and the number of pixels.
Definition stats.hpp:81
ResultType entropy() const
Compute the Shannon entropy of the spatial distribution of the events.
Definition stats.hpp:256
ResultType rate() const
Compute event rate as the ratio between the number of events and the time difference between the last...
Definition stats.hpp:71
std::size_t activePixels() const
Count the pixels with at least one event.
Definition stats.hpp:89
ResultType polarityRatio(const PolarityType p) const
Compute polarity ratio as the fraction of events with the given polarity.
Definition stats.hpp:113
ResultType meanTime() const
Compute the mean time of the events.
Definition stats.hpp:213
cv::Rect boundingBox() const
Compute the smallest rectangle of pixels containing the events.
Definition stats.hpp:201
cv::Matx< ResultType, 2, 2 > covariance() const
Compute the covariance of the x,y coordinates of the events around meanPoint().
Definition stats.hpp:173
Basic event-based vision structures based on OpenCV components.