OpenEV
Extending OpenCV to event-based vision
Loading...
Searching...
No Matches
grid.hpp
Go to the documentation of this file.
1
6#ifndef OPENEV_CONTAINERS_GRID_HPP
7#define OPENEV_CONTAINERS_GRID_HPP
8
10#include <cstddef>
11#include <opencv2/core/base.hpp>
12#include <opencv2/core/types.hpp>
13#include <type_traits>
14#include <utility>
15#include <vector>
16
17namespace ev {
18[[maybe_unused]] constexpr bool USING_GRID_HPP = true;
19
21template <typename Container, typename = void>
22struct has_push_back_ : std::false_type {};
23template <typename Container>
24struct has_push_back_<Container, std::void_t<decltype(std::declval<Container &>().push_back(std::declval<const typename Container::value_type &>()))>> : std::true_type {};
25
26template <typename Container, typename = void>
27struct has_push_ : std::false_type {};
28template <typename Container>
29struct has_push_<Container, std::void_t<decltype(std::declval<Container &>().push(std::declval<const typename Container::value_type &>()))>> : std::true_type {};
31
43template <typename Container>
44class Grid_ {
45 static_assert(has_push_back_<Container>::value || has_push_<Container>::value, "ev::Grid_: the container must offer push_back() or push().");
46
47public:
48 using EventType = typename Container::value_type;
49 using T = typename EventType::value_type;
50
57 template <typename... Args>
58 explicit Grid_(const cv::Size sensor, const cv::Size cells, Args &&...args) : sensor_{sensor}, shape_{cells}, prototype_(std::forward<Args>(args)...) {
59 if(sensor.width <= 0 || sensor.height <= 0) {
60 CV_Error(cv::Error::StsBadArg, "ev::Grid_: the sensor size must be positive.");
61 }
62 if(cells.width <= 0 || cells.height <= 0 || cells.width > sensor.width || cells.height > sensor.height) {
63 CV_Error(cv::Error::StsBadArg, "ev::Grid_: the number of cells must be positive and not exceed the sensor size.");
64 }
65 cell_ = cv::Size((sensor.width + cells.width - 1) / cells.width, (sensor.height + cells.height - 1) / cells.height);
66 cells_.assign(static_cast<std::size_t>(cells.width) * static_cast<std::size_t>(cells.height), prototype_);
67 }
68
74 inline bool insert(const EventType &e) {
75 const cv::Point c = cell(e);
76 if(c.x < 0) {
77 return false;
78 }
79 push_(cells_[index_(c)], e);
80 return true;
81 }
82
88 [[nodiscard]] inline cv::Point cell(const EventType &e) const {
89 int x = 0;
90 int y = 0;
91 if constexpr(std::is_floating_point_v<T>) {
92 x = round_(e.x);
93 y = round_(e.y);
94 } else {
95 x = static_cast<int>(e.x);
96 y = static_cast<int>(e.y);
97 }
98 if(x < 0 || y < 0 || x >= sensor_.width || y >= sensor_.height) {
99 return {-1, -1};
100 }
101 return {x / cell_.width, y / cell_.height};
102 }
103
110 [[nodiscard]] inline Container &operator()(const int row, const int col) {
111 return cells_[index_({col, row})];
112 }
113
120 [[nodiscard]] inline const Container &operator()(const int row, const int col) const {
121 return cells_[index_({col, row})];
122 }
123
129 [[nodiscard]] inline Container &operator()(const cv::Point c) {
130 return cells_[index_(c)];
131 }
132
138 [[nodiscard]] inline const Container &operator()(const cv::Point c) const {
139 return cells_[index_(c)];
140 }
141
145 inline void clear() {
146 cells_.assign(cells_.size(), prototype_);
147 }
148
153 [[nodiscard]] inline int rows() const {
154 return shape_.height;
155 }
156
161 [[nodiscard]] inline int cols() const {
162 return shape_.width;
163 }
164
169 [[nodiscard]] inline cv::Size size() const {
170 return shape_;
171 }
172
177 [[nodiscard]] inline cv::Size cellSize() const {
178 return cell_;
179 }
180
185 [[nodiscard]] inline cv::Size sensorSize() const {
186 return sensor_;
187 }
188
190 [[nodiscard]] inline auto begin() {
191 return cells_.begin();
192 }
193
194 [[nodiscard]] inline auto end() {
195 return cells_.end();
196 }
197
198 [[nodiscard]] inline auto begin() const {
199 return cells_.begin();
200 }
201
202 [[nodiscard]] inline auto end() const {
203 return cells_.end();
204 }
206
207private:
208 cv::Size sensor_;
209 cv::Size shape_;
210 cv::Size cell_;
211 Container prototype_;
212 std::vector<Container> cells_;
213
214 [[nodiscard]] inline std::size_t index_(const cv::Point c) const {
215 return (static_cast<std::size_t>(c.y) * static_cast<std::size_t>(shape_.width)) + static_cast<std::size_t>(c.x);
216 }
217
218 static inline void push_(Container &container, const EventType &e) {
219 if constexpr(has_push_<Container>::value) {
220 container.push(e);
221 } else {
222 container.push_back(e);
223 }
224 }
225};
226} // namespace ev
227
228#endif // OPENEV_CONTAINERS_GRID_HPP
const Container & operator()(const int row, const int col) const
Access a cell.
Definition grid.hpp:120
cv::Point cell(const EventType &e) const
Cell an event falls into.
Definition grid.hpp:88
bool insert(const EventType &e)
Insert an event into the cell its coordinates fall into.
Definition grid.hpp:74
cv::Size cellSize() const
Size of each cell in pixels.
Definition grid.hpp:177
cv::Size sensorSize() const
Size of the sensor in pixels.
Definition grid.hpp:185
Container & operator()(const int row, const int col)
Access a cell.
Definition grid.hpp:110
Grid_(const cv::Size sensor, const cv::Size cells, Args &&...args)
Construct a grid of cells covering the sensor.
Definition grid.hpp:58
typename Container::value_type EventType
Definition grid.hpp:48
void clear()
Reset every cell to its freshly constructed state.
Definition grid.hpp:145
const Container & operator()(const cv::Point c) const
Access a cell.
Definition grid.hpp:138
typename EventType::value_type T
Definition grid.hpp:49
cv::Size size() const
Number of cells: width columns and height rows.
Definition grid.hpp:169
int rows() const
Number of rows of the grid.
Definition grid.hpp:153
Container & operator()(const cv::Point c)
Access a cell.
Definition grid.hpp:129
int cols() const
Number of columns of the grid.
Definition grid.hpp:161
Basic event-based vision structures based on OpenCV components.