JeVois  1.8
JeVois Smart Embedded Machine Vision Toolkit
Share this page:
Module.C
Go to the documentation of this file.
1 // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 //
3 // JeVois Smart Embedded Machine Vision Toolkit - Copyright (C) 2016 by Laurent Itti, the University of Southern
4 // California (USC), and iLab at USC. See http://iLab.usc.edu and http://jevois.org for information about this project.
5 //
6 // This file is part of the JeVois Smart Embedded Machine Vision Toolkit. This program is free software; you can
7 // redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software
8 // Foundation, version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 // without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
10 // License for more details. You should have received a copy of the GNU General Public License along with this program;
11 // if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
12 //
13 // Contact information: Laurent Itti - 3641 Watt Way, HNB-07A - Los Angeles, CA 90089-2520 - USA.
14 // Tel: +1 213 740 3527 - itti@pollux.usc.edu - http://iLab.usc.edu - http://jevois.org
15 // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
16 /*! \file */
17 
18 #include <jevois/Core/Module.H>
19 #include <jevois/Core/VideoInput.H>
21 #include <jevois/Core/Engine.H>
25 
26 #include <opencv2/imgproc/imgproc.hpp>
27 
28 #include <cmath>
29 #include <sstream>
30 #include <iomanip>
31 
32 // ####################################################################################################
33 jevois::InputFrame::InputFrame(std::shared_ptr<jevois::VideoInput> const & cam, bool turbo) :
34  itsCamera(cam), itsDidGet(false), itsDidDone(false), itsTurbo(turbo)
35 { }
36 
37 // ####################################################################################################
39 {
40  // If itsCamera is invalidated, we have been moved to another object, so do not do anything here:
41  if (itsCamera.get() == nullptr) return;
42 
43  // If we did not yet get(), just end now, camera will drop this frame:
44  if (itsDidGet == false) return;
45 
46  // If we did get() but not done(), signal done now:
47  if (itsDidDone == false) try { itsCamera->done(itsImage); } catch (...) { }
48 }
49 
50 // ####################################################################################################
51 jevois::RawImage const & jevois::InputFrame::get(bool casync) const
52 {
53  itsCamera->get(itsImage);
54  itsDidGet = true;
55  if (casync && itsTurbo) itsImage.buf->sync();
56  return itsImage;
57 }
58 
59 // ####################################################################################################
61 {
62  itsCamera->done(itsImage);
63  itsDidDone = true;
64 }
65 
66 // ####################################################################################################
67 cv::Mat jevois::InputFrame::getCvGRAY(bool casync) const
68 {
69  jevois::RawImage const & rawimg = get(casync);
70  cv::Mat cvimg = jevois::rawimage::convertToCvGray(rawimg);
71  done();
72  return cvimg;
73 }
74 
75 // ####################################################################################################
76 cv::Mat jevois::InputFrame::getCvBGR(bool casync) const
77 {
78  jevois::RawImage const & rawimg = get(casync);
79  cv::Mat cvimg = jevois::rawimage::convertToCvBGR(rawimg);
80  done();
81  return cvimg;
82 }
83 
84 // ####################################################################################################
85 cv::Mat jevois::InputFrame::getCvRGB(bool casync) const
86 {
87  jevois::RawImage const & rawimg = get(casync);
88  cv::Mat cvimg = jevois::rawimage::convertToCvRGB(rawimg);
89  done();
90  return cvimg;
91 }
92 
93 // ####################################################################################################
94 cv::Mat jevois::InputFrame::getCvRGBA(bool casync) const
95 {
96  jevois::RawImage const & rawimg = get(casync);
97  cv::Mat cvimg = jevois::rawimage::convertToCvRGBA(rawimg);
98  done();
99  return cvimg;
100 }
101 
102 // ####################################################################################################
103 // ####################################################################################################
104 jevois::OutputFrame::OutputFrame(std::shared_ptr<jevois::VideoOutput> const & gad, jevois::RawImage * excimg) :
105  itsGadget(gad), itsDidGet(false), itsDidSend(false), itsImagePtrForException(excimg)
106 { }
107 
108 // ####################################################################################################
110 {
111  // If itsGadget is invalidated, we have been moved to another object, so do not do anything here:
112  if (itsGadget.get() == nullptr) return;
113 
114  // If we did not get(), just end now:
115  if (itsDidGet == false) return;
116 
117  // If Engine gave us a non-zero image pointer for exceptions, and we did get(), pass down the buffer we did get, so
118  // that Engine can write exception text into it, unless it is too late (exception occurred after send()) or too early
119  // (before get()), in which case Engine will get its own buffer:
120  if (itsImagePtrForException)
121  {
122  if (itsDidSend == false) { *itsImagePtrForException = itsImage; }
123  // Engine will be responsible for the final send()
124  }
125  else
126  {
127  // If we did get() but not send(), send now (the image will likely contain garbage):
128  if (itsDidSend == false) try { itsGadget->send(itsImage); } catch (...) { }
129  }
130 }
131 
132 // ####################################################################################################
134 {
135  itsGadget->get(itsImage);
136  itsDidGet = true;
137  return itsImage;
138 }
139 
140 // ####################################################################################################
142 {
143  itsGadget->send(itsImage);
144  itsDidSend = true;
145  if (itsImagePtrForException) itsImagePtrForException->invalidate();
146 }
147 
148 // ####################################################################################################
149 void jevois::OutputFrame::sendCv(cv::Mat const & img, int quality) const
150 {
151  switch(img.type())
152  {
153  case CV_8UC3: sendScaledCvBGR(img, quality); break;
154  case CV_8UC1: sendScaledCvGRAY(img, quality); break;
155  case CV_8UC4: sendScaledCvRGBA(img, quality); break;
156  default: LFATAL("cv::Mat of type " << cvtypestr(img.type()) << " not supported.");
157  }
158 }
159 
160 // ####################################################################################################
161 void jevois::OutputFrame::sendCvGRAY(cv::Mat const & img, int quality) const
162 {
163  jevois::RawImage rawimg = get();
164  jevois::rawimage::convertCvGRAYtoRawImage(img, rawimg, quality);
165  send();
166 }
167 
168 // ####################################################################################################
169 void jevois::OutputFrame::sendCvBGR(cv::Mat const & img, int quality) const
170 {
171  jevois::RawImage rawimg = get();
172  jevois::rawimage::convertCvBGRtoRawImage(img, rawimg, quality);
173  send();
174 }
175 // ####################################################################################################
176 void jevois::OutputFrame::sendCvRGB(cv::Mat const & img, int quality) const
177 {
178  jevois::RawImage rawimg = get();
179  jevois::rawimage::convertCvRGBtoRawImage(img, rawimg, quality);
180  send();
181 }
182 
183 // ####################################################################################################
184 void jevois::OutputFrame::sendCvRGBA(cv::Mat const & img, int quality) const
185 {
186  jevois::RawImage rawimg = get();
187  jevois::rawimage::convertCvRGBAtoRawImage(img, rawimg, quality);
188  send();
189 }
190 
191 
192 
193 
194 
195 // ####################################################################################################
196 void jevois::OutputFrame::sendScaledCvGRAY(cv::Mat const & img, int quality) const
197 {
198  jevois::RawImage rawimg = get();
200  rawimg, quality);
201  send();
202 }
203 
204 // ####################################################################################################
205 void jevois::OutputFrame::sendScaledCvBGR(cv::Mat const & img, int quality) const
206 {
207  jevois::RawImage rawimg = get();
209  rawimg, quality);
210  send();
211 }
212 // ####################################################################################################
213 void jevois::OutputFrame::sendScaledCvRGB(cv::Mat const & img, int quality) const
214 {
215  jevois::RawImage rawimg = get();
217  rawimg, quality);
218  send();
219 }
220 
221 // ####################################################################################################
222 void jevois::OutputFrame::sendScaledCvRGBA(cv::Mat const & img, int quality) const
223 {
224  jevois::RawImage rawimg = get();
226  rawimg, quality);
227  send();
228 }
229 
230 // ####################################################################################################
231 // ####################################################################################################
232 jevois::Module::Module(std::string const & instance) :
233  jevois::Component(instance)
234 { }
235 
236 // ####################################################################################################
238 { }
239 
240 // ####################################################################################################
241 void jevois::Module::process(InputFrame && JEVOIS_UNUSED_PARAM(inframe), OutputFrame && JEVOIS_UNUSED_PARAM(outframe))
242 { LFATAL("Not implemented in this module"); }
243 
244 // ####################################################################################################
245 void jevois::Module::process(InputFrame && JEVOIS_UNUSED_PARAM(inframe))
246 { LFATAL("Not implemented in this module"); }
247 
248 // ####################################################################################################
249 void jevois::Module::sendSerial(std::string const & str)
250 {
251  jevois::Engine * e = dynamic_cast<jevois::Engine *>(itsParent);
252  if (e == nullptr) LFATAL("My parent is not Engine -- CANNOT SEND SERIAL");
253 
254  e->sendSerial(str);
255 }
256 
257 // ####################################################################################################
258 void jevois::Module::parseSerial(std::string const & str,
259  std::shared_ptr<jevois::UserInterface> JEVOIS_UNUSED_PARAM(s))
260 { throw std::runtime_error("Unsupported command [" + str + ']'); }
261 
262 // ####################################################################################################
263 void jevois::Module::supportedCommands(std::ostream & os)
264 { os << "None" << std::endl; }
265 
266 // ####################################################################################################
268 {
269  jevois::Engine * e = dynamic_cast<jevois::Engine *>(itsParent);
270  if (e == nullptr) LFATAL("My parent is not Engine -- CANNOT GET FRAME NUMBER");
271 
272  return e->frameNum();
273 }
274 
275 // ####################################################################################################
276 // ####################################################################################################
277 jevois::StdModule::StdModule(std::string const & instance) :
278  jevois::Module(instance)
279 { }
280 
281 // ####################################################################################################
283 { }
284 
285 // ####################################################################################################
286 std::string jevois::StdModule::getStamp() const
287 {
288  std::string ret;
289 
290  switch(serstamp::get())
291  {
292  case jevois::module::SerStamp::None:
293  break;
294 
295  case jevois::module::SerStamp::Frame:
296  ret = std::to_string(frameNum());
297  break;
298 
299  case jevois::module::SerStamp::Time:
300  {
301  std::time_t t = std::time(nullptr); char str[100];
302  std::strftime(str, sizeof(str), "%T", std::localtime(&t));
303  ret = std::string(str);
304  }
305  break;
306 
307  case jevois::module::SerStamp::FrameTime:
308  {
309  std::time_t t = std::time(nullptr); char str[100];
310  std::strftime(str, sizeof(str), "%T", std::localtime(&t));
311  ret = std::to_string(frameNum()) + '/' + std::string(str);
312  }
313  break;
314 
315  case jevois::module::SerStamp::FrameDateTime:
316  {
317  std::time_t t = std::time(nullptr); char str[100];
318  std::strftime(str, sizeof(str), "%F/%T", std::localtime(&t));
319  ret = std::to_string(frameNum()) + '/' + std::string(str);
320  }
321  break;
322  }
323 
324  if (ret.empty() == false) ret += ' ';
325  return ret;
326 }
327 
328 // ####################################################################################################
329 void jevois::StdModule::sendSerialImg1Dx(unsigned int camw, float x, float size, std::string const & id,
330  std::string const & extra)
331 {
332  // Normalize the coordinate and size using the given precision to do rounding:
333  float const eps = std::pow(10.0F, -float(serprec::get()));
334 
335  jevois::coords::imgToStdX(x, camw, eps);
336  float dummy = 0.0F; jevois::coords::imgToStdSize(size, dummy, camw, 100, eps);
337 
338  // Delegate:
339  sendSerialStd1Dx(x, size, id, extra);
340 }
341 
342 // ####################################################################################################
343 void jevois::StdModule::sendSerialStd1Dx(float x, float size, std::string const & id, std::string const & extra)
344 {
345  // Build the message depending on desired style:
346  std::ostringstream oss; oss << std::fixed << std::setprecision(serprec::get());
347 
348  // Prepend frame/date/time as possibly requested by parameter serstamp:
349  oss << getStamp();
350 
351  // Format the message depending on parameter serstyle:
352  switch (serstyle::get())
353  {
354  case jevois::module::SerStyle::Terse:
355  oss << "T1 " << x;
356  break;
357 
358  case jevois::module::SerStyle::Normal:
359  oss << "N1 ";
360  if (id.empty()) oss << "unknown "; else oss << jevois::replaceWhitespace(id) << ' ';
361  oss << x << ' ' << size;
362  break;
363 
364  case jevois::module::SerStyle::Detail:
365  case jevois::module::SerStyle::Fine:
366  oss << "D1 ";
367  if (id.empty()) oss << "unknown "; else oss << jevois::replaceWhitespace(id) << ' ';
368  oss << x - 0.5F * size << ' ' << x + 0.5F * size;
369  if (extra.empty() == false) oss << ' ' << extra;
370  break;
371  }
372 
373  // Send the message:
374  sendSerial(oss.str());
375 }
376 
377 // ####################################################################################################
378 void jevois::StdModule::sendSerialImg1Dy(unsigned int camh, float y, float size, std::string const & id,
379  std::string const & extra)
380 {
381  // Normalize the coordinate and size using the given precision to do rounding:
382  float const eps = std::pow(10.0F, -float(serprec::get()));
383  jevois::coords::imgToStdY(y, camh, eps);
384  float dummy = 0.0F; jevois::coords::imgToStdSize(dummy, size, 100, camh, eps);
385 
386  // Delegate:
387  sendSerialStd1Dy(y, size, id, extra);
388 }
389 
390 // ####################################################################################################
391 void jevois::StdModule::sendSerialStd1Dy(float y, float size, std::string const & id, std::string const & extra)
392 {
393  // Build the message depending on desired style:
394  std::ostringstream oss; oss << std::fixed << std::setprecision(serprec::get());
395 
396  // Prepend frame/date/time as possibly requested by parameter serstamp:
397  oss << getStamp();
398 
399  // Format the message depending on parameter serstyle:
400  switch (serstyle::get())
401  {
402  case jevois::module::SerStyle::Terse:
403  oss << "T1 " << y;
404  break;
405 
406  case jevois::module::SerStyle::Normal:
407  oss << "N1 ";
408  if (id.empty()) oss << "unknown "; else oss << jevois::replaceWhitespace(id) << ' ';
409  oss << y << ' ' << size;
410  break;
411 
412  case jevois::module::SerStyle::Detail:
413  case jevois::module::SerStyle::Fine:
414  oss << "D1 ";
415  if (id.empty()) oss << "unknown "; else oss << jevois::replaceWhitespace(id) << ' ';
416  oss << y - 0.5F * size << ' ' << y + 0.5F * size;
417  if (extra.empty() == false) oss << ' ' << extra;
418  break;
419  }
420 
421  // Send the message:
422  sendSerial(oss.str());
423 }
424 
425 // ####################################################################################################
426 void jevois::StdModule::sendSerialImg2D(unsigned int camw, unsigned int camh, float x, float y, float w, float h,
427  std::string const & id, std::string const & extra)
428 {
429  // Normalize the coordinates and sizes using the given precision to do rounding:
430  float const eps = std::pow(10.0F, -float(serprec::get()));
431 
432  jevois::coords::imgToStd(x, y, camw, camh, eps);
433  jevois::coords::imgToStdSize(w, h, camw, camh, eps);
434 
435  // Delegate:
436  sendSerialStd2D(x, y, w, h, id, extra);
437 }
438 // ####################################################################################################
439 void jevois::StdModule::sendSerialStd2D(float x, float y, float w, float h, std::string const & id,
440  std::string const & extra)
441 {
442  // Build the message depending on desired style:
443  std::ostringstream oss; oss << std::fixed << std::setprecision(serprec::get());
444 
445  // Prepend frame/date/time as possibly requested by parameter serstamp:
446  oss << getStamp();
447 
448  // Format the message depending on parameter serstyle:
449  switch (serstyle::get())
450  {
451  case jevois::module::SerStyle::Terse:
452  oss << "T2 " << x << ' ' << y;
453  break;
454 
455  case jevois::module::SerStyle::Normal:
456  oss << "N2 ";
457  if (id.empty()) oss << "unknown "; else oss << jevois::replaceWhitespace(id) << ' ';
458  oss << x << ' ' << y << ' ' << w << ' ' << h;
459  break;
460 
461  case jevois::module::SerStyle::Detail:
462  oss << "D2 ";
463  if (id.empty()) oss << "unknown "; else oss << jevois::replaceWhitespace(id) << ' ';
464  oss << x - 0.5F * w << ' ' << y - 0.5F * h << ' ';
465  oss << x + 0.5F * w << ' ' << y - 0.5F * h << ' ';
466  oss << x + 0.5F * w << ' ' << y + 0.5F * h << ' ';
467  oss << x + 0.5F * w << ' ' << y - 0.5F * h;
468  if (extra.empty() == false) oss << ' ' << extra;
469  break;
470 
471  case jevois::module::SerStyle::Fine:
472  oss << "F2 ";
473  if (id.empty()) oss << "unknown "; else oss << jevois::replaceWhitespace(id) << ' ';
474  oss << 4 << ' '; // number of vertices
475  oss << x - 0.5F * w << ' ' << y - 0.5F * h << ' ';
476  oss << x + 0.5F * w << ' ' << y - 0.5F * h << ' ';
477  oss << x + 0.5F * w << ' ' << y + 0.5F * h << ' ';
478  oss << x + 0.5F * w << ' ' << y - 0.5F * h;
479  if (extra.empty() == false) oss << ' ' << extra;
480  break;
481  }
482 
483  // Send the message:
484  sendSerial(oss.str());
485 }
486 
487 // ####################################################################################################
488 template <typename T>
489 void jevois::StdModule::sendSerialContour2D(unsigned int camw, unsigned int camh, std::vector<cv::Point_<T> > points,
490  std::string const & id, std::string const & extra)
491 {
492  // Format the message depending on parameter serstyle:
493  switch (serstyle::get())
494  {
495  case jevois::module::SerStyle::Terse:
496  {
497  // Compute center of gravity:
498  float cx = 0.0F, cy = 0.0F;
499  for (cv::Point const & p : points) { cx += p.x; cy += p.y; }
500  if (points.size()) { cx /= points.size(); cy /= points.size(); }
501  sendSerialImg2D(camw, camh, cx, cy, 0.0F, 0.0F, id, extra);
502  }
503  break;
504 
505  case jevois::module::SerStyle::Normal:
506  {
507  // Compute upright bounding rectangle:
508  cv::Rect r = cv::boundingRect(points);
509  sendSerialImg2D(camw, camh, r.x + 0.5F * r.width, r.y + 0.5F * r.height, r.width, r.height, id, extra);
510  }
511  break;
512 
513  case jevois::module::SerStyle::Detail:
514  {
515  // Compute minimal rotated rectangle enclosing the points:
516  cv::RotatedRect r = cv::minAreaRect(points);
517 
518  // Build the message:
519  unsigned int const prec = serprec::get(); float const eps = std::pow(10.0F, -float(prec));
520  std::ostringstream oss; oss << std::fixed << std::setprecision(prec);
521 
522  // Prepend frame/date/time as possibly requested by parameter serstamp:
523  oss << getStamp();
524 
525  // Now the rest of the message:
526  oss << "D2 ";
527  if (id.empty()) oss << "unknown "; else oss << jevois::replaceWhitespace(id) << ' ';
528  cv::Point2f corners[4];
529  r.points(corners);
530 
531  oss << 4; // number of vertices
532 
533  for (int i = 0; i < 4; ++i)
534  {
535  float x = corners[i].x, y = corners[i].y;
536  jevois::coords::imgToStd(x, y, camw, camh, eps);
537  oss << ' ' << x << ' ' << y;
538  }
539  if (extra.empty() == false) oss << ' ' << extra;
540 
541  // Send the message:
542  sendSerial(oss.str());
543  }
544  break;
545 
546  case jevois::module::SerStyle::Fine:
547  {
548  // Build the message:
549  unsigned int const prec = serprec::get(); float const eps = std::pow(10.0F, -float(prec));
550  std::ostringstream oss; oss << std::fixed << std::setprecision(prec);
551 
552  // Prepend frame/date/time as possibly requested by parameter serstamp:
553  oss << getStamp();
554 
555  // Now the rest of the message:
556  oss << "F2 ";
557  if (id.empty()) oss << "unknown "; else oss << jevois::replaceWhitespace(id) << ' ';
558  oss << points.size(); // number of vertices
559 
560  for (cv::Point const & p : points)
561  {
562  float x = p.x, y = p.y;
563  jevois::coords::imgToStd(x, y, camw, camh, eps);
564  oss << ' ' << x << ' ' << y;
565  }
566  if (extra.empty() == false) oss << ' ' << extra;
567 
568  // Send the message:
569  sendSerial(oss.str());
570  }
571  break;
572  }
573 }
574 
575 // Compile in explicit template instantiations:
576 namespace jevois
577 {
578  template
579  void StdModule::sendSerialContour2D(unsigned int camw, unsigned int camh, std::vector<cv::Point_<int> > points,
580  std::string const & id, std::string const & extra);
581  template
582  void StdModule::sendSerialContour2D(unsigned int camw, unsigned int camh, std::vector<cv::Point_<float> > points,
583  std::string const & id, std::string const & extra);
584  template
585  void StdModule::sendSerialContour2D(unsigned int camw, unsigned int camh, std::vector<cv::Point_<double> > points,
586  std::string const & id, std::string const & extra);
587 }
588 
589 // ####################################################################################################
590 void jevois::StdModule::sendSerialStd3D(float x, float y, float z, float w, float h, float d,
591  float q1, float q2, float q3, float q4,
592  std::string const & id, std::string const & extra)
593 {
594  // Build the message depending on desired style:
595  std::ostringstream oss; oss << std::fixed << std::setprecision(serprec::get());
596 
597  // Prepend frame/date/time as possibly requested by parameter serstamp:
598  oss << getStamp();
599 
600  // Format the message depending on parameter serstyle:
601  switch (serstyle::get())
602  {
603  case jevois::module::SerStyle::Terse:
604  oss << "T3 " << x << ' ' << y << ' ' << z;
605  break;
606 
607  case jevois::module::SerStyle::Normal:
608  oss << "N3 ";
609  if (id.empty()) oss << "unknown "; else oss << jevois::replaceWhitespace(id) << ' ';
610  oss << x << ' ' << y << ' ' << z << ' ' << w << ' ' << h << ' ' << d;
611  break;
612 
613  case jevois::module::SerStyle::Detail:
614  oss << "D3 ";
615  if (id.empty()) oss << "unknown "; else oss << jevois::replaceWhitespace(id) << ' ';
616  oss << x << ' ' << y << ' ' << z << ' ' << w << ' ' << h << ' ' << d << ' '
617  << q1 << ' ' << q2 << ' ' << q3 << ' ' << q4;
618  if (extra.empty() == false) oss << ' ' << extra;
619  break;
620 
621  case jevois::module::SerStyle::Fine:
622  oss << "F3 ";
623  if (id.empty()) oss << "unknown "; else oss << jevois::replaceWhitespace(id) << ' ';
624  oss << 8 << ' '; // number of vertices
625  oss << x - 0.5F * w << ' ' << y - 0.5F * h << ' ' << z - 0.5F * d << ' ';
626  oss << x + 0.5F * w << ' ' << y - 0.5F * h << ' ' << z - 0.5F * d << ' ';
627  oss << x + 0.5F * w << ' ' << y + 0.5F * h << ' ' << z - 0.5F * d << ' ';
628  oss << x + 0.5F * w << ' ' << y - 0.5F * h << ' ' << z - 0.5F * d << ' ';
629  oss << x - 0.5F * w << ' ' << y - 0.5F * h << ' ' << z + 0.5F * d << ' ';
630  oss << x + 0.5F * w << ' ' << y - 0.5F * h << ' ' << z + 0.5F * d << ' ';
631  oss << x + 0.5F * w << ' ' << y + 0.5F * h << ' ' << z + 0.5F * d << ' ';
632  oss << x + 0.5F * w << ' ' << y - 0.5F * h << ' ' << z + 0.5F * d << ' ';
633  if (extra.empty() == false) oss << ' ' << extra;
634  break;
635  }
636 
637  // Send the message:
638  sendSerial(oss.str());
639 }
640 
641 // ####################################################################################################
642 void jevois::StdModule::sendSerialStd3D(std::vector<cv::Point3f> points, std::string const & id,
643  std::string const & extra)
644 {
645  // Format the message depending on parameter serstyle:
646  switch (serstyle::get())
647  {
648  case jevois::module::SerStyle::Terse:
649  {
650  // Compute center of gravity:
651  cv::Point3f cg(0.0F, 0.0F, 0.0F);
652  for (cv::Point3f const & p : points) cg += p;
653  if (points.size()) { cg.x /= points.size(); cg.y /= points.size(); cg.z /= points.size(); }
654  sendSerialStd3D(cg.x, cg.y, cg.z, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, 0.0F, id, extra);
655  }
656  break;
657 
658  case jevois::module::SerStyle::Normal:
659  {
660  // Compute upright bounding parallelepiped:
661  cv::Point3f cg(0.0F, 0.0F, 0.0F), pmin(1e30F, 1e30F, 1e30F), pmax(-1e30F, -1e30F, -1e30F);
662  for (cv::Point3f const & p : points)
663  {
664  cg += p;
665  if (p.x < pmin.x) pmin.x = p.x;
666  if (p.y < pmin.y) pmin.y = p.y;
667  if (p.z < pmin.z) pmin.z = p.z;
668  if (p.x > pmax.x) pmax.x = p.x;
669  if (p.y > pmax.y) pmax.y = p.y;
670  if (p.z > pmax.z) pmax.z = p.z;
671  }
672  if (points.size()) { cg.x /= points.size(); cg.y /= points.size(); cg.z /= points.size(); }
673  sendSerialStd3D(cg.x, cg.y, cg.z, pmax.x - pmin.x, pmax.y - pmin.y, pmax.z - pmin.z, 0.0F, 0.0F, 0.0F, 0.0F,
674  id, extra);
675  }
676  break;
677 
678  case jevois::module::SerStyle::Detail:
679  {
680  // Compute upright bounding parallelepiped:
681  cv::Point3f cg(0.0F, 0.0F, 0.0F), pmin(1e30F, 1e30F, 1e30F), pmax(-1e30F, -1e30F, -1e30F);
682  for (cv::Point3f const & p : points)
683  {
684  cg += p;
685  if (p.x < pmin.x) pmin.x = p.x;
686  if (p.y < pmin.y) pmin.y = p.y;
687  if (p.z < pmin.z) pmin.z = p.z;
688  if (p.x > pmax.x) pmax.x = p.x;
689  if (p.y > pmax.y) pmax.y = p.y;
690  if (p.z > pmax.z) pmax.z = p.z;
691  }
692  if (points.size()) { cg.x /= points.size(); cg.y /= points.size(); cg.z /= points.size(); }
693  // FIXME what should we send for the quaternion?
694  sendSerialStd3D(cg.x, cg.y, cg.z, pmax.x - pmin.x, pmax.y - pmin.y, pmax.z - pmin.z, 0.0F, 0.0F, 0.0F, 1.0F,
695  id, extra);
696  }
697  break;
698 
699  case jevois::module::SerStyle::Fine:
700  {
701  // Build the message:
702  unsigned int const prec = serprec::get();
703  std::ostringstream oss; oss << std::fixed << std::setprecision(prec);
704 
705  // Prepend frame/date/time as possibly requested by parameter serstamp:
706  oss << getStamp();
707 
708  // Now the rest of the message:
709  oss << "F3 ";
710  if (id.empty()) oss << "unknown "; else oss << jevois::replaceWhitespace(id) << ' ';
711  oss << points.size(); // number of vertices
712 
713  for (cv::Point3f const & p : points) oss << ' ' << p.x << ' ' << p.y << ' ' << p.z;
714  if (extra.empty() == false) oss << ' ' << extra;
715 
716  // Send the message:
717  sendSerial(oss.str());
718  }
719  break;
720  }
721 }
cv::Mat convertToCvRGB(RawImage const &src)
Convert RawImage to OpenCV doing color conversion from any RawImage source pixel to OpenCV RGB byte...
Definition: RawImageOps.C:302
cv::Mat convertToCvRGBA(RawImage const &src)
Convert RawImage to OpenCV doing color conversion from any RawImage source pixel to OpenCV RGB-A byte...
Definition: RawImageOps.C:325
void sendSerialContour2D(unsigned int camw, unsigned int camh, std::vector< cv::Point_< T > > points, std::string const &id="", std::string const &extra="")
Send standardized 2D message for polygons in image coordinates.
Definition: Module.C:489
void imgToStdY(float &y, unsigned int const height, float const eps=0.1F)
Transform Y coordinate in-place from camera to standardized, using given image width and height...
Definition: Coordinates.C:43
Exception-safe wrapper around a raw camera input frame.
Definition: Module.H:56
void imgToStd(float &x, float &y, RawImage const &camimg, float const eps=0.1F)
Transform coordinates in-place from camera to standardized, using a RawImage to establish image size...
Definition: Coordinates.C:22
cv::Mat convertToCvBGR(RawImage const &src)
Convert RawImage to OpenCV doing color conversion from any RawImage source pixel to OpenCV BGR byte...
Definition: RawImageOps.C:279
unsigned int height
Image height in pixels.
Definition: RawImage.H:146
std::string cvtypestr(unsigned int cvtype)
Convert cv::Mat::type() code to to a string (e.g., CV_8UC1, CV_32SC3, etc)
Definition: Utils.C:52
void sendSerialStd1Dx(float x, float size=0.0F, std::string const &id="", std::string const &extra="")
Send standardized 1D message for a standardized X coordinate.
Definition: Module.C:343
void send(RawImage const &img) override
Send an image out over USB to the host computer.
Definition: Gadget.C:852
cv::Mat getCvRGBA(bool casync=false) const
Shorthand to get the input image as a RGBA cv::Mat and release the raw buffer.
Definition: Module.C:94
void sendScaledCvRGB(cv::Mat const &img, int quality=75) const
Shorthand to send a RGB cv::Mat after converting it to the current output format. ...
Definition: Module.C:213
void sendScaledCvBGR(cv::Mat const &img, int quality=75) const
Shorthand to send a BGR cv::Mat after converting it to the current output format. ...
Definition: Module.C:205
void sendCvRGBA(cv::Mat const &img, int quality=75) const
Shorthand to send a RGBA cv::Mat after converting it to the current output format.
Definition: Module.C:184
void send() const
Send an image out over USB to the host computer.
Definition: Module.C:141
Module(std::string const &instance)
Constructor.
Definition: Module.C:232
void sendCvRGB(cv::Mat const &img, int quality=75) const
Shorthand to send a RGB cv::Mat after converting it to the current output format. ...
Definition: Module.C:176
void sendCv(cv::Mat const &img, int quality=75) const
Shorthand to send a cv::Mat after converting / scaling it to the current output format.
Definition: Module.C:149
RawImage const & get(bool casync=false) const
Get the next captured camera image.
Definition: Module.C:51
void sendCvGRAY(cv::Mat const &img, int quality=75) const
Shorthand to send a GRAY cv::Mat after converting it to the current output format.
Definition: Module.C:161
InputFrame(InputFrame &&other)=default
Move constructor.
virtual void supportedCommands(std::ostream &os)
Human-readable description of this Module&#39;s supported custom commands.
Definition: Module.C:263
void sendSerial(std::string const &str, bool islog=false)
Send a string to all serial ports.
Definition: Engine.C:859
std::string replaceWhitespace(std::string const &str, char rep='_')
Replace white space characters in a string with underscore (default) or another characters.
Definition: Utils.C:172
void sendScaledCvRGBA(cv::Mat const &img, int quality=75) const
Shorthand to send a RGBA cv::Mat after converting it to the current output format.
Definition: Module.C:222
size_t frameNum() const
Get frame number.
Definition: Engine.C:897
void sendCvBGR(cv::Mat const &img, int quality=75) const
Shorthand to send a BGR cv::Mat after converting it to the current output format. ...
Definition: Module.C:169
A component of a model hierarchy.
Definition: Component.H:177
virtual void process(InputFrame &&inframe, OutputFrame &&outframe)
Processing function, version that receives a frame from camera and sends a frame out over USB...
StdModule(std::string const &instance)
Constructor.
Definition: Module.C:277
A raw image as coming from a V4L2 Camera and/or being sent out to a USB Gadget.
Definition: RawImage.H:110
cv::Mat getCvRGB(bool casync=false) const
Shorthand to get the input image as a RGB cv::Mat and release the raw buffer.
Definition: Module.C:85
virtual void done(RawImage &img)=0
Indicate that user processing is done with an image previously obtained via get() ...
void sendSerialStd2D(float x, float y, float w=0.0F, float h=0.0F, std::string const &id="", std::string const &extra="")
Send standardized 2D message for standardized coordinates.
Definition: Module.C:439
void sendSerialImg2D(unsigned int camw, unsigned int camh, float x, float y, float w=0.0F, float h=0.0F, std::string const &id="", std::string const &extra="")
Send standardized 2D message for image coordinates.
Definition: Module.C:426
void imgToStdSize(float &w, float &h, unsigned int const width, unsigned int const height, float const eps=0.1F)
Transform size in-place from camera to standardized, using given image width and height.
Definition: Coordinates.C:50
virtual void get(RawImage &img)=0
Get the next captured buffer.
cv::Mat convertToCvGray(RawImage const &src)
Convert RawImage to OpenCV doing color conversion from any RawImage source pixel to OpenCV gray byte...
Definition: RawImageOps.C:245
void convertCvBGRtoRawImage(cv::Mat const &src, RawImage &dst, int quality)
Convert a BGR cv::Mat to RawImage with already-allocated pixels and pixel type.
Definition: RawImageOps.C:1254
void imgToStdX(float &x, unsigned int const width, float const eps=0.1F)
Transform X coordinate in-place from camera to standardized, using given image width and height...
Definition: Coordinates.C:36
virtual void sendSerial(std::string const &str)
Send a string over the &#39;serout&#39; serial port.
Definition: Module.C:249
void sendSerialImg1Dy(unsigned int camh, float y, float size=0.0F, std::string const &id="", std::string const &extra="")
Send standardized 1D message for an Y image coordinate.
Definition: Module.C:378
cv::Mat getCvGRAY(bool casync=false) const
Shorthand to get the input image as a GRAY cv::Mat and release the raw buffer.
Definition: Module.C:67
void sendSerialStd3D(float x, float y, float z, float w=0.0F, float h=0.0F, float d=0.0F, float q1=0.0F, float q2=0.0F, float q3=0.0f, float q4=0.0F, std::string const &id="", std::string const &extra="")
Send standardized 3D message.
Definition: Module.C:590
void sendSerialImg1Dx(unsigned int camw, float x, float size=0.0F, std::string const &id="", std::string const &extra="")
Send standardized 1D message for an X image coordinate.
Definition: Module.C:329
#define LFATAL(msg)
Convenience macro for users to print out console or syslog messages, FATAL level. ...
Definition: Log.H:212
virtual ~StdModule()
Virtual destructor for safe inheritance.
Definition: Module.C:282
Prepend standardized serial messages with a frame time
Definition: Module.H:433
void convertCvRGBAtoRawImage(cv::Mat const &src, RawImage &dst, int quality)
Convert an RGBA cv::Mat to RawImage with already-allocated pixels and pixel type. ...
Definition: RawImageOps.C:1323
JeVois processing engine - gets images from camera sensor, processes them, and sends results over USB...
Definition: Engine.H:257
std::string to_string(T const &val)
Convert from type to string.
Definition: UtilsImpl.H:58
std::string getStamp() const
Get a string with the frame/date/time stamp in it, depending on serstamp parameter.
Definition: Module.C:286
void convertCvGRAYtoRawImage(cv::Mat const &src, RawImage &dst, int quality)
Convert a Gray cv::Mat to RawImage with already-allocated pixels and pixel type.
Definition: RawImageOps.C:1344
virtual void parseSerial(std::string const &str, std::shared_ptr< UserInterface > s)
Receive a string from a serial port which contains a user command.
Definition: Module.C:258
Virtual base class for a vision processing module.
Definition: Module.H:335
void sendScaledCvGRAY(cv::Mat const &img, int quality=75) const
Shorthand to send a GRAY cv::Mat after converting it to the current output format.
Definition: Module.C:196
void sendSerialStd1Dy(float y, float size=0.0F, std::string const &id="", std::string const &extra="")
Send standardized 1D message for a standardized Y coordinate.
Definition: Module.C:391
Exception-safe wrapper around a raw image to be sent over USB.
Definition: Module.H:144
~InputFrame()
Destructor, returns the buffers to the driver as needed.
Definition: Module.C:38
RawImage const & get() const
Get a pre-allocated image so that we can fill the pixel data and later send out over USB using send()...
Definition: Module.C:133
cv::Mat getCvBGR(bool casync=false) const
Shorthand to get the input image as a BGR cv::Mat and release the raw buffer.
Definition: Module.C:76
void done() const
Indicate that user processing is done with the image previously obtained via get() ...
Definition: Module.C:60
cv::Mat rescaleCv(cv::Mat const &img, cv::Size const &newdims)
Rescale an OpenCV image, choosing the right kind of interpolation.
Definition: RawImageOps.C:1407
unsigned int width
Image width in pixels.
Definition: RawImage.H:145
~OutputFrame()
Destructor, returns the buffers to the driver as needed.
Definition: Module.C:109
virtual ~Module()
Virtual destructor for safe inheritance.
Definition: Module.C:237
void convertCvRGBtoRawImage(cv::Mat const &src, RawImage &dst, int quality)
Convert a RGB cv::Mat to RawImage with already-allocated pixels and pixel type.
Definition: RawImageOps.C:1276
size_t frameNum() const
Get frame number from the Engine.
Definition: Module.C:267