YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
FakeFrameGrabber_Utils.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")
24
25//the following data are used by [time] test
26constexpr char num[12][16]
27{
28 // '0'
29 "***"
30 "* *"
31 "* *"
32 "* *"
33 "***",
34
35 // '1'
36 " * "
37 " * "
38 " * "
39 " * "
40 " * ",
41
42 // '2'
43 "***"
44 " *"
45 "***"
46 "* "
47 "***",
48
49 // '3'
50 "***"
51 " *"
52 "***"
53 " *"
54 "***",
55
56 // '4'
57 "* *"
58 "* *"
59 "***"
60 " *"
61 " *",
62
63 // '5'
64 "***"
65 "* "
66 "***"
67 " *"
68 "***",
69
70 // '6'
71 "***"
72 "* "
73 "***"
74 "* *"
75 "***",
76
77 // '7'
78 "***"
79 " *"
80 " *"
81 " *"
82 " *",
83
84 // '8'
85 "***"
86 "* *"
87 "***"
88 "* *"
89 "***",
90
91 // '9'
92 "***"
93 "* *"
94 "***"
95 " *"
96 "***",
97
98 // ' '
99 " "
100 " "
101 " "
102 " "
103 " ",
104
105 // '.'
106 " "
107 " "
108 " "
109 " **"
110 " **",
111};
112constexpr size_t num_width = 3;
113constexpr size_t num_height = 5;
114
115} // namespace
116
117void FakeFrameGrabber::printTime(unsigned char* pixbuf, size_t pixbuf_w, size_t pixbuf_h, size_t x, size_t y, char* s, size_t size)
118{
119 for (size_t i = 0; i < size; i++)
120 {
121 const char* num_p = nullptr;
122 switch (s[i]) {
123 case '0': num_p = num[0]; break;
124 case '1': num_p = num[1]; break;
125 case '2': num_p = num[2]; break;
126 case '3': num_p = num[3]; break;
127 case '4': num_p = num[4]; break;
128 case '5': num_p = num[5]; break;
129 case '6': num_p = num[6]; break;
130 case '7': num_p = num[7]; break;
131 case '8': num_p = num[8]; break;
132 case '9': num_p = num[9]; break;
133 case ' ': num_p = num[10]; break;
134 case '.': num_p = num[11]; break;
135 default: num_p = num[10]; break;
136 }
137
138 for (size_t yi = 0; yi < num_height; yi++) {
139 for (size_t xi = 0; xi < num_width; xi++) {
140 size_t ii = yi * num_width + xi;
141 if (num_p[ii] == '*') {
142 for (size_t r = yi * num_height; r < yi*num_height + num_height; r++) {
143 size_t off = i * (num_height + 20);
144 for (size_t c = xi * num_height + off; c < xi*num_height + num_height + off; c++) {
145 if (c >= pixbuf_h || r >= pixbuf_w) {
146 //avoid drawing out of the image memory
147 return;
148 }
149 unsigned char *pixel = pixbuf;
150 size_t offset = c * sizeof(yarp::sig::PixelRgb) + r * (pixbuf_w * sizeof(yarp::sig::PixelRgb));
151 pixel = pixel + offset;
152 pixel[0] = 0;
153 pixel[1] = 0;
154 pixel[2] = 255;
155 }
156 }
157 }
158 }
159 }
160 }
161}
162
163void FakeFrameGrabber::createTestImage(yarp::sig::ImageOf<yarp::sig::PixelRgb>& image,
164 double& timestamp)
165{
166 //block to avoid race while an rpc can reset the image properties(e.g. w/h)
167 std::lock_guard<std::mutex> lock(rpc_methods_mutex);
168
169 //to test IPreciselyTimed, make timestamps be mysteriously NNN.NNN42
170 double t = Time::now();
171 t -= (((t*1000) - static_cast<int64_t>(t*1000)) / 1000);
172 t += 0.00042;
173 timestamp = t;
174
175 //set the image size
176 image.resize(m_width,m_height);
177
178 //check the counter inside the image size
179 if (m_ct>=image.height()) {
180 m_ct = 0;
181 }
182 if (m_by>=image.height()) {
183 m_by = image.height()-1;
184 }
185 if (m_bx>=image.width()) {
186 m_bx = image.width()-1;
187 }
188
189 if (m_mode == "[Time]")
190 {
191 {
192 if (m_have_bg) {
193 image.copy(background);
194 } else {
195 image.zero();
196 }
197 char txtbuf[50];
198 static const double start_time = t;
199 double time = t - start_time;
200 std::snprintf(txtbuf, 50, "%.3f", time);
201 int len = strlen(txtbuf);
202 if (len < 20)
203 {
204 printTime((unsigned char*)image.getRawImage(), image.width(), image.height(), 0, 0, txtbuf, len);
205 }
206 }
207 }
208 else if (m_mode == "[ball]")
209 {
210 {
211 if (m_have_bg) {
212 image.copy(background);
213 } else {
214 image.zero();
215 }
216 addCircle(image,PixelRgb{0,255,0},m_bx,m_by,15);
217 addCircle(image,PixelRgb{0,255,255},m_bx,m_by,8);
218 if (m_ct%5!=0) {
219 m_rnd *= 65537;
220 m_rnd += 17;
221 int delta_x = (m_rnd % 5) - 2;
222 m_bx += delta_x;
223 m_rnd *= 65537;
224 m_rnd += 17;
225 int delta_y = (m_rnd % 5) - 2;
226 m_by += delta_y;
227 } else {
228 int dx = m_width/2 - m_bx;
229 int dy = m_height/2 - m_by;
230 if (dx>0) { m_bx++; }
231 if (dx<0) { m_bx--; }
232 if (dy>0) { m_by++; }
233 if (dy<0) { m_by--; }
234 }
235 }
236 }
237 else if (m_mode == "[grid]")
238 {
239 {
240 size_t ww = image.width();
241 size_t hh = image.height();
242 if (ww>1&&hh>1) {
243 for (size_t x=0; x<ww; x++) {
244 for (size_t y=0; y<hh; y++) {
245 double xx = ((double)x)/(ww-1);
246 double yy = ((double)y)/(hh-1);
247 bool act = (y==m_ct);
248 auto r = static_cast<unsigned char>(0.5 + 255 * xx);
249 auto g = static_cast<unsigned char>(0.5 + 255 * yy);
250 auto b = static_cast<unsigned char>(act * 255);
251 image.pixel(x, y) = PixelRgb{r, g, b};
252 }
253 }
254 }
255 }
256 }
257 else if (m_mode == "[size]")
258 {
259 static int count = 0;
260 count++;
261 if (count== 100)
262 {
263 yCDebug(FAKEFRAMEGRABBER) << "size 100, 100";
264 image.resize(100,100);
265 }
266 else if (count == 200)
267 {
268 yCDebug(FAKEFRAMEGRABBER) << "size 200, 100";
269 image.resize(200, 100);
270 }
271 else if (count == 300)
272 {
273 yCDebug(FAKEFRAMEGRABBER) << "size 300, 50";
274 image.resize(300, 50);
275 count = 0;
276 }
277
278 size_t ww = m_width = image.width();
279 size_t hh = m_height = image.height();
280 if (ww>1 && hh>1) {
281 for (size_t x = 0; x<ww; x++) {
282 for (size_t y = 0; y<hh; y++) {
283 double xx = ((double)x) / (ww - 1);
284 double yy = ((double)y) / (hh - 1);
285 bool act = (y == m_ct);
286 auto r = static_cast<unsigned char>(0.5 + 255 * xx);
287 auto g = static_cast<unsigned char>(0.5 + 255 * yy);
288 auto b = static_cast<unsigned char>(act * 255);
289 image.pixel(x, y) = PixelRgb{r, g, b};
290 }
291 }
292 }
293 }
294 else if (m_mode == "[line]")
295 {
296 {
297 if (m_have_bg) {
298 image.copy(background);
299 } else {
300 image.zero();
301 }
302 for (size_t i=0; i<image.width(); i++) {
303 image.pixel(i,m_ct).r = 255;
304 }
305 }
306 }
307 else if (m_mode == "[rand]")
308 {
309 {
310 static unsigned char r = 128;
311 static unsigned char g = 128;
312 static unsigned char b = 128;
313
314 size_t ww = image.width();
315 size_t hh = image.height();
316
317 if (ww>1&&hh>1) {
318 for (size_t x=0; x<ww; x++) {
319 for (size_t y=0; y<hh; y++) {
320 r += udist(randengine);
321 g += udist(randengine);
322 b += udist(randengine);
323 image.pixel(x,y) = PixelRgb{r,g,b};
324 }
325 }
326 }
327 }
328 }
329 else if (m_mode == "[none]")
330 {
331 {
332 if (m_have_bg) {
333 image.copy(background);
334 } else {
335 image.zero();
336 }
337 }
338 }
339 else
340 {
341 yCError(FAKEFRAMEGRABBER, "Invalid mode %s", m_mode.c_str());
342 }
343
344 if (m_add_noise)
345 {
346 static const double nsr = 1.0 - m_snr;
347 for (size_t x = 0; x < image.width(); ++x) {
348 for (size_t y = 0; y < image.height(); ++y) {
349 auto rand = ucdist(randengine);
350 image.pixel(x,y) = PixelRgb {
351 static_cast<unsigned char>(image.pixel(x,y).r * m_snr + (rand * nsr * 255)),
352 static_cast<unsigned char>(image.pixel(x,y).g * m_snr + (rand * nsr * 255)),
353 static_cast<unsigned char>(image.pixel(x,y).b * m_snr + (rand * nsr * 255))
354 };
355 }
356 }
357 }
358
359 if (m_add_timestamp)
360 {
361 char ttxt[50];
362 std::snprintf(ttxt, 50, "%021.10f", timestamp);
363 image.pixel(0, 0).r = ttxt[0] - '0';
364 image.pixel(0, 0).g = ttxt[1] - '0';
365 image.pixel(0, 0).b = ttxt[2] - '0';
366
367 image.pixel(1, 0).r = ttxt[3] - '0';
368 image.pixel(1, 0).g = ttxt[4] - '0';
369 image.pixel(1, 0).b = ttxt[5] - '0';
370
371 image.pixel(2, 0).r = ttxt[6] - '0';
372 image.pixel(2, 0).g = ttxt[7] - '0';
373 image.pixel(2, 0).b = ttxt[8] - '0';
374
375 image.pixel(3, 0).r = ttxt[9] - '0';
376 image.pixel(3, 0).g = ttxt[10] - '0';
377 image.pixel(3, 0).b = ttxt[11] - '0';
378
379 image.pixel(4, 0).r = ttxt[12] - '0';
380 image.pixel(4, 0).g = ttxt[13] - '0';
381 image.pixel(4, 0).b = ttxt[14] - '0';
382
383 image.pixel(5, 0).r = ttxt[15] - '0';
384 image.pixel(5, 0).g = ttxt[16] - '0';
385 image.pixel(5, 0).b = ttxt[17] - '0';
386
387 image.pixel(6, 0).r = ttxt[18] - '0';
388 image.pixel(6, 0).g = ttxt[19] - '0';
389 image.pixel(6, 0).b = ttxt[20] - '0';
390 }
391
392 m_ct++;
393}
394
395
396
397// From iCub staticgrabber device.
398// DF2 bayer sequence.
399// -- in staticgrabber: first row GBGBGB, second row RGRGRG.
400// -- changed here to: first row GRGRGR, second row BGBGBG.
401bool FakeFrameGrabber::makeSimpleBayer(
404
405 bayer.resize(img.width(), img.height());
406
407 const size_t w = img.width();
408 const size_t h = img.height();
409
410 size_t i, j;
411 for (i = 0; i < h; i++) {
412 auto* row = (PixelRgb *)img.getRow(i);
413 auto* rd = (PixelMono *)bayer.getRow(i);
414
415 for (j = 0; j < w; j++) {
416
417 if ((i%2) == 0) {
418 switch (j%4) {
419 case 0:
420 case 2:
421 *rd++ = row->g;
422 row++;
423 break;
424
425 case 1:
426 case 3:
427 *rd++ = row->r;
428 row++;
429 break;
430 }
431 }
432
433 if ((i%2) == 1) {
434 switch (j%4) {
435 case 1:
436 case 3:
437 *rd++ = row->g;
438 row++;
439 break;
440
441 case 0:
442 case 2:
443 *rd++ = row->b;
444 row++;
445 break;
446 }
447 }
448 }
449 }
450
451 return true;
452}
A mini-server for performing network communication in the background.
Typed image class.
Definition Image.h:603
#define yCError(component,...)
#define yCDebug(component,...)
#define YARP_LOG_COMPONENT(name,...)
For streams capable of holding different kinds of content, check what they actually have.
double now()
Return the current time in seconds, relative to an arbitrary starting point.
Definition Time.cpp:121
An interface to the operating system, including Port based communication.
void addCircle(ImageOf< T > &dest, const T &pix, int i, int j, int r)
Definition ImageDraw.h:32