YARP
Yet Another Robot Platform
FakeFrameGrabber.cpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3  * SPDX-FileCopyrightText: 2006-2010 RobotCub Consortium
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "FakeFrameGrabber.h"
8 
9 #include <yarp/os/LogComponent.h>
10 #include <yarp/os/LogStream.h>
11 #include <yarp/sig/ImageDraw.h>
12 
13 #include <cstdio>
14 #include <thread>
15 #include <random>
16 
17 using namespace yarp::os;
18 using namespace yarp::dev;
19 using namespace yarp::sig;
20 using namespace yarp::sig::draw;
21 
22 namespace {
23 YARP_LOG_COMPONENT(FAKEFRAMEGRABBER, "yarp.device.fakeFrameGrabber")
24 constexpr yarp::conf::vocab32_t VOCAB_LINE = yarp::os::createVocab32('l','i','n','e');
25 constexpr yarp::conf::vocab32_t VOCAB_BALL = yarp::os::createVocab32('b','a','l','l');
26 constexpr yarp::conf::vocab32_t VOCAB_GRID = yarp::os::createVocab32('g','r','i','d');
27 constexpr yarp::conf::vocab32_t VOCAB_RAND = yarp::os::createVocab32('r','a','n','d');
28 constexpr yarp::conf::vocab32_t VOCAB_NONE = yarp::os::createVocab32('n','o','n','e');
29 constexpr yarp::conf::vocab32_t VOCAB_GRID_MULTISIZE = yarp::os::createVocab32('s','i','z','e');
30 constexpr yarp::conf::vocab32_t VOCAB_TIMETEXT = yarp::os::createVocab32('t','i','m','e');
31 
32 //the following data are used by [time] test
33 constexpr char num[12][16]
34 {
35  // '0'
36  "***"
37  "* *"
38  "* *"
39  "* *"
40  "***",
41 
42  // '1'
43  " * "
44  " * "
45  " * "
46  " * "
47  " * ",
48 
49  // '2'
50  "***"
51  " *"
52  "***"
53  "* "
54  "***",
55 
56  // '3'
57  "***"
58  " *"
59  "***"
60  " *"
61  "***",
62 
63  // '4'
64  "* *"
65  "* *"
66  "***"
67  " *"
68  " *",
69 
70  // '5'
71  "***"
72  "* "
73  "***"
74  " *"
75  "***",
76 
77  // '6'
78  "***"
79  "* "
80  "***"
81  "* *"
82  "***",
83 
84  // '7'
85  "***"
86  " *"
87  " *"
88  " *"
89  " *",
90 
91  // '8'
92  "***"
93  "* *"
94  "***"
95  "* *"
96  "***",
97 
98  // '9'
99  "***"
100  "* *"
101  "***"
102  " *"
103  "***",
104 
105  // ' '
106  " "
107  " "
108  " "
109  " "
110  " ",
111 
112  // '.'
113  " "
114  " "
115  " "
116  " **"
117  " **",
118 };
119 constexpr size_t num_width = 3;
120 constexpr size_t num_height = 5;
121 
122 }
123 
125 {
126  yarp::os::Bottle command;
127  yarp::os::Bottle reply;
128  bool ok = command.read(connection);
129  if (!ok) {
130  return false;
131  }
132  reply.clear();
133 
134  if (command.get(0).asString()=="help")
135  {
136  reply.addVocab32("many");
137  reply.addString("set_mode <mode>");
138  reply.addString("set_image <file_name>/off");
139  reply.addString("available modes: ball, line, grid, size, rand, none, time");
140  reply.addString("set_topIsLow on/off");
141  reply.addString("set_noise on/off");
142  reply.addString("set_snr <snr>");
143  reply.addString("");
144  }
145  else if (command.get(0).asString() == "set_mode")
146  {
147  mode= command.get(1).asVocab32();
148  reply.addString("ack");
149  }
150  else if (command.get(0).asString() == "set_image")
151  {
152  if (command.get(1).asString() == "off")
153  {
154  have_bg=false;
155  reply.addString("ack");
156  }
157  else
158  {
159  if (yarp::sig::file::read(background, command.get(1).asString()))
160  {
161  w = background.width();
162  h = background.height();
163  have_bg = true;
164  reply.addString("ack");
165  }
166  else
167  {
168  have_bg = false;
169  reply.addString("err");
170  }
171  }
172  }
173  else if (command.get(0).asString() == "set_topIsLow")
174  {
175  if (command.get(1).asString() == "off") {
176  topIsLow = false;
177  reply.addString("ack");
178  } else if (command.get(1).asString() == "on") {
179  topIsLow = true;
180  reply.addString("ack");
181  } else {
182  reply.addString("err");
183  }
184  }
185  else if (command.get(0).asString() == "set_noise")
186  {
187  if (command.get(1).asString() == "off") {
188  add_noise = false;
189  reply.addString("ack");
190  } else if (command.get(1).asString() == "on") {
191  add_noise = true;
192  reply.addString("ack");
193  } else {
194  reply.addString("err");
195  }
196  }
197  else if (command.get(0).asString() == "set_snr")
198  {
199  snr = yarp::conf::clamp(command.get(1).asFloat64(), 0.0, 1.0);
200  reply.addString("ack");
201  }
202  else
203  {
204  reply.addString("Unknown command. Type 'help'.");
205  }
206 
207  yarp::os::ConnectionWriter* returnToSender = connection.getWriter();
208  if (returnToSender != nullptr)
209  {
210  reply.write(*returnToSender);
211  }
212 
213  return true;
214 }
215 
217  stop();
218  m_rpcPort.close();
219  return true;
220 }
221 
223  m_rpcPortName = config.check("fakeFrameGrabber_rpc_port", yarp::os::Value("/fakeFrameGrabber/rpc"), "rpc port for the fakeFrameGrabber").asString();
224  w = config.check("width",yarp::os::Value(320),
225  "desired width of test image").asInt32();
226  h = config.check("height",yarp::os::Value(240),
227  "desired height of test image").asInt32();
228  horizontalFov=config.check("horizontalFov",Value(1.0),
229  "desired horizontal fov of test image").asFloat64();
230  verticalFov=config.check("verticalFov",Value(2.0),
231  "desired vertical fov of test image").asFloat64();
232  mirror=config.check("mirror",Value(false),
233  "mirroring disabled by default").asBool();
234  syncro=config.check("syncro",Value(false),
235  "syncronize producer and consumer, so that all images are used once and only once").asBool();
236  topIsLow=config.check("topIsLow",Value(true),
237  "explicitly set the topIsLow field in the images").asBool();
238  intrinsic.put("physFocalLength",config.check("physFocalLength",Value(3.0),"Physical focal length of the fakeFrameGrabber").asFloat64());
239  intrinsic.put("focalLengthX",config.check("focalLengthX",Value(4.0),"Horizontal component of the focal length of the fakeFrameGrabber").asFloat64());
240  intrinsic.put("focalLengthY",config.check("focalLengthY",Value(5.0),"Vertical component of the focal length of the fakeFrameGrabber").asFloat64());
241  intrinsic.put("principalPointX",config.check("principalPointX",Value(6.0),"X coordinate of the principal point of the fakeFrameGrabber").asFloat64());
242  intrinsic.put("principalPointY",config.check("principalPointY",Value(7.0),"Y coordinate of the principal point of the fakeFrameGrabber").asFloat64());
243 
244  Value* retM;
245  retM=Value::makeList("1.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 1.0");
246  intrinsic.put("rectificationMatrix",config.check("rectificationMatrix",*retM,"Matrix that describes the lens' distortion(fake)"));
247  delete retM;
248 
249  intrinsic.put("distortionModel",config.check("distortionModel",Value("FishEye"),"Reference to group of parameters describing the distortion model of the camera").asString());
250  intrinsic.put("k1",config.check("k1",Value(8.0),"Radial distortion coefficient of the lens(fake)").asFloat64());
251  intrinsic.put("k2",config.check("k2",Value(9.0),"Radial distortion coefficient of the lens(fake)").asFloat64());
252  intrinsic.put("k3",config.check("k3",Value(10.0),"Radial distortion coefficient of the lens(fake)").asFloat64());
253  intrinsic.put("t1",config.check("t1",Value(11.0),"Tangential distortion of the lens(fake)").asFloat64());
254  intrinsic.put("t2",config.check("t2",Value(12.0),"Tangential distortion of the lens(fake)").asFloat64());
255  //Only for debug
256  CameraConfig conf1;
257  conf1.height=128;
258  conf1.width=128;
259  conf1.framerate=60.0;
261  configurations.push_back(conf1);
262 
263  CameraConfig conf2;
264  conf2.height=256;
265  conf2.width=256;
266  conf2.framerate=30.0;
268  configurations.push_back(conf2);
269 
270  CameraConfig conf3;
271  conf3.height=512;
272  conf3.width=512;
273  conf3.framerate=15.0;
275  configurations.push_back(conf3);
276 
277  yarp::os::Value *val;
278  if (config.check("freq", val, "rate of test images in Hz")) {
279  freq = val->asFloat64();
280  period = 1/freq;
281  } else if (config.check("period", val,
282  "period of test images in seconds")) {
283  period = val->asFloat64() / 1000.0;
284  if(period<=0) {
285  period =0;
286  freq = -1;
287  }
288  }
289 
290  mode = config.check("mode",
291  yarp::os::Value(VOCAB_LINE, true),
292  "bouncy [ball], scrolly [line], grid [grid], grid multisize [size], random [rand], none [none], time test[time]").asVocab32();
293 
294  if (config.check("src")) {
295  if (!yarp::sig::file::read(background,
296  config.check("src",
297  yarp::os::Value("test.ppm"),
298  "background image to use, if any").asString())) {
299  return false;
300  }
301  if (background.width()>0) {
302  if (config.check("width") || config.check("height")) {
303  yCWarning(FAKEFRAMEGRABBER, "width and height option are ignored when passing a background image");
304  }
305  w = background.width();
306  h = background.height();
307  have_bg = true;
308  }
309  }
310 
311  add_timestamp = config.check("timestamp", "should write the timestamp in the first bytes of the image");
312 
313  add_noise = config.check("noise", "Should add noise to the image (uses snr)");
314 
315  snr = yarp::conf::clamp(config.check("snr",Value(default_snr), "Signal noise ratio ([0.0-1.0] default 0.5)").asFloat64(), 0.0, 1.0);
316 
317  use_bayer = config.check("bayer","should emit bayer test image?");
318  use_mono = config.check("mono","should emit a monochrome image?");
319  use_mono = use_mono||use_bayer;
320 
321  if (freq!=-1) {
322  yCInfo(FAKEFRAMEGRABBER,
323  "Test grabber period %g / freq %g , mode [%s]",
324  period,
325  freq,
326  yarp::os::Vocab32::decode(mode).c_str());
327  } else {
328  yCInfo(FAKEFRAMEGRABBER,
329  "Test grabber period %g / freq [inf], mode [%s]",
330  period,
331  yarp::os::Vocab32::decode(mode).c_str());
332  }
333 
334  bx = w/2;
335  by = h/2;
336 
337  for (auto& buff : buffs) {
338  buff.resize(w, h);
339  buff.zero();
340  }
341 
342  if (!m_rpcPort.open(m_rpcPortName.c_str()))
343  {
344  yCError(FAKEFRAMEGRABBER, "Failed to open port %s", m_rpcPortName.c_str());
345  yCError(FAKEFRAMEGRABBER, "Do you have multiple FakeFrameGrabber devices running?");
346  yCError(FAKEFRAMEGRABBER, "If yes, use the `fakeFrameGrabber_rpc_port` parameter to set a different name for each of them");
347  return false;
348  }
349  m_rpcPort.setReader(*this);
350 
351  start();
352 
353  return true;
354 }
355 
357  double now = yarp::os::Time::now();
358 
359  if (now-prev>1000) {
360  first = now;
361  prev = now;
362  }
363  double dt = period-(now-prev);
364 
365  if (dt>0) {
367  }
368 
369  // this is the controlled instant when we consider the
370  // image as going out
371  prev += period;
372 }
373 
375  return h;
376 }
377 
379  return w;
380 }
381 
383  return h;
384 }
385 
387  return w;
388 }
389 
391  configurations=this->configurations;
392  return true;
393 }
394 
395 bool FakeFrameGrabber::getRgbResolution(int &width, int &height){
396  width=w;
397  height=h;
398  return true;
399 }
400 
401 bool FakeFrameGrabber::setRgbResolution(int width, int height){
402  w=width;
403  h=height;
404  return true;
405 }
406 
407 bool FakeFrameGrabber::getRgbFOV(double &horizontalFov, double &verticalFov){
408  horizontalFov=this->horizontalFov;
409  verticalFov=this->verticalFov;
410  return true;
411 }
412 
413 bool FakeFrameGrabber::setRgbFOV(double horizontalFov, double verticalFov){
414  this->horizontalFov=horizontalFov;
415  this->verticalFov=verticalFov;
416  return true;
417 }
418 
420  intrinsic=this->intrinsic;
421  return true;
422 }
423 
425  mirror=this->mirror;
426  return true;}
427 
429  this->mirror=mirror;
430  return true;
431 }
432 
434 {
435  while (!isStopping()) {
436  for (size_t i = 0; i < 2 && !isStopping(); ++i) {
437  if (!syncro) {
438  std::unique_lock<std::mutex> lk(mutex[i]);
439  createTestImage(buffs[i], buff_ts[i]);
440  timing();
441  lk.unlock();
442 
443  curr_buff_mutex.lock();
444  curr_buff = i;
445  curr_buff_mutex.unlock();
447  } else {
448  std::unique_lock<std::mutex> lk(mutex[i]);
449  img_consumed_cv[i].wait(lk, [&]{ if (img_ready[i]) {img_ready_cv[i].notify_one();} return (isStopping() || img_consumed[i]);});
450  if (isStopping()) {
451  break;
452  }
453  img_ready[i] = false;
454  img_consumed[i] = false;
455  createTestImage(buffs[i], buff_ts[i]);
456  img_ready[i] = true;
457  img_ready_cv[i].notify_all();
458  }
459  }
460  }
461 }
462 
464 {
465  // Unlock any blocked thread.
466  if (syncro) {
467  for (size_t i = 0; i < 2; ++i) {
468  std::unique_lock<std::mutex> lk(mutex[i]);
469  img_consumed[i] = true;
470  img_consumed_cv[i].notify_all();
471  img_ready[i] = true;
472  img_ready_cv[i].notify_all();
473  }
474  }
475 }
476 
477 
479 {
480  if (!isRunning()) {
481  return false;
482  }
483 
484  if (!syncro) {
485  curr_buff_mutex.lock();
486  size_t cb = curr_buff;
487  std::unique_lock<std::mutex> lk(mutex[cb]);
488  // Release the mutex after we get the lock on current image to avoid
489  // that the image is swapped while we are waiting to read it
490  curr_buff_mutex.unlock();
491  image.copy(buffs[cb]);
492  stamp.update(buff_ts[cb]);
493  } else {
494  curr_buff_mutex.lock();
495  timing();
496  size_t cb = curr_buff;
497  std::unique_lock<std::mutex> lk(mutex[cb]);
498  img_ready_cv[cb].wait(lk, [&]{return (!isRunning() || img_ready[cb]);});
499  if (!isRunning()) {
500  return false;
501  }
502 
503  image.copy(buffs[cb]);
504  stamp.update(buff_ts[cb]);
505  img_consumed[cb] = true;
506  img_consumed_cv[cb].notify_one();
507 
508  curr_buff = (cb + 1) % 2;
509  curr_buff_mutex.unlock();
510  }
511 
512  return true;
513 }
514 
516 {
517  if (!isRunning()) {
518  return false;
519  }
520 
521  if (!syncro) {
522  curr_buff_mutex.lock();
523  size_t cb = curr_buff;
524  std::unique_lock<std::mutex> lk(mutex[cb]);
525  curr_buff_mutex.unlock();
526  if (use_bayer) {
527  makeSimpleBayer(buffs[cb], image);
528  } else {
529  image.copy(buffs[cb]);
530  }
531  stamp.update(buff_ts[cb]);
532  } else {
533  curr_buff_mutex.lock();
534  timing();
535  size_t cb = curr_buff;
536  std::unique_lock<std::mutex> lk(mutex[cb]);
537  img_ready_cv[cb].wait(lk, [&]{return (!isRunning() || img_ready[cb]);});
538  if (!isRunning()) {
539  return false;
540  }
541  if (use_bayer) {
542  makeSimpleBayer(buffs[cb], image);
543  } else {
544  image.copy(buffs[cb]);
545  }
546  stamp.update(buff_ts[cb]);
547  img_consumed[cb] = true;
548  img_consumed_cv[cb].notify_one();
549 
550  curr_buff = (cb + 1) % 2;
551  curr_buff_mutex.unlock();
552  }
553 
554  return true;
555 }
556 
558  yarp::sig::VectorOf<std::pair<int, int>> vertices,
560 {
561  yCDebugThrottle(FAKEFRAMEGRABBER, 5.0) << "Hardware crop requested!";
562  return yarp::dev::IFrameGrabberOf<yarp::sig::ImageOf<yarp::sig::PixelRgb>>::getImageCrop(cropType, vertices, image);
563 }
564 
566  yarp::sig::VectorOf<std::pair<int, int>> vertices,
568 {
569  yCDebugThrottle(FAKEFRAMEGRABBER, 5.0) << "Hardware crop requested!";
570  return yarp::dev::IFrameGrabberOf<yarp::sig::ImageOf<yarp::sig::PixelMono>>::getImageCrop(cropType, vertices, image);
571 }
572 
574  return stamp;
575 }
576 
577 bool FakeFrameGrabber::hasAudio() { return false; }
578 
579 bool FakeFrameGrabber::hasVideo() { return !use_mono; }
580 
582  return use_mono;
583 }
584 
586 bool FakeFrameGrabber::hasFeature(int feature, bool *hasFeature) { return false; }
587 bool FakeFrameGrabber::setFeature(int feature, double value) { return false; }
588 bool FakeFrameGrabber::getFeature(int feature, double *value) { return false; }
589 bool FakeFrameGrabber::setFeature(int feature, double value1, double value2) { return false; }
590 bool FakeFrameGrabber::getFeature(int feature, double *value1, double *value2) { return false; }
591 bool FakeFrameGrabber::hasOnOff(int feature, bool *HasOnOff) { return false; }
592 bool FakeFrameGrabber::setActive(int feature, bool onoff) { return false; }
593 bool FakeFrameGrabber::getActive(int feature, bool *isActive) { return false; }
594 bool FakeFrameGrabber::hasAuto(int feature, bool *hasAuto) { return false; }
595 bool FakeFrameGrabber::hasManual(int feature, bool *hasManual) { return false; }
596 bool FakeFrameGrabber::hasOnePush(int feature, bool *hasOnePush) { return false; }
597 bool FakeFrameGrabber::setMode(int feature, FeatureMode mode) { return false; }
598 bool FakeFrameGrabber::getMode(int feature, FeatureMode *mode) { return false; }
599 bool FakeFrameGrabber::setOnePush(int feature) { return false; }
600 
601 void FakeFrameGrabber::printTime(unsigned char* pixbuf, size_t pixbuf_w, size_t pixbuf_h, size_t x, size_t y, char* s, size_t size)
602 {
603  for (size_t i = 0; i < size; i++)
604  {
605  const char* num_p = nullptr;
606  switch (s[i]) {
607  case '0': num_p = num[0]; break;
608  case '1': num_p = num[1]; break;
609  case '2': num_p = num[2]; break;
610  case '3': num_p = num[3]; break;
611  case '4': num_p = num[4]; break;
612  case '5': num_p = num[5]; break;
613  case '6': num_p = num[6]; break;
614  case '7': num_p = num[7]; break;
615  case '8': num_p = num[8]; break;
616  case '9': num_p = num[9]; break;
617  case ' ': num_p = num[10]; break;
618  case '.': num_p = num[11]; break;
619  default: num_p = num[10]; break;
620  }
621 
622  for (size_t yi = 0; yi < num_height; yi++) {
623  for (size_t xi = 0; xi < num_width; xi++) {
624  size_t ii = yi * num_width + xi;
625  if (num_p[ii] == '*') {
626  for (size_t r = yi * num_height; r < yi*num_height + num_height; r++) {
627  size_t off = i * (num_height + 20);
628  for (size_t c = xi * num_height + off; c < xi*num_height + num_height + off; c++) {
629  if (c >= pixbuf_h || r >= pixbuf_w) {
630  //avoid drawing out of the image memory
631  return;
632  }
633  unsigned char *pixel = pixbuf;
634  size_t offset = c * sizeof(yarp::sig::PixelRgb) + r * (pixbuf_w * sizeof(yarp::sig::PixelRgb));
635  pixel = pixel + offset;
636  pixel[0] = 0;
637  pixel[1] = 0;
638  pixel[2] = 255;
639  }
640  }
641  }
642  }
643  }
644  }
645 }
646 
647 void FakeFrameGrabber::createTestImage(yarp::sig::ImageOf<yarp::sig::PixelRgb>& image,
648  double& timestamp) {
649  // to test IPreciselyTimed, make timestamps be mysteriously NNN.NNN42
650  double t = Time::now();
651  t -= (((t*1000) - static_cast<int64_t>(t*1000)) / 1000);
652  t += 0.00042;
653  timestamp = t;
654  image.resize(w,h);
655 
656  switch (mode) {
657  case VOCAB_TIMETEXT:
658  {
659  if (have_bg) {
660  image.copy(background);
661  } else {
662  image.zero();
663  }
664  char txtbuf[50];
665  static const double start_time = t;
666  double time = t - start_time;
667  std::snprintf(txtbuf, 50, "%.3f", time);
668  int len = strlen(txtbuf);
669  if (len < 20)
670  {
671  printTime((unsigned char*)image.getRawImage(), image.width(), image.height(), 0, 0, txtbuf, len);
672  }
673  }
674  break;
675  case VOCAB_BALL:
676  {
677  if (have_bg) {
678  image.copy(background);
679  } else {
680  image.zero();
681  }
682  addCircle(image,PixelRgb{0,255,0},bx,by,15);
683  addCircle(image,PixelRgb{0,255,255},bx,by,8);
684  if (ct%5!=0) {
685  rnd *= 65537;
686  rnd += 17;
687  int delta_x = (rnd % 5) - 2;
688  bx += delta_x;
689  rnd *= 65537;
690  rnd += 17;
691  int delta_y = (rnd % 5) - 2;
692  by += delta_y;
693  } else {
694  int dx = w/2 - bx;
695  int dy = h/2 - by;
696  if (dx>0) { bx++; }
697  if (dx<0) { bx--; }
698  if (dy>0) { by++; }
699  if (dy<0) { by--; }
700  }
701  }
702  break;
703  case VOCAB_GRID:
704  {
705  size_t ww = image.width();
706  size_t hh = image.height();
707  if (ww>1&&hh>1) {
708  for (size_t x=0; x<ww; x++) {
709  for (size_t y=0; y<hh; y++) {
710  double xx = ((double)x)/(ww-1);
711  double yy = ((double)y)/(hh-1);
712  bool act = (y==ct);
713  auto r = static_cast<unsigned char>(0.5 + 255 * xx);
714  auto g = static_cast<unsigned char>(0.5 + 255 * yy);
715  auto b = static_cast<unsigned char>(act * 255);
716  image.pixel(x, y) = PixelRgb{r, g, b};
717  }
718  }
719  }
720  }
721  break;
722  case VOCAB_GRID_MULTISIZE:
723  {
724  static int count = 0;
725  count++;
726  if (count== 100)
727  {
728  yCDebug(FAKEFRAMEGRABBER) << "size 100, 100";
729  image.resize(100,100);
730  }
731  else if (count == 200)
732  {
733  yCDebug(FAKEFRAMEGRABBER) << "size 200, 100";
734  image.resize(200, 100);
735  }
736  else if (count == 300)
737  {
738  yCDebug(FAKEFRAMEGRABBER) << "size 300, 50";
739  image.resize(300, 50);
740  count = 0;
741  }
742 
743  size_t ww = w = image.width();
744  size_t hh = h = image.height();
745  if (ww>1 && hh>1) {
746  for (size_t x = 0; x<ww; x++) {
747  for (size_t y = 0; y<hh; y++) {
748  double xx = ((double)x) / (ww - 1);
749  double yy = ((double)y) / (hh - 1);
750  bool act = (y == ct);
751  auto r = static_cast<unsigned char>(0.5 + 255 * xx);
752  auto g = static_cast<unsigned char>(0.5 + 255 * yy);
753  auto b = static_cast<unsigned char>(act * 255);
754  image.pixel(x, y) = PixelRgb{r, g, b};
755  }
756  }
757  }
758  }
759  break;
760  case VOCAB_LINE:
761  default:
762  {
763  if (have_bg) {
764  image.copy(background);
765  } else {
766  image.zero();
767  }
768  for (size_t i=0; i<image.width(); i++) {
769  image.pixel(i,ct).r = 255;
770  }
771  }
772  break;
773  case VOCAB_RAND:
774  {
775  static unsigned char r = 128;
776  static unsigned char g = 128;
777  static unsigned char b = 128;
778 
779  size_t ww = image.width();
780  size_t hh = image.height();
781 
782  if (ww>1&&hh>1) {
783  for (size_t x=0; x<ww; x++) {
784  for (size_t y=0; y<hh; y++) {
785  r += udist(randengine);
786  g += udist(randengine);
787  b += udist(randengine);
788  image.pixel(x,y) = PixelRgb{r,g,b};
789  }
790  }
791  }
792  }
793  break;
794  case VOCAB_NONE:
795  {
796  if (have_bg) {
797  image.copy(background);
798  } else {
799  image.zero();
800  }
801  }
802  break;
803  }
804  ct++;
805  if (ct>=image.height()) {
806  ct = 0;
807  }
808  if (by>=image.height()) {
809  by = image.height()-1;
810  }
811  if (bx>=image.width()) {
812  bx = image.width()-1;
813  }
814 
815  if (add_noise) {
816  static const double nsr = 1.0 - snr;
817  for (size_t x = 0; x < image.width(); ++x) {
818  for (size_t y = 0; y < image.height(); ++y) {
819  auto rand = ucdist(randengine);
820  image.pixel(x,y) = PixelRgb {
821  static_cast<unsigned char>(image.pixel(x,y).r * snr + (rand * nsr * 255)),
822  static_cast<unsigned char>(image.pixel(x,y).g * snr + (rand * nsr * 255)),
823  static_cast<unsigned char>(image.pixel(x,y).b * snr + (rand * nsr * 255))
824  };
825  }
826  }
827  }
828 
829  if (add_timestamp) {
830  char ttxt[50];
831  std::snprintf(ttxt, 50, "%021.10f", timestamp);
832  image.pixel(0, 0).r = ttxt[0] - '0';
833  image.pixel(0, 0).g = ttxt[1] - '0';
834  image.pixel(0, 0).b = ttxt[2] - '0';
835 
836  image.pixel(1, 0).r = ttxt[3] - '0';
837  image.pixel(1, 0).g = ttxt[4] - '0';
838  image.pixel(1, 0).b = ttxt[5] - '0';
839 
840  image.pixel(2, 0).r = ttxt[6] - '0';
841  image.pixel(2, 0).g = ttxt[7] - '0';
842  image.pixel(2, 0).b = ttxt[8] - '0';
843 
844  image.pixel(3, 0).r = ttxt[9] - '0';
845  image.pixel(3, 0).g = ttxt[10] - '0';
846  image.pixel(3, 0).b = ttxt[11] - '0';
847 
848  image.pixel(4, 0).r = ttxt[12] - '0';
849  image.pixel(4, 0).g = ttxt[13] - '0';
850  image.pixel(4, 0).b = ttxt[14] - '0';
851 
852  image.pixel(5, 0).r = ttxt[15] - '0';
853  image.pixel(5, 0).g = ttxt[16] - '0';
854  image.pixel(5, 0).b = ttxt[17] - '0';
855 
856  image.pixel(6, 0).r = ttxt[18] - '0';
857  image.pixel(6, 0).g = ttxt[19] - '0';
858  image.pixel(6, 0).b = ttxt[20] - '0';
859  }
860 
861  image.setTopIsLowIndex(topIsLow);
862 }
863 
864 
865 
866 // From iCub staticgrabber device.
867 // DF2 bayer sequence.
868 // -- in staticgrabber: first row GBGBGB, second row RGRGRG.
869 // -- changed here to: first row GRGRGR, second row BGBGBG.
870 bool FakeFrameGrabber::makeSimpleBayer(
871  ImageOf<PixelRgb>& img,
872  ImageOf<PixelMono>& bayer) {
873 
874  bayer.resize(img.width(), img.height());
875 
876  const size_t w = img.width();
877  const size_t h = img.height();
878 
879  size_t i, j;
880  for (i = 0; i < h; i++) {
881  auto* row = (PixelRgb *)img.getRow(i);
882  auto* rd = (PixelMono *)bayer.getRow(i);
883 
884  for (j = 0; j < w; j++) {
885 
886  if ((i%2) == 0) {
887  switch (j%4) {
888  case 0:
889  case 2:
890  *rd++ = row->g;
891  row++;
892  break;
893 
894  case 1:
895  case 3:
896  *rd++ = row->r;
897  row++;
898  break;
899  }
900  }
901 
902  if ((i%2) == 1) {
903  switch (j%4) {
904  case 1:
905  case 3:
906  *rd++ = row->g;
907  row++;
908  break;
909 
910  case 0:
911  case 2:
912  *rd++ = row->b;
913  row++;
914  break;
915  }
916  }
917  }
918  }
919 
920  return true;
921 }
float t
cropType_id_t
std::default_random_engine randengine
Definition: Random.cpp:13
int width() const override
Return the width of each frame.
bool getCameraDescription(CameraDescriptor *camera) override
Get a basic description of the camera hw.
bool getImageCrop(cropType_id_t cropType, yarp::sig::VectorOf< std::pair< int, int >> vertices, yarp::sig::ImageOf< yarp::sig::PixelRgb > &image) override
bool hasFeature(int feature, bool *hasFeature) override
Check if camera has the requested feature (saturation, brightness ...
bool getMode(int feature, FeatureMode *mode) override
Get the current mode for the feature.
bool setFeature(int feature, double value) override
Set the requested feature to a value (saturation, brightness ...
int getRgbWidth() override
Return the width of each frame.
int getRgbHeight() override
Return the height of each frame.
yarp::os::Stamp getLastInputStamp() override
Return the time stamp relative to the last acquisition.
bool setOnePush(int feature) override
Set the requested feature to a value (saturation, brightness ...
bool getRgbResolution(int &width, int &height) override
Get the resolution of the rgb image from the camera.
bool getRgbIntrinsicParam(yarp::os::Property &intrinsic) override
Get the intrinsic parameters of the rgb camera.
bool getActive(int feature, bool *isActive) override
Get the current status of the feature, on or off.
bool hasVideo() override
bool getRgbSupportedConfigurations(yarp::sig::VectorOf< yarp::dev::CameraConfig > &configurations) override
Get the possible configurations of the camera.
bool hasOnePush(int feature, bool *hasOnePush) override
Check if the requested feature has the 'onePush' mode.
int height() const override
Return the height of each frame.
bool setMode(int feature, FeatureMode mode) override
Set the requested mode for the feature.
bool hasManual(int feature, bool *hasManual) override
Check if the requested feature has the 'manual' mode.
bool getRgbMirroring(bool &mirror) override
Get the mirroring setting of the sensor.
bool hasAuto(int feature, bool *hasAuto) override
Check if the requested feature has the 'auto' mode.
bool hasOnOff(int feature, bool *HasOnOff) override
Check if the camera has the ability to turn on/off the requested feature.
bool getFeature(int feature, double *value) override
Get the current value for the requested feature.
bool getRgbFOV(double &horizontalFov, double &verticalFov) override
Get the field of view (FOV) of the rgb camera.
bool setRgbMirroring(bool mirror) override
Set the mirroring setting of the sensor.
bool setActive(int feature, bool onoff) override
Set the requested feature on or off.
bool open(yarp::os::Searchable &config) override
Configure with a set of options.
bool setRgbResolution(int width, int height) override
Set the resolution of the rgb image from the camera.
bool setRgbFOV(double horizontalFov, double verticalFov) override
Set the field of view (FOV) of the rgb camera.
void run() override
Main body of the new thread.
void onStop() override
Call-back, called while halting the thread (before join).
bool getImage(yarp::sig::ImageOf< yarp::sig::PixelRgb > &image) override
bool hasAudio() override
bool hasRawVideo() override
bool read(yarp::os::ConnectionReader &connection) override
Read this object from a network connection.
bool close() override
Close the DeviceDriver.
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:74
void addVocab32(yarp::conf::vocab32_t x)
Places a vocabulary item in the bottle, at the end of the list.
Definition: Bottle.cpp:164
bool read(ConnectionReader &reader) override
Set the bottle's value based on input from a network connection.
Definition: Bottle.cpp:240
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:246
void clear()
Empties the bottle of any objects it contains.
Definition: Bottle.cpp:121
bool write(ConnectionWriter &writer) const override
Output a representation of the bottle to a network connection.
Definition: Bottle.cpp:230
void addString(const char *str)
Places a string in the bottle, at the end of the list.
Definition: Bottle.cpp:170
An interface for reading from a network connection.
virtual ConnectionWriter * getWriter()=0
Gets a way to reply to the message, if possible.
An interface for writing to a network connection.
A class for storing options and configuration information.
Definition: Property.h:34
A base class for nested structures that can be searched.
Definition: Searchable.h:66
virtual bool check(const std::string &key) const =0
Check if there exists a property of the given name.
An abstraction for a time stamp and/or sequence number.
Definition: Stamp.h:22
A single value (typically within a Bottle).
Definition: Value.h:45
virtual yarp::conf::float64_t asFloat64() const
Get 64-bit floating point value.
Definition: Value.cpp:222
static Value * makeList()
Create a list Value.
Definition: Value.cpp:440
virtual yarp::conf::vocab32_t asVocab32() const
Get vocabulary identifier as an integer.
Definition: Value.cpp:228
virtual std::string asString() const
Get string value.
Definition: Value.cpp:234
T & pixel(size_t x, size_t y)
Definition: Image.h:674
size_t width() const
Gets width of image in pixels.
Definition: Image.h:166
unsigned char * getRawImage() const
Access to the internal image buffer.
Definition: Image.cpp:541
bool copy(const Image &alt)
Copy operator.
Definition: Image.cpp:836
unsigned char * getRow(size_t r)
Get the address of a the first byte of a row in memory.
Definition: Image.h:216
void resize(size_t imgWidth, size_t imgHeight)
Reallocate an image to be of a desired size, throwing away its current contents.
Definition: Image.cpp:452
void setTopIsLowIndex(bool flag)
control whether image has origin at top left (default) or bottom left.
Definition: Image.cpp:511
void zero()
Set all pixels to 0.
Definition: Image.cpp:445
size_t height() const
Gets height of image in pixels.
Definition: Image.h:172
Provides:
Definition: Vector.h:119
#define yCInfo(component,...)
Definition: LogComponent.h:132
#define yCError(component,...)
Definition: LogComponent.h:154
#define yCDebugThrottle(component, period,...)
Definition: LogComponent.h:112
#define yCWarning(component,...)
Definition: LogComponent.h:143
#define yCDebug(component,...)
Definition: LogComponent.h:109
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:77
@ VOCAB_PIXEL_BGR
Definition: Image.h:52
@ VOCAB_PIXEL_MONO
Definition: Image.h:45
@ VOCAB_PIXEL_RGB
Definition: Image.h:47
std::int32_t vocab32_t
Definition: numeric.h:78
constexpr const T & clamp(const T &v, const T &lo, const T &hi)
Definition: numeric.h:91
An interface for the device drivers.
void yield()
The calling thread releases its remaining quantum upon calling this function.
Definition: Time.cpp:138
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition: Time.cpp:121
void delay(double seconds)
Wait for a certain number of seconds.
Definition: Time.cpp:111
std::string decode(NetInt32 code)
Convert a vocabulary identifier into a string.
Definition: Vocab.cpp:33
An interface to the operating system, including Port based communication.
constexpr yarp::conf::vocab32_t createVocab32(char a, char b=0, char c=0, char d=0)
Create a vocab from chars.
Definition: Vocab.h:28
Very basic drawing functions, in case you don't have anything better available.
Definition: ImageDraw.h:23
void addCircle(ImageOf< T > &dest, const T &pix, int i, int j, int r)
Definition: ImageDraw.h:40
bool read(ImageOf< PixelRgb > &dest, const std::string &src, image_fileformat format=FORMAT_ANY)
Definition: ImageFile.cpp:922
Signal processing.
Definition: Image.h:22
unsigned char PixelMono
Monochrome pixel type.
Definition: Image.h:447
The main, catch-all namespace for YARP.
Definition: dirs.h:16
Struct describing a possible camera configuration.
YarpVocabPixelTypesEnum pixelCoding
Packed RGB pixel type.
Definition: Image.h:464
unsigned char g
Definition: Image.h:466
unsigned char r
Definition: Image.h:465
unsigned char b
Definition: Image.h:467