VisionServer  v2.1.1-1-g21dc5465
FRC vision library
vision.h
Go to the documentation of this file.
1#pragma once
2
3#include <type_traits>
4#include <algorithm>
5#include <vector>
6#include <array>
7
8#include <opencv2/core/types.hpp>
9
10#include <networktables/NetworkTableInstance.h>
11#include <networktables/NetworkTable.h>
12#include <cameraserver/CameraServer.h>
13#include <wpi/StringExtras.h>
14
15#include "visioncamera.h"
16
28// cs::CvSink switchedCameraVision(
29// const std::vector<VisionCamera>& cameras,
30// std::shared_ptr<nt::NetworkTable> table = nt::NetworkTableInstance::GetDefault().GetTable("Vision")
31// );
32
38inline cv::Size getResolution(cs::VideoMode vm) { return cv::Size(vm.height, vm.width); }
39
44cs::VideoMode getJsonVideoMode(const wpi::json& config);
45
53// template<typename num_t>
54// void addNetTableVar(num_t& var, const std::string& name, std::shared_ptr<nt::NetworkTable> table);
61//void addNetTableVar(bool& var, const std::string& name, std::shared_ptr<nt::NetworkTable> table);
62
71template<typename num_t, typename dnum_t> static inline
72cv::Size_<num_t> operator/(cv::Size_<num_t> input, dnum_t scale) {
73 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
74 static_assert(std::is_arithmetic<dnum_t>::value, "Template parameter (dnum_t) must be arithemetic type");
75 return cv::Size_<num_t>(input.width/scale, input.height/scale);
76}
77// template<typename num_t> static inline
78// cv::Size_<num_t> operator/(cv::Size_<num_t> input, size_t scale) {
79// static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
80// return cv::Size_<num_t>(input.width/scale, input.height/scale);
81// }
82
83template<typename num_t>
84inline bool inRange(num_t a, num_t lower, num_t upper) {
85 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
86 return a <= upper && a >= lower;
87}
88
89// inserts(copies) the item at the specified index to the beginning, then erases the source -> effectively moves the item to the beginning while retaining order of other items
90template<typename t>
91void reinsert(std::vector<t>& vec, size_t idx) {
92 vec.insert(vec.begin(), vec.at(idx));
93 vec.erase(vec.begin() + idx + 1);
94}
95template<typename t>
96inline void swapIdx(std::vector<t>& vec, size_t idx1, size_t idx2) {
97 std::iter_swap(vec.begin()+idx1, vec.begin()+idx2);
98}
99
100template <typename num_t>
101inline int sgn(num_t val) { return (num_t(0) < val) - (val < num_t(0)); }
102
103template<typename num_t>
104inline cv::Size_<num_t> distance(const cv::Point_<num_t>& a, const cv::Point_<num_t>& b) {
105 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
106 return cv::Size_<num_t>(std::abs(a.x-b.x), std::abs(a.y-b.y));
107}
108template<typename num_t>
109inline cv::Point3_<num_t> distance(const cv::Point3_<num_t>& a, const cv::Point3_<num_t>& b) {
110 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
111 return cv::Point3_<num_t>(std::abs(a.x-b.x), std::abs(a.y-b.y), std::abs(a.z-b.z));
112}
113
114template<typename num_t>
115inline bool operator<(const cv::Size_<num_t>& a, const cv::Size_<num_t>& b) {
116 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
117 return a.width < b.width && a.height < b.height;
118}
119template<typename num_t>
120inline bool operator<=(const cv::Size_<num_t>& a, const cv::Size_<num_t>& b) {
121 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
122 return a.width <= b.width && a.height <= b.height;
123}
124template<typename num_t>
125inline bool operator>(const cv::Size_<num_t>& a, const cv::Size_<num_t>& b) {
126 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
127 return a.width > b.width && a.height > b.height;
128}
129template<typename num_t>
130inline bool operator>=(const cv::Size_<num_t>& a, const cv::Size_<num_t>& b) {
131 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
132 return a.width >= b.width && a.height >= b.height;
133}
134
135template<typename num_t>
136inline cv::Point_<num_t> operator - (const cv::Point_<num_t>& a, const cv::Size_<num_t>& b) {
137 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
138 return cv::Point_<num_t>(a.x-b.width, a.y-b.height);
139}
140template<typename num_t>
141inline cv::Point_<num_t> operator + (const cv::Point_<num_t>& a, const cv::Size_<num_t>& b) {
142 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
143 return cv::Point_<num_t>(a.x+b.width, a.y+b.height);
144}
145template<typename num_t>
146inline cv::Size_<num_t> operator - (const cv::Size_<num_t>& a, const cv::Point_<num_t>& b) {
147 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
148 return cv::Point_<num_t>(a.width-b.x, a.height-b.y);
149}
150template<typename num_t>
151inline cv::Size_<num_t> operator + (const cv::Size_<num_t>& a, const cv::Point_<num_t>& b) {
152 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
153 return cv::Point_<num_t>(a.width+b.x, a.height+b.y);
154}
155
156template<typename inum1_t, typename inum2_t, typename onum_t>
157inline cv::Size_<onum_t> operator / (const cv::Size_<inum1_t>& a, const cv::Size_<inum2_t>& b) {
158 static_assert(std::is_arithmetic<inum1_t>::value, "Template parameter (inum1_t) must be arithemetic type");
159 static_assert(std::is_arithmetic<inum2_t>::value, "Template parameter (inum2_t) must be arithemetic type");
160 static_assert(std::is_arithmetic<onum_t>::value, "Template parameter (onum_t) must be arithemetic type");
161 return cv::Size_<onum_t>((onum_t)a.width / b.width, (onum_t)a.height / b.height);
162}
163
164template<typename num_t>
165void operator -= (const cv::Point_<num_t>& a, const cv::Size_<num_t>& b);
166template<typename num_t>
167void operator += (const cv::Point_<num_t>& a, const cv::Size_<num_t>& b);
168template<typename num_t>
169void operator -= (const cv::Size_<num_t>& a, const cv::Point_<num_t>& b);
170template<typename num_t>
171void operator += (const cv::Size_<num_t>& a, const cv::Point_<num_t>& b);
172
173template<typename num_t>
174void rescale(std::vector<cv::Point_<num_t> >& points, size_t scale); // scales up (multiplies by scale)
175template<typename num_t>
176void _rescale(std::vector<cv::Point_<num_t> >& points, size_t scale); // scales down with a size value (multiplies by 1.0/value)
177template<typename num_t>
178void rescale(std::vector<cv::Point_<num_t> >& points, double scale); // scales up or down (multiplies by scale)
179template<typename num_t>
180void rescale(std::vector<std::vector<cv::Point_<num_t> > >& contours, double scale);
181template<typename num_t>
182void rescale(std::vector<cv::Rect_<num_t> >& rects, double scale);
183
184template<typename num_t>
185cv::Point_<num_t> findCenter(const std::vector<cv::Point_<num_t> >& contour);
186template<typename onum_t, typename inum_t>
187cv::Point_<onum_t> findCenter(const std::vector<cv::Point_<inum_t> >& contour);
188template<typename num_t>
189cv::Point3_<num_t> findCenter3D(const std::vector<cv::Point3_<num_t> >& contour);
190template<typename onum_t, typename inum_t>
191cv::Point3_<onum_t> findCenter3D(const std::vector<cv::Point3_<inum_t> >& contour);
192
193template<typename num_t>
194cv::Point_<num_t> findCenter(const cv::Rect_<num_t>& rect);
195template<typename onum_t, typename inum_t>
196cv::Point_<onum_t> findCenter(const cv::Rect_<inum_t>& rect);
197
198template<typename num_t>
199void reorderClockWise(std::vector<cv::Point_<num_t> >& points);
200template<typename num_t>
201void reorderCClockWise(std::vector<cv::Point_<num_t> >& points);
202// reorder sorting with point-buffer params
203
204template<typename num_t, size_t s>
205std::array<cv::Point3_<num_t>, s> operator+(const std::array<cv::Point_<num_t>, s>& base, num_t depth);
206template<typename num_t, size_t s>
207std::array<cv::Point3_<num_t>, s> operator+(const std::array<cv::Point3_<num_t>, s>& base, num_t depth);
208template<typename num_t, size_t s>
209void operator+=(std::array<cv::Point3_<num_t>, s>& base, num_t depth); // extend by depth amount
210template<typename num_t>
211std::vector<cv::Point3_<num_t> > operator+(const std::vector<cv::Point_<num_t> >& base, num_t depth);
212template<typename num_t>
213std::vector<cv::Point3_<num_t> > operator+(const std::vector<cv::Point3_<num_t> >& base, num_t depth);
214template<typename num_t>
215void operator+=(std::vector<cv::Point3_<num_t>>& base, num_t depth);
216template<typename num_t, size_t s>
217const auto extend_array = operator+=<num_t, s>; // an alias
218template<typename num_t>
219const auto extend_vector = operator+=<num_t>;
220
221
222
223
224
225
226
227
228
229
232// template<typename num_t>
233// void addNetTableVar(num_t& var, const std::string& name, std::shared_ptr<nt::NetworkTable> table) {
234// static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
235// if(!table->ContainsKey(name)) {
236// table->PutNumber(name, var);
237// } else {}
238// table->GetEntry(name).AddListener(
239// [&var](const nt::EntryNotification& event){
240// if(event.value->IsDouble()) {
241// var = event.value->GetDouble();
242// //std::cout << "Networktable var(num) updated to : " << var << newline;
243// }
244// },
245// NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE
246// );
247// }
248
249template<typename num_t>
250void rescale(std::vector<cv::Point_<num_t> >& points, size_t scale) {
251 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
252 for(size_t i = 0; i < points.size(); i++) {
253 points[i] *= (int)scale;
254 }
255}
256template<typename num_t>
257void _rescale(std::vector<cv::Point_<num_t> >& points, size_t scale) {
258 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
259 for(size_t i = 0; i < points.size(); i++) {
260 points[i] /= (int)scale;
261 }
262}
263template<typename num_t>
264void rescale(std::vector<cv::Point_<num_t> >& points, double scale) {
265 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
266 for(size_t i = 0; i < points.size(); i++) {
267 points[i] *= scale;
268 }
269}
270template<typename num_t>
271void rescale(std::vector<std::vector<cv::Point_<num_t> > >& contours, double scale) {
272 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
273 for(std::vector<cv::Point_<num_t> >& contour : contours) {
274 for(cv::Point_<num_t>& point : contour) {
275 point *= scale;
276 }
277 }
278}
279template<typename num_t>
280void rescale(std::vector<cv::Rect_<num_t> >& rects, double scale) {
281 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
282 for(cv::Rect_<num_t>& r : rects) {
283 r.x *= scale;
284 r.y *= scale;
285 r.width *= scale;
286 r.height *= scale;
287 }
288}
289
290template<typename num_t>
291cv::Point_<num_t> findCenter(const std::vector<cv::Point_<num_t> >& contour) {
292 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
293 if(contour.size() > 0) {
294 cv::Point_<num_t> ret;
295 for(size_t i = 0; i < contour.size(); i++) {
296 ret.x += contour[i].x;
297 ret.y += contour[i].y;
298 }
299 ret.x /= contour.size();
300 ret.y /= contour.size();
301 return ret;
302 }
303 return cv::Point_<num_t>();
304}
305template<typename onum_t, typename inum_t>
306cv::Point_<onum_t> findCenter(const std::vector<cv::Point_<inum_t> >& contour) {
307 static_assert(std::is_arithmetic<onum_t>::value, "Template parameter (num_t) must be arithemetic type");
308 static_assert(std::is_arithmetic<inum_t>::value, "Template parameter (num_t) must be arithemetic type");
309 if(contour.size() > 0) {
310 cv::Point_<onum_t> ret;
311 for(size_t i = 0; i < contour.size(); i++) {
312 ret.x += contour[i].x;
313 ret.y += contour[i].y;
314 }
315 ret.x /= contour.size();
316 ret.y /= contour.size();
317 return ret;
318 }
319 return cv::Point_<onum_t>();
320}
321template<typename num_t>
322cv::Point3_<num_t> findCenter3D(const std::vector<cv::Point3_<num_t> >& contour) {
323 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
324 if(contour.size() > 0) {
325 cv::Point3_<num_t> ret;
326 for(size_t i = 0; i < contour.size(); i++) {
327 ret.x += contour[i].x;
328 ret.y += contour[i].y;
329 ret.z += contour[i].z;
330 }
331 ret.x /= contour.size();
332 ret.y /= contour.size();
333 ret.z /= contour.size();
334 return ret;
335 }
336 return cv::Point3_<num_t>();
337}
338template<typename onum_t, typename inum_t>
339cv::Point3_<onum_t> findCenter3D(const std::vector<cv::Point3_<inum_t> >& contour) {
340 static_assert(std::is_arithmetic<onum_t>::value, "Template parameter (num_t) must be arithemetic type");
341 static_assert(std::is_arithmetic<inum_t>::value, "Template parameter (num_t) must be arithemetic type");
342 if(contour.size() > 0) {
343 cv::Point3_<onum_t> ret;
344 for(size_t i = 0; i < contour.size(); i++) {
345 ret.x += contour[i].x;
346 ret.y += contour[i].y;
347 ret.z += contour[i].z;
348 }
349 ret.x /= contour.size();
350 ret.y /= contour.size();
351 ret.z /= contour.size();
352 return ret;
353 }
354 return cv::Point3_<onum_t>();
355}
356
357template<typename num_t>
358cv::Point_<num_t> findCenter(const cv::Rect_<num_t>& rect) {
359 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
360 cv::Point_<num_t> ret;
361 ret.x = rect.tl().x + rect.br().x;
362 ret.y = rect.tl().y + rect.br().y;
363 ret.x /= 2;
364 ret.y /= 2;
365 return ret;
366}
367template<typename onum_t, typename inum_t>
368cv::Point_<onum_t> findCenter(const cv::Rect_<inum_t>& rect) {
369 static_assert(std::is_arithmetic<onum_t>::value, "Template parameter (num_t) must be arithemetic type");
370 static_assert(std::is_arithmetic<inum_t>::value, "Template parameter (num_t) must be arithemetic type");
371 cv::Point_<onum_t> ret;
372 ret.x = rect.tl().x + rect.br().x;
373 ret.y = rect.tl().y + rect.br().y;
374 ret.x /= 2;
375 ret.y /= 2;
376 return ret;
377}
378
379template<typename num_t>
380void reorderClockWise(std::vector<cv::Point_<num_t> >& points) {
381 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
382 cv::Point_<num_t> center = findCenter<num_t, num_t>(points), abuff, bbuff;
383 std::sort(
384 points.begin(),
385 points.end(),
386 [center, &abuff, &bbuff](const cv::Point_<num_t>& a, const cv::Point_<num_t>& b) {
387 abuff = a - center;
388 bbuff = b - center;
389 return -atan2(abuff.x, abuff.y) < -atan2(bbuff.x, bbuff.y);
390 }
391 );
392}
393template<typename num_t>
394void reorderCClockWise(std::vector<cv::Point_<num_t> >& points) {
395 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
396 cv::Point_<num_t> center = findCenter<num_t, num_t>(points), abuff, bbuff;
397 std::sort(
398 points.begin(),
399 points.end(),
400 [center, &abuff, &bbuff](const cv::Point_<num_t>& a, const cv::Point_<num_t>& b) {
401 abuff = a - center;
402 bbuff = b - center;
403 return atan2(abuff.x, abuff.y) < atan2(bbuff.x, bbuff.y);
404 }
405 );
406}
407
408template<typename num_t, size_t s>
409std::array<cv::Point3_<num_t>, s> operator+(const std::array<cv::Point_<num_t>, s>& base, num_t depth) {
410 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
411 std::array<cv::Point3_<num_t>, s> ret;
412 for(size_t i = 0; i < s; i++) {
413 ret[i] = std::move(cv::Point3_<num_t>(base[i].x, base[i].y, depth));
414 }
415 return ret;
416}
417template<typename num_t, size_t s>
418std::array<cv::Point3_<num_t>, s> operator+(const std::array<cv::Point3_<num_t>, s>& base, num_t depth) {
419 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
420 std::array<cv::Point3_<num_t>, s> ret;
421 for(size_t i = 0; i < s; i++) {
422 ret[i] = base[i];
423 ret[i].z += depth;
424 }
425}
426template<typename num_t, size_t s>
427void operator+=(std::array<cv::Point3_<num_t>, s>& base, num_t depth) {
428 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
429 for(size_t i = 0; i < s; i++) {
430 base[i].z += depth;
431 }
432}
433template<typename num_t>
434std::vector<cv::Point3_<num_t> > operator+(const std::vector<cv::Point_<num_t> >& base, num_t depth) {
435 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
436 std::vector<cv::Point3_<num_t> > ret(base.size());
437 for(size_t i = 0; i < base.size(); i++) {
438 ret.emplace_back(base[i].x, base[i].y, depth);
439 }
440 return ret;
441}
442template<typename num_t>
443std::vector<cv::Point3_<num_t> > operator+(const std::vector<cv::Point3_<num_t> >& base, num_t depth) {
444 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
445 std::vector<cv::Point3_<num_t> > ret(base.size());
446 for(size_t i = 0; i < base.size(); i++) {
447 ret.emplace_back(base[i].x, base[i].y, base[i].z + depth);
448 }
449 return ret;
450}
451template<typename num_t>
452void operator+=(std::vector<cv::Point3_<num_t>>& base, num_t depth) {
453 static_assert(std::is_arithmetic<num_t>::value, "Template parameter (num_t) must be arithemetic type");
454 for(size_t i = 0; i < base.size(); i++) {
455 base[i].depth += depth;
456 }
457}
void rescale(std::vector< cv::Point_< num_t > > &points, size_t scale)
Definition: vision.h:250
void reorderClockWise(std::vector< cv::Point_< num_t > > &points)
Definition: vision.h:380
bool operator>=(const cv::Size_< num_t > &a, const cv::Size_< num_t > &b)
Definition: vision.h:130
void _rescale(std::vector< cv::Point_< num_t > > &points, size_t scale)
Definition: vision.h:257
cv::Point_< num_t > operator-(const cv::Point_< num_t > &a, const cv::Size_< num_t > &b)
Definition: vision.h:136
bool operator<=(const cv::Size_< num_t > &a, const cv::Size_< num_t > &b)
Definition: vision.h:120
cv::Size_< num_t > distance(const cv::Point_< num_t > &a, const cv::Point_< num_t > &b)
Definition: vision.h:104
void swapIdx(std::vector< t > &vec, size_t idx1, size_t idx2)
Definition: vision.h:96
bool operator<(const cv::Size_< num_t > &a, const cv::Size_< num_t > &b)
Definition: vision.h:115
cv::Size getResolution(cs::VideoMode vm)
Definition: vision.h:38
int sgn(num_t val)
Definition: vision.h:101
cv::Point3_< num_t > findCenter3D(const std::vector< cv::Point3_< num_t > > &contour)
Definition: vision.h:322
void reorderCClockWise(std::vector< cv::Point_< num_t > > &points)
Definition: vision.h:394
bool operator>(const cv::Size_< num_t > &a, const cv::Size_< num_t > &b)
Definition: vision.h:125
static cv::Size_< num_t > operator/(cv::Size_< num_t > input, dnum_t scale)
Definition: vision.h:72
cv::Point_< num_t > findCenter(const std::vector< cv::Point_< num_t > > &contour)
Definition: vision.h:291
cs::VideoMode getJsonVideoMode(const wpi::json &config)
Definition: vision.cpp:32
const auto extend_vector
Definition: vision.h:219
const auto extend_array
Definition: vision.h:217
bool inRange(num_t a, num_t lower, num_t upper)
Definition: vision.h:84
void operator-=(const cv::Point_< num_t > &a, const cv::Size_< num_t > &b)
void reinsert(std::vector< t > &vec, size_t idx)
Definition: vision.h:91
cv::Point_< num_t > operator+(const cv::Point_< num_t > &a, const cv::Size_< num_t > &b)
Definition: vision.h:141
void operator+=(const cv::Point_< num_t > &a, const cv::Size_< num_t > &b)