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
10#include <yarp/os/LogStream.h>
11#include <yarp/sig/ImageDraw.h>
12
13#include <cstdio>
14#include <thread>
15#include <random>
16
17using namespace yarp::os;
18using namespace yarp::dev;
19using namespace yarp::sig;
20using namespace yarp::sig::draw;
21
22namespace {
23YARP_LOG_COMPONENT(FAKEFRAMEGRABBER, "yarp.device.fakeFrameGrabber")
24constexpr yarp::conf::vocab32_t VOCAB_LINE = yarp::os::createVocab32('l','i','n','e');
25constexpr yarp::conf::vocab32_t VOCAB_BALL = yarp::os::createVocab32('b','a','l','l');
26constexpr yarp::conf::vocab32_t VOCAB_GRID = yarp::os::createVocab32('g','r','i','d');
27constexpr yarp::conf::vocab32_t VOCAB_RAND = yarp::os::createVocab32('r','a','n','d');
28constexpr yarp::conf::vocab32_t VOCAB_NONE = yarp::os::createVocab32('n','o','n','e');
29constexpr yarp::conf::vocab32_t VOCAB_GRID_MULTISIZE = yarp::os::createVocab32('s','i','z','e');
30constexpr yarp::conf::vocab32_t VOCAB_TIMETEXT = yarp::os::createVocab32('t','i','m','e');
31
32//the following data are used by [time] test
33constexpr 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};
119constexpr size_t num_width = 3;
120constexpr size_t num_height = 5;
121
122} // namespace
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
395bool FakeFrameGrabber::getRgbResolution(int &width, int &height){
396 width=w;
397 height=h;
398 return true;
399}
400
401bool FakeFrameGrabber::setRgbResolution(int width, int height){
402 w=width;
403 h=height;
404 return true;
405}
406
407bool FakeFrameGrabber::getRgbFOV(double &horizontalFov, double &verticalFov){
408 horizontalFov=this->horizontalFov;
409 verticalFov=this->verticalFov;
410 return true;
411}
412
413bool 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!";
563}
564
566 yarp::sig::VectorOf<std::pair<int, int>> vertices,
568{
569 yCDebugThrottle(FAKEFRAMEGRABBER, 5.0) << "Hardware crop requested!";
571}
572
574 return stamp;
575}
576
577bool FakeFrameGrabber::hasAudio() { return false; }
578
579bool FakeFrameGrabber::hasVideo() { return !use_mono; }
580
582 return use_mono;
583}
584
586bool FakeFrameGrabber::hasFeature(int feature, bool *hasFeature) { return false; }
587bool FakeFrameGrabber::setFeature(int feature, double value) { return false; }
588bool FakeFrameGrabber::getFeature(int feature, double *value) { return false; }
589bool FakeFrameGrabber::setFeature(int feature, double value1, double value2) { return false; }
590bool FakeFrameGrabber::getFeature(int feature, double *value1, double *value2) { return false; }
591bool FakeFrameGrabber::hasOnOff(int feature, bool *HasOnOff) { return false; }
592bool FakeFrameGrabber::setActive(int feature, bool onoff) { return false; }
593bool FakeFrameGrabber::getActive(int feature, bool *isActive) { return false; }
594bool FakeFrameGrabber::hasAuto(int feature, bool *hasAuto) { return false; }
595bool FakeFrameGrabber::hasManual(int feature, bool *hasManual) { return false; }
596bool FakeFrameGrabber::hasOnePush(int feature, bool *hasOnePush) { return false; }
597bool FakeFrameGrabber::setMode(int feature, FeatureMode mode) { return false; }
598bool FakeFrameGrabber::getMode(int feature, FeatureMode *mode) { return false; }
599bool FakeFrameGrabber::setOnePush(int feature) { return false; }
600
601void 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
647void 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.
870bool FakeFrameGrabber::makeSimpleBayer(
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
int width() const override
Return the width of each frame.
bool getCameraDescription(CameraDescriptor *camera) override
Get a basic description of the camera hw.
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
Get an image from the frame grabber.
bool getImageCrop(cropType_id_t cropType, yarp::sig::VectorOf< std::pair< int, int > > vertices, 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:64
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.
void setReader(PortReader &reader) override
Set an external reader for port data.
Definition: Port.cpp:511
void close() override
Stop port activity.
Definition: Port.cpp:363
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
Definition: Port.cpp:79
A class for storing options and configuration information.
Definition: Property.h:33
void put(const std::string &key, const std::string &value)
Associate the given key with the given string.
Definition: Property.cpp:1015
A base class for nested structures that can be searched.
Definition: Searchable.h:63
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:21
void update()
Set the timestamp to the current time, and increment the sequence number (wrapping to 0 if the sequen...
Definition: Stamp.cpp:124
bool stop()
Stop the thread.
Definition: Thread.cpp:81
bool isStopping()
Returns true if the thread is stopping (Thread::stop has been called).
Definition: Thread.cpp:99
bool isRunning()
Returns true if the thread is running (Thread::start has been called successfully and the thread has ...
Definition: Thread.cpp:105
bool start()
Start the new thread running.
Definition: Thread.cpp:93
A single value (typically within a Bottle).
Definition: Value.h:43
virtual yarp::conf::float64_t asFloat64() const
Get 64-bit floating point value.
Definition: Value.cpp:222
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:669
unsigned char * getRow(size_t r)
Get the address of a the first byte of a row in memory.
Definition: Image.h:213
size_t width() const
Gets width of image in pixels.
Definition: Image.h:163
unsigned char * getRawImage() const
Access to the internal image buffer.
Definition: Image.cpp:542
bool copy(const Image &alt)
Copy operator.
Definition: Image.cpp:837
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:453
void setTopIsLowIndex(bool flag)
control whether image has origin at top left (default) or bottom left.
Definition: Image.cpp:512
void zero()
Set all pixels to 0.
Definition: Image.cpp:446
size_t height() const
Gets height of image in pixels.
Definition: Image.h:169
Provides:
Definition: Vector.h:117
void push_back(const T &elem)
Push a new element in the vector: size is changed.
Definition: Vector.h:248
#define yCInfo(component,...)
Definition: LogComponent.h:171
#define yCError(component,...)
Definition: LogComponent.h:213
#define yCDebugThrottle(component, period,...)
Definition: LogComponent.h:131
#define yCWarning(component,...)
Definition: LogComponent.h:192
#define yCDebug(component,...)
Definition: LogComponent.h:128
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:76
@ VOCAB_PIXEL_BGR
Definition: Image.h:49
@ VOCAB_PIXEL_MONO
Definition: Image.h:42
@ VOCAB_PIXEL_RGB
Definition: Image.h:44
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
For streams capable of holding different kinds of content, check what they actually have.
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:27
void addCircle(ImageOf< T > &dest, const T &pix, int i, int j, int r)
Definition: ImageDraw.h:32
bool read(ImageOf< PixelRgb > &dest, const std::string &src, image_fileformat format=FORMAT_ANY)
Definition: ImageFile.cpp:915
unsigned char PixelMono
Monochrome pixel type.
Definition: Image.h:443
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:460
unsigned char g
Definition: Image.h:462
unsigned char r
Definition: Image.h:461
unsigned char b
Definition: Image.h:463