Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
catchColorConversion.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Test image conversion.
32 */
33
39
40#include <visp3/core/vpConfig.h>
41
42#if defined(VISP_HAVE_CATCH2)
43
44#include "common.hpp"
45#include <catch_amalgamated.hpp>
46#include <visp3/core/vpImageConvert.h>
47#include <visp3/core/vpIoTools.h>
48#include <visp3/core/vpEndian.h>
49#include <visp3/io/vpImageIo.h>
50
51#ifdef ENABLE_VISP_NAMESPACE
52using namespace VISP_NAMESPACE_NAME;
53#endif
54
55static const double maxMeanPixelError = 1.5; // conversion to gray produce an error = 1.0
56static const unsigned int width = 223, height = 151;
57
58TEST_CASE("Gray to RGBa conversion", "[image_conversion]")
59{
60 SECTION("Image 1x16 (SSE41 aligned=true)")
61 {
62 unsigned int h = 1, w = 16;
63 vpImage<unsigned char> gray(h, w);
64 common_tools::fill(gray);
65
66 vpImage<vpRGBa> rgba_ref(h, w);
67 common_tools::grayToRGBaRef(gray.bitmap, reinterpret_cast<unsigned char *>(rgba_ref.bitmap), gray.getSize());
68
69 vpImage<vpRGBa> rgba;
70 vpImageConvert::convert(gray, rgba);
71 CHECK((rgba == rgba_ref));
72 }
73 SECTION("Image 1x17 (SSE41 aligned=false)")
74 {
75 unsigned int h = 1, w = 17;
76 vpImage<unsigned char> gray(h, w);
77 common_tools::fill(gray);
78
79 vpImage<vpRGBa> rgba_ref(h, w);
80 common_tools::grayToRGBaRef(gray.bitmap, reinterpret_cast<unsigned char *>(rgba_ref.bitmap), gray.getSize());
81
82 vpImage<vpRGBa> rgba;
83 vpImageConvert::convert(gray, rgba);
84 CHECK((rgba == rgba_ref));
85 }
86 SECTION("Image 1x32 (AVX2 aligned=true)")
87 {
88 unsigned int h = 1, w = 32;
89 vpImage<unsigned char> gray(h, w);
90 common_tools::fill(gray);
91
92 vpImage<vpRGBa> rgba_ref(h, w);
93 common_tools::grayToRGBaRef(gray.bitmap, reinterpret_cast<unsigned char *>(rgba_ref.bitmap), gray.getSize());
94
95 vpImage<vpRGBa> rgba;
96 vpImageConvert::convert(gray, rgba);
97 CHECK((rgba == rgba_ref));
98 }
99 SECTION("Image 1x33 (AVX2 aligned=false)")
100 {
101 unsigned int h = 1, w = 33;
102 vpImage<unsigned char> gray(h, w);
103 common_tools::fill(gray);
104
105 vpImage<vpRGBa> rgba_ref(h, w);
106 common_tools::grayToRGBaRef(gray.bitmap, reinterpret_cast<unsigned char *>(rgba_ref.bitmap), gray.getSize());
107
108 vpImage<vpRGBa> rgba;
109 vpImageConvert::convert(gray, rgba);
110 CHECK((rgba == rgba_ref));
111 }
112 SECTION("Image 4x64 (general aligned = true")
113 {
114 unsigned int h = 4, w = 64;
115 vpImage<unsigned char> gray(h, w);
116 common_tools::fill(gray);
117
118 vpImage<vpRGBa> rgba_ref(h, w);
119 common_tools::grayToRGBaRef(gray.bitmap, reinterpret_cast<unsigned char *>(rgba_ref.bitmap), gray.getSize());
120
121 vpImage<vpRGBa> rgba;
122 vpImageConvert::convert(gray, rgba);
123 CHECK((rgba == rgba_ref));
124 }
125 SECTION("Image 5x65 (general aligned = false")
126 {
127 unsigned int h = 5, w = 65;
128 vpImage<unsigned char> gray(h, w);
129 common_tools::fill(gray);
130
131 vpImage<vpRGBa> rgba_ref(h, w);
132 common_tools::grayToRGBaRef(gray.bitmap, reinterpret_cast<unsigned char *>(rgba_ref.bitmap), gray.getSize());
133
134 vpImage<vpRGBa> rgba;
135 vpImageConvert::convert(gray, rgba);
136 CHECK((rgba == rgba_ref));
137 }
138}
139
140TEST_CASE("RGBa to Gray conversion", "[image_conversion]")
141{
142 SECTION("Image 1x16 (SSE41 aligned=true)")
143 {
144 unsigned int h = 1, w = 16;
145 vpImage<vpRGBa> rgba(h, w);
146 common_tools::fill(rgba);
147
148 vpImage<unsigned char> gray_ref(h, w);
149 common_tools::RGBaToGrayRef(reinterpret_cast<unsigned char *>(rgba.bitmap), gray_ref.bitmap, rgba.getSize());
150
151 vpImage<unsigned char> gray(h, w);
152 vpImageConvert::convert(rgba, gray);
153 double error = 0;
154 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
155 std::cout << "RGBa to Gray conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
156 }
157 SECTION("Image 1x17 (SSE41 aligned=false)")
158 {
159 unsigned int h = 1, w = 17;
160 vpImage<vpRGBa> rgba(h, w);
161 common_tools::fill(rgba);
162
163 vpImage<unsigned char> gray_ref(h, w);
164 common_tools::RGBaToGrayRef(reinterpret_cast<unsigned char *>(rgba.bitmap), gray_ref.bitmap, rgba.getSize());
165
166 vpImage<unsigned char> gray(h, w);
167 vpImageConvert::convert(rgba, gray);
168 double error = 0;
169 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
170 std::cout << "RGBa to Gray conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
171 }
172 SECTION("Image 1x32 (AVX2 aligned=true)")
173 {
174 unsigned int h = 1, w = 32;
175 vpImage<vpRGBa> rgba(h, w);
176 common_tools::fill(rgba);
177
178 vpImage<unsigned char> gray_ref(h, w);
179 common_tools::RGBaToGrayRef(reinterpret_cast<unsigned char *>(rgba.bitmap), gray_ref.bitmap, rgba.getSize());
180
181 vpImage<unsigned char> gray(h, w);
182 vpImageConvert::convert(rgba, gray);
183 double error = 0;
184 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
185 std::cout << "RGBa to Gray conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
186 }
187 SECTION("Image 1x33 (AVX2 aligned=false)")
188 {
189 unsigned int h = 1, w = 33;
190 vpImage<vpRGBa> rgba(h, w);
191 common_tools::fill(rgba);
192
193 vpImage<unsigned char> gray_ref(h, w);
194 common_tools::RGBaToGrayRef(reinterpret_cast<unsigned char *>(rgba.bitmap), gray_ref.bitmap, rgba.getSize());
195
196 vpImage<unsigned char> gray(h, w);
197 vpImageConvert::convert(rgba, gray);
198 double error = 0;
199 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
200 std::cout << "RGBa to Gray conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
201 }
202 SECTION("Image 4x64 (general aligned = true")
203 {
204 unsigned int h = 4, w = 64;
205 vpImage<vpRGBa> rgba(h, w);
206 common_tools::fill(rgba);
207
208 vpImage<unsigned char> gray_ref(h, w);
209 common_tools::RGBaToGrayRef(reinterpret_cast<unsigned char *>(rgba.bitmap), gray_ref.bitmap, rgba.getSize());
210
211 vpImage<unsigned char> gray(h, w);
212 vpImageConvert::convert(rgba, gray);
213 double error = 0;
214 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
215 std::cout << "RGBa to Gray conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
216 }
217 SECTION("Image 5x65 (general aligned = false")
218 {
219 unsigned int h = 5, w = 65;
220 vpImage<vpRGBa> rgba(h, w);
221 common_tools::fill(rgba);
222
223 vpImage<unsigned char> gray_ref(h, w);
224 common_tools::RGBaToGrayRef(reinterpret_cast<unsigned char *>(rgba.bitmap), gray_ref.bitmap, rgba.getSize());
225
226 vpImage<unsigned char> gray(h, w);
227 vpImageConvert::convert(rgba, gray);
228 double error = 0;
229 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
230 std::cout << "RGBa to Gray conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
231 }
232}
233
234TEST_CASE("RGB to Gray conversion", "[image_conversion]")
235{
236 SECTION("Image 1x16 (SSE41 aligned=true)")
237 {
238 unsigned int h = 1, w = 16;
239 std::vector<unsigned char> rgb(h * w * 3);
240 common_tools::fill(rgb);
241
242 vpImage<unsigned char> gray_ref(h, w);
243 common_tools::RGBToGrayRef(rgb.data(), gray_ref.bitmap, gray_ref.getWidth(), gray_ref.getHeight(), false);
244
245 vpImage<unsigned char> gray(h, w);
246 vpImageConvert::RGBToGrey(rgb.data(), gray.bitmap, w, h, false);
247 double error = 0;
248 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
249 std::cout << "RGB to Gray conversion 1, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
250
251 vpImage<unsigned char> gray2(h, w);
252 vpImageConvert::RGBToGrey(rgb.data(), gray2.bitmap, w * h);
253 CHECK(common_tools::almostEqual(gray_ref, gray2, maxMeanPixelError, error));
254 std::cout << "RGB to Gray conversion 2, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
255 }
256 SECTION("Image 1x17 (SSE41 aligned=false)")
257 {
258 unsigned int h = 1, w = 17;
259 std::vector<unsigned char> rgb(h * w * 3);
260 common_tools::fill(rgb);
261
262 vpImage<unsigned char> gray_ref(h, w);
263 common_tools::RGBToGrayRef(rgb.data(), gray_ref.bitmap, gray_ref.getWidth(), gray_ref.getHeight(), false);
264
265 vpImage<unsigned char> gray(h, w);
266 vpImageConvert::RGBToGrey(rgb.data(), gray.bitmap, w, h, false);
267 double error = 0;
268 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
269 std::cout << "RGB to Gray conversion 1, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
270
271 vpImage<unsigned char> gray2(h, w);
272 vpImageConvert::RGBToGrey(rgb.data(), gray2.bitmap, w * h);
273 CHECK(common_tools::almostEqual(gray_ref, gray2, maxMeanPixelError, error));
274 std::cout << "RGB to Gray conversion 2, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
275 }
276 SECTION("Image 1x32 (AVX2 aligned=true)")
277 {
278 unsigned int h = 1, w = 32;
279 std::vector<unsigned char> rgb(h * w * 3);
280 common_tools::fill(rgb);
281
282 vpImage<unsigned char> gray_ref(h, w);
283 common_tools::RGBToGrayRef(rgb.data(), gray_ref.bitmap, gray_ref.getWidth(), gray_ref.getHeight(), false);
284
285 vpImage<unsigned char> gray(h, w);
286 vpImageConvert::RGBToGrey(rgb.data(), gray.bitmap, w, h, false);
287 double error = 0;
288 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
289 std::cout << "RGB to Gray conversion 1, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
290 vpImage<unsigned char> gray2(h, w);
291 vpImageConvert::RGBToGrey(rgb.data(), gray2.bitmap, w * h);
292 CHECK(common_tools::almostEqual(gray_ref, gray2, maxMeanPixelError, error));
293 std::cout << "RGB to Gray conversion 2, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
294 }
295 SECTION("Image 1x33 (AVX2 aligned=false)")
296 {
297 unsigned int h = 1, w = 33;
298 std::vector<unsigned char> rgb(h * w * 3);
299 common_tools::fill(rgb);
300
301 vpImage<unsigned char> gray_ref(h, w);
302 common_tools::RGBToGrayRef(rgb.data(), gray_ref.bitmap, gray_ref.getWidth(), gray_ref.getHeight(), false);
303
304 vpImage<unsigned char> gray(h, w);
305 vpImageConvert::RGBToGrey(rgb.data(), gray.bitmap, w, h, false);
306 double error = 0;
307 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
308 std::cout << "RGB to Gray conversion 1, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
309
310 vpImage<unsigned char> gray2(h, w);
311 vpImageConvert::RGBToGrey(rgb.data(), gray2.bitmap, w * h);
312 CHECK(common_tools::almostEqual(gray_ref, gray2, maxMeanPixelError, error));
313 std::cout << "RGB to Gray conversion 2, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
314 }
315 SECTION("Image 4x64 (general aligned = true")
316 {
317 unsigned int h = 4, w = 64;
318 std::vector<unsigned char> rgb(h * w * 3);
319 common_tools::fill(rgb);
320
321 vpImage<unsigned char> gray_ref(h, w);
322 common_tools::RGBToGrayRef(rgb.data(), gray_ref.bitmap, gray_ref.getWidth(), gray_ref.getHeight(), false);
323
324 vpImage<unsigned char> gray(h, w);
325 vpImageConvert::RGBToGrey(rgb.data(), gray.bitmap, w, h, false);
326 double error = 0;
327 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
328 std::cout << "RGB to Gray conversion 1, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
329
330 vpImage<unsigned char> gray2(h, w);
331 vpImageConvert::RGBToGrey(rgb.data(), gray2.bitmap, w * h);
332 CHECK(common_tools::almostEqual(gray_ref, gray2, maxMeanPixelError, error));
333 std::cout << "RGB to Gray conversion 2, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
334 }
335 SECTION("Image 5x65 (general aligned = false")
336 {
337 unsigned int h = 5, w = 65;
338 std::vector<unsigned char> rgb(h * w * 3);
339 common_tools::fill(rgb);
340
341 vpImage<unsigned char> gray_ref(h, w);
342 common_tools::RGBToGrayRef(rgb.data(), gray_ref.bitmap, gray_ref.getWidth(), gray_ref.getHeight(), false);
343
344 vpImage<unsigned char> gray(h, w);
345 vpImageConvert::RGBToGrey(rgb.data(), gray.bitmap, w, h, false);
346 double error = 0;
347 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
348 std::cout << "RGB to Gray conversion 1, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
349
350 vpImage<unsigned char> gray2(h, w);
351 vpImageConvert::RGBToGrey(rgb.data(), gray2.bitmap, w * h);
352 CHECK(common_tools::almostEqual(gray_ref, gray2, maxMeanPixelError, error));
353 std::cout << "RGB to Gray conversion 2, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
354 }
355}
356
357TEST_CASE("RGB <==> RGBa conversion", "[image_conversion]")
358{
359 SECTION("Image 1x16 (SSE41 aligned=true)")
360 {
361 unsigned int h = 1, w = 16;
362 vpImage<vpRGBa> rgba_ref(h, w);
363 common_tools::fill(rgba_ref);
364
365 std::vector<unsigned char> rgb(h * w * 3);
366 vpImageConvert::RGBaToRGB(reinterpret_cast<unsigned char *>(rgba_ref.bitmap), rgb.data(), rgba_ref.getSize());
367
368 vpImage<vpRGBa> rgba(h, w);
369 vpImageConvert::RGBToRGBa(rgb.data(), reinterpret_cast<unsigned char *>(rgba.bitmap), rgba_ref.getSize());
370
371 CHECK((rgba == rgba_ref));
372 }
373 SECTION("Image 1x17 (SSE41 aligned=false)")
374 {
375 unsigned int h = 1, w = 17;
376 vpImage<vpRGBa> rgba_ref(h, w);
377 common_tools::fill(rgba_ref);
378
379 std::vector<unsigned char> rgb(h * w * 3);
380 vpImageConvert::RGBaToRGB(reinterpret_cast<unsigned char *>(rgba_ref.bitmap), rgb.data(), rgba_ref.getSize());
381
382 vpImage<vpRGBa> rgba(h, w);
383 vpImageConvert::RGBToRGBa(rgb.data(), reinterpret_cast<unsigned char *>(rgba.bitmap), rgba_ref.getSize());
384
385 CHECK((rgba == rgba_ref));
386 }
387 SECTION("Image 1x32 (AVX2 aligned=true)")
388 {
389 unsigned int h = 1, w = 32;
390 vpImage<vpRGBa> rgba_ref(h, w);
391 common_tools::fill(rgba_ref);
392
393 std::vector<unsigned char> rgb(h * w * 3);
394 vpImageConvert::RGBaToRGB(reinterpret_cast<unsigned char *>(rgba_ref.bitmap), rgb.data(), rgba_ref.getSize());
395
396 vpImage<vpRGBa> rgba(h, w);
397 vpImageConvert::RGBToRGBa(rgb.data(), reinterpret_cast<unsigned char *>(rgba.bitmap), rgba_ref.getSize());
398
399 CHECK((rgba == rgba_ref));
400 }
401 SECTION("Image 1x33 (AVX2 aligned=false)")
402 {
403 unsigned int h = 1, w = 33;
404 vpImage<vpRGBa> rgba_ref(h, w);
405 common_tools::fill(rgba_ref);
406
407 std::vector<unsigned char> rgb(h * w * 3);
408 vpImageConvert::RGBaToRGB(reinterpret_cast<unsigned char *>(rgba_ref.bitmap), rgb.data(), rgba_ref.getSize());
409
410 vpImage<vpRGBa> rgba(h, w);
411 vpImageConvert::RGBToRGBa(rgb.data(), reinterpret_cast<unsigned char *>(rgba.bitmap), rgba_ref.getSize());
412
413 CHECK((rgba == rgba_ref));
414 }
415 SECTION("Image 4x64 (general aligned = true")
416 {
417 unsigned int h = 4, w = 64;
418 vpImage<vpRGBa> rgba_ref(h, w);
419 common_tools::fill(rgba_ref);
420
421 std::vector<unsigned char> rgb(h * w * 3);
422 vpImageConvert::RGBaToRGB(reinterpret_cast<unsigned char *>(rgba_ref.bitmap), rgb.data(), rgba_ref.getSize());
423
424 vpImage<vpRGBa> rgba(h, w);
425 vpImageConvert::RGBToRGBa(rgb.data(), reinterpret_cast<unsigned char *>(rgba.bitmap), rgba_ref.getSize());
426
427 CHECK((rgba == rgba_ref));
428 }
429 SECTION("Image 5x65 (general aligned = false")
430 {
431 unsigned int h = 5, w = 65;
432 vpImage<vpRGBa> rgba_ref(h, w);
433 common_tools::fill(rgba_ref);
434
435 std::vector<unsigned char> rgb(h * w * 3);
436 vpImageConvert::RGBaToRGB(reinterpret_cast<unsigned char *>(rgba_ref.bitmap), rgb.data(), rgba_ref.getSize());
437
438 vpImage<vpRGBa> rgba(h, w);
439 vpImageConvert::RGBToRGBa(rgb.data(), reinterpret_cast<unsigned char *>(rgba.bitmap), rgba_ref.getSize());
440
441 CHECK((rgba == rgba_ref));
442 }
443}
444
445TEST_CASE("BGR to Gray conversion", "[image_conversion]")
446{
447 SECTION("Image 1x16 (SSE41 aligned=true)")
448 {
449 unsigned int h = 1, w = 16;
450 vpImage<vpRGBa> rgba_ref(h, w);
451 common_tools::fill(rgba_ref);
452
453 vpImage<unsigned char> gray_ref;
454 vpImageConvert::convert(rgba_ref, gray_ref);
455
456 std::vector<unsigned char> bgr;
457 common_tools::RGBaToBGR(rgba_ref, bgr);
458
459 vpImage<unsigned char> gray(gray_ref.getHeight(), gray_ref.getWidth());
460 vpImageConvert::BGRToGrey(bgr.data(), gray.bitmap, gray.getWidth(), gray.getHeight());
461
462 double error = 0;
463 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
464 std::cout << "BGR to Gray conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
465 }
466 SECTION("Image 1x17 (SSE41 aligned=false)")
467 {
468 unsigned int h = 1, w = 17;
469 vpImage<vpRGBa> rgba_ref(h, w);
470 common_tools::fill(rgba_ref);
471
472 vpImage<unsigned char> gray_ref;
473 vpImageConvert::convert(rgba_ref, gray_ref);
474
475 std::vector<unsigned char> bgr;
476 common_tools::RGBaToBGR(rgba_ref, bgr);
477
478 vpImage<unsigned char> gray(gray_ref.getHeight(), gray_ref.getWidth());
479 vpImageConvert::BGRToGrey(bgr.data(), gray.bitmap, gray.getWidth(), gray.getHeight());
480
481 double error = 0;
482 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
483 std::cout << "BGR to Gray conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
484 }
485 SECTION("Image 1x32 (AVX2 aligned=true)")
486 {
487 unsigned int h = 1, w = 32;
488 vpImage<vpRGBa> rgba_ref(h, w);
489 common_tools::fill(rgba_ref);
490
491 vpImage<unsigned char> gray_ref;
492 vpImageConvert::convert(rgba_ref, gray_ref);
493
494 std::vector<unsigned char> bgr;
495 common_tools::RGBaToBGR(rgba_ref, bgr);
496
497 vpImage<unsigned char> gray(gray_ref.getHeight(), gray_ref.getWidth());
498 vpImageConvert::BGRToGrey(bgr.data(), gray.bitmap, gray.getWidth(), gray.getHeight());
499
500 double error = 0;
501 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
502 std::cout << "BGR to Gray conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
503 }
504 SECTION("Image 1x33 (AVX2 aligned=false)")
505 {
506 unsigned int h = 1, w = 33;
507 vpImage<vpRGBa> rgba_ref(h, w);
508 common_tools::fill(rgba_ref);
509
510 vpImage<unsigned char> gray_ref;
511 vpImageConvert::convert(rgba_ref, gray_ref);
512
513 std::vector<unsigned char> bgr;
514 common_tools::RGBaToBGR(rgba_ref, bgr);
515
516 vpImage<unsigned char> gray(gray_ref.getHeight(), gray_ref.getWidth());
517 vpImageConvert::BGRToGrey(bgr.data(), gray.bitmap, gray.getWidth(), gray.getHeight());
518
519 double error = 0;
520 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
521 std::cout << "BGR to Gray conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
522 }
523 SECTION("Image 4x64 (general aligned = true")
524 {
525 unsigned int h = 4, w = 64;
526 vpImage<vpRGBa> rgba_ref(h, w);
527 common_tools::fill(rgba_ref);
528
529 vpImage<unsigned char> gray_ref;
530 vpImageConvert::convert(rgba_ref, gray_ref);
531
532 std::vector<unsigned char> bgr;
533 common_tools::RGBaToBGR(rgba_ref, bgr);
534
535 vpImage<unsigned char> gray(gray_ref.getHeight(), gray_ref.getWidth());
536 vpImageConvert::BGRToGrey(bgr.data(), gray.bitmap, gray.getWidth(), gray.getHeight());
537
538 double error = 0;
539 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
540 std::cout << "BGR to Gray conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
541 }
542 SECTION("Image 5x65 (general aligned = false")
543 {
544 unsigned int h = 5, w = 65;
545 vpImage<vpRGBa> rgba_ref(h, w);
546 common_tools::fill(rgba_ref);
547
548 vpImage<unsigned char> gray_ref;
549 vpImageConvert::convert(rgba_ref, gray_ref);
550
551 std::vector<unsigned char> bgr;
552 common_tools::RGBaToBGR(rgba_ref, bgr);
553
554 vpImage<unsigned char> gray(gray_ref.getHeight(), gray_ref.getWidth());
555 vpImageConvert::BGRToGrey(bgr.data(), gray.bitmap, gray.getWidth(), gray.getHeight());
556
557 double error = 0;
558 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
559 std::cout << "BGR to Gray conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
560 }
561}
562
563TEST_CASE("BGRa to Gray conversion", "[image_conversion]")
564{
565 SECTION("Image 1x16 (SSE41 aligned=true)")
566 {
567 unsigned int h = 1, w = 16;
568 vpImage<vpRGBa> rgba_ref(h, w);
569 common_tools::fill(rgba_ref);
570
571 vpImage<unsigned char> gray_ref;
572 vpImageConvert::convert(rgba_ref, gray_ref);
573
574 std::vector<unsigned char> bgra;
575 common_tools::RGBaToBGRa(rgba_ref, bgra);
576
577 vpImage<unsigned char> gray(gray_ref.getHeight(), gray_ref.getWidth());
578 vpImageConvert::BGRaToGrey(bgra.data(), gray.bitmap, gray.getWidth(), gray.getHeight());
579
580 double error = 0;
581 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
582 std::cout << "BGRa to Gray conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
583 }
584 SECTION("Image 1x17 (SSE41 aligned=false)")
585 {
586 unsigned int h = 1, w = 17;
587 vpImage<vpRGBa> rgba_ref(h, w);
588 common_tools::fill(rgba_ref);
589
590 vpImage<unsigned char> gray_ref;
591 vpImageConvert::convert(rgba_ref, gray_ref);
592
593 std::vector<unsigned char> bgra;
594 common_tools::RGBaToBGRa(rgba_ref, bgra);
595
596 vpImage<unsigned char> gray(gray_ref.getHeight(), gray_ref.getWidth());
597 vpImageConvert::BGRaToGrey(bgra.data(), gray.bitmap, gray.getWidth(), gray.getHeight());
598
599 double error = 0;
600 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
601 std::cout << "BGRa to Gray conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
602 }
603 SECTION("Image 1x32 (AVX2 aligned=true)")
604 {
605 unsigned int h = 1, w = 32;
606 vpImage<vpRGBa> rgba_ref(h, w);
607 common_tools::fill(rgba_ref);
608
609 vpImage<unsigned char> gray_ref;
610 vpImageConvert::convert(rgba_ref, gray_ref);
611
612 std::vector<unsigned char> bgra;
613 common_tools::RGBaToBGRa(rgba_ref, bgra);
614
615 vpImage<unsigned char> gray(gray_ref.getHeight(), gray_ref.getWidth());
616 vpImageConvert::BGRaToGrey(bgra.data(), gray.bitmap, gray.getWidth(), gray.getHeight());
617
618 double error = 0;
619 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
620 std::cout << "BGRa to Gray conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
621 }
622 SECTION("Image 1x33 (AVX2 aligned=false)")
623 {
624 unsigned int h = 1, w = 33;
625 vpImage<vpRGBa> rgba_ref(h, w);
626 common_tools::fill(rgba_ref);
627
628 vpImage<unsigned char> gray_ref;
629 vpImageConvert::convert(rgba_ref, gray_ref);
630
631 std::vector<unsigned char> bgra;
632 common_tools::RGBaToBGRa(rgba_ref, bgra);
633
634 vpImage<unsigned char> gray(gray_ref.getHeight(), gray_ref.getWidth());
635 vpImageConvert::BGRaToGrey(bgra.data(), gray.bitmap, gray.getWidth(), gray.getHeight());
636
637 double error = 0;
638 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
639 std::cout << "BGRa to Gray conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
640 }
641 SECTION("Image 4x64 (general aligned = true")
642 {
643 unsigned int h = 4, w = 64;
644 vpImage<vpRGBa> rgba_ref(h, w);
645 common_tools::fill(rgba_ref);
646
647 vpImage<unsigned char> gray_ref;
648 vpImageConvert::convert(rgba_ref, gray_ref);
649
650 std::vector<unsigned char> bgra;
651 common_tools::RGBaToBGRa(rgba_ref, bgra);
652
653 vpImage<unsigned char> gray(gray_ref.getHeight(), gray_ref.getWidth());
654 vpImageConvert::BGRaToGrey(bgra.data(), gray.bitmap, gray.getWidth(), gray.getHeight());
655
656 double error = 0;
657 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
658 std::cout << "BGRa to Gray conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
659 }
660 SECTION("Image 5x65 (general aligned = false")
661 {
662 unsigned int h = 5, w = 65;
663 vpImage<vpRGBa> rgba_ref(h, w);
664 common_tools::fill(rgba_ref);
665
666 vpImage<unsigned char> gray_ref;
667 vpImageConvert::convert(rgba_ref, gray_ref);
668
669 std::vector<unsigned char> bgra;
670 common_tools::RGBaToBGRa(rgba_ref, bgra);
671
672 vpImage<unsigned char> gray(gray_ref.getHeight(), gray_ref.getWidth());
673 vpImageConvert::BGRaToGrey(bgra.data(), gray.bitmap, gray.getWidth(), gray.getHeight());
674
675 double error = 0;
676 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
677 std::cout << "BGRa to Gray conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
678 }
679}
680
681TEST_CASE("BGRa to RGBa conversion", "[image_conversion]")
682{
683 SECTION("Image 1x16 (SSE41 aligned=true)")
684 {
685 unsigned int h = 1, w = 16;
686 vpImage<vpRGBa> rgba_ref(h, w);
687 common_tools::fill(rgba_ref);
688
689 std::vector<unsigned char> bgra_ref;
690 common_tools::RGBaToBGRa(rgba_ref, bgra_ref);
691
692 vpImage<vpRGBa> rgba(rgba_ref.getHeight(), rgba_ref.getWidth());
693 vpImageConvert::BGRaToRGBa(bgra_ref.data(), reinterpret_cast<unsigned char *>(rgba.bitmap), rgba.getWidth(),
694 rgba.getHeight());
695 double error = 0;
696 CHECK(common_tools::almostEqual(rgba_ref, rgba, maxMeanPixelError, error));
697 std::cout << "BGRa to RGBa conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
698 }
699 SECTION("Image 1x17 (SSE41 aligned=false)")
700 {
701 unsigned int h = 1, w = 17;
702 vpImage<vpRGBa> rgba_ref(h, w);
703 common_tools::fill(rgba_ref);
704
705 std::vector<unsigned char> bgra_ref;
706 common_tools::RGBaToBGRa(rgba_ref, bgra_ref);
707
708 vpImage<vpRGBa> rgba(rgba_ref.getHeight(), rgba_ref.getWidth());
709 vpImageConvert::BGRaToRGBa(bgra_ref.data(), reinterpret_cast<unsigned char *>(rgba.bitmap), rgba.getWidth(),
710 rgba.getHeight());
711 double error = 0;
712 CHECK(common_tools::almostEqual(rgba_ref, rgba, maxMeanPixelError, error));
713 std::cout << "BGRa to RGBa conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
714 }
715 SECTION("Image 1x32 (AVX2 aligned=true)")
716 {
717 unsigned int h = 1, w = 32;
718 vpImage<vpRGBa> rgba_ref(h, w);
719 common_tools::fill(rgba_ref);
720
721 std::vector<unsigned char> bgra_ref;
722 common_tools::RGBaToBGRa(rgba_ref, bgra_ref);
723
724 vpImage<vpRGBa> rgba(rgba_ref.getHeight(), rgba_ref.getWidth());
725 vpImageConvert::BGRaToRGBa(bgra_ref.data(), reinterpret_cast<unsigned char *>(rgba.bitmap), rgba.getWidth(),
726 rgba.getHeight());
727 double error = 0;
728 CHECK(common_tools::almostEqual(rgba_ref, rgba, maxMeanPixelError, error));
729 std::cout << "BGRa to RGBa conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
730 }
731 SECTION("Image 1x33 (AVX2 aligned=false)")
732 {
733 unsigned int h = 1, w = 33;
734 vpImage<vpRGBa> rgba_ref(h, w);
735 common_tools::fill(rgba_ref);
736
737 std::vector<unsigned char> bgra_ref;
738 common_tools::RGBaToBGRa(rgba_ref, bgra_ref);
739
740 vpImage<vpRGBa> rgba(rgba_ref.getHeight(), rgba_ref.getWidth());
741 vpImageConvert::BGRaToRGBa(bgra_ref.data(), reinterpret_cast<unsigned char *>(rgba.bitmap), rgba.getWidth(),
742 rgba.getHeight());
743 double error = 0;
744 CHECK(common_tools::almostEqual(rgba_ref, rgba, maxMeanPixelError, error));
745 std::cout << "BGRa to RGBa conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
746 }
747 SECTION("Image 4x64 (general aligned = true")
748 {
749 unsigned int h = 4, w = 64;
750 vpImage<vpRGBa> rgba_ref(h, w);
751 common_tools::fill(rgba_ref);
752
753 std::vector<unsigned char> bgra_ref;
754 common_tools::RGBaToBGRa(rgba_ref, bgra_ref);
755
756 vpImage<vpRGBa> rgba(rgba_ref.getHeight(), rgba_ref.getWidth());
757 vpImageConvert::BGRaToRGBa(bgra_ref.data(), reinterpret_cast<unsigned char *>(rgba.bitmap), rgba.getWidth(),
758 rgba.getHeight());
759 double error = 0;
760 CHECK(common_tools::almostEqual(rgba_ref, rgba, maxMeanPixelError, error));
761 std::cout << "BGRa to RGBa conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
762 }
763 SECTION("Image 5x65 (general aligned = false")
764 {
765 unsigned int h = 5, w = 65;
766 vpImage<vpRGBa> rgba_ref(h, w);
767 common_tools::fill(rgba_ref);
768
769 std::vector<unsigned char> bgra_ref;
770 common_tools::RGBaToBGRa(rgba_ref, bgra_ref);
771
772 vpImage<vpRGBa> rgba(rgba_ref.getHeight(), rgba_ref.getWidth());
773 vpImageConvert::BGRaToRGBa(bgra_ref.data(), reinterpret_cast<unsigned char *>(rgba.bitmap), rgba.getWidth(),
774 rgba.getHeight());
775 double error = 0;
776 CHECK(common_tools::almostEqual(rgba_ref, rgba, maxMeanPixelError, error));
777 std::cout << "BGRa to RGBa conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
778 }
779}
780
781TEST_CASE("Split <==> Merge conversion", "[image_conversion]")
782{
783 vpImage<vpRGBa> rgba_ref(height, width);
784 common_tools::fill(rgba_ref);
785
786 vpImage<unsigned char> R, G, B, A;
787 vpImageConvert::split(rgba_ref, &R, &G, &B, &A);
788
789 vpImage<vpRGBa> rgba;
790 vpImageConvert::merge(&R, &G, &B, &A, rgba);
791
792 CHECK((rgba == rgba_ref));
793}
794
795#if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
796TEST_CASE("OpenCV Mat <==> vpImage conversion", "[image_conversion]")
797{
798 SECTION("CV_8UC3 to vpRGBa")
799 {
800 cv::Mat img(height, width, CV_8UC3);
801 common_tools::fill(img);
802
803 vpImage<vpRGBa> rgba_ref(height, width);
804 common_tools::BGRToRGBaRef(img.data, reinterpret_cast<unsigned char *>(rgba_ref.bitmap), img.cols, img.rows, false);
805
806 vpImage<vpRGBa> rgba;
807 vpImageConvert::convert(img, rgba);
808 CHECK((rgba_ref == rgba));
809 }
810
811 SECTION("CV_8UC1 to vpRGBa")
812 {
813 cv::Mat img(height, width, CV_8UC1);
814 common_tools::fill(img);
815
816 vpImage<vpRGBa> rgba_ref(height, width);
817 common_tools::grayToRGBaRef(img.data, reinterpret_cast<unsigned char *>(rgba_ref.bitmap), height * width);
818
819 vpImage<vpRGBa> rgba;
820 vpImageConvert::convert(img, rgba);
821 CHECK((rgba_ref == rgba));
822 }
823
824 SECTION("CV_8UC3 to unsigned char")
825 {
826 cv::Mat img(height, width, CV_8UC3);
827 common_tools::fill(img);
828
829 vpImage<unsigned char> gray_ref(height, width);
830 common_tools::BGRToGrayRef(img.data, gray_ref.bitmap, img.cols, img.rows, false);
831
833 vpImageConvert::convert(img, gray);
834 double error = 0;
835 CHECK(common_tools::almostEqual(gray_ref, gray, maxMeanPixelError, error));
836 std::cout << "BGR to Gray conversion, mean error: " << error << " max allowed: " << maxMeanPixelError << std::endl;
837 }
838
839 SECTION("CV_8UC1 to unsigned char")
840 {
841 cv::Mat img(height, width, CV_8UC1);
842 common_tools::fill(img);
843
845 vpImageConvert::convert(img, gray);
846
847 REQUIRE(gray.getHeight() == height);
848 REQUIRE(gray.getWidth() == width);
849
850 for (int i = 0; i < img.rows; i++) {
851 for (int j = 0; j < img.cols; j++) {
852 REQUIRE(img.at<uchar>(i, j) == gray[i][j]);
853 }
854 }
855 }
856
857 SECTION("CV_16UC1 to uint16_t")
858 {
859 // Test when data in cv::Mat is continuous
860 unsigned int w = 3, h = 3;
861 cv::Mat img = (cv::Mat_<uint16_t>(h, w) << 65, 650, 6500, 65000, 60000, 6000, 600, 60, 6);
862 vpImage<uint16_t> gray16;
863 vpImageConvert::convert(img, gray16);
864
865 REQUIRE(gray16.getHeight() == h);
866 REQUIRE(gray16.getWidth() == w);
867
868 for (int i = 0; i < img.rows; i++) {
869 for (int j = 0; j < img.cols; j++) {
870 REQUIRE(img.at<uint16_t>(i, j) == gray16[i][j]);
871 }
872 }
873
874 // Test when data in cv::Mat is discontinuous
875 cv::Mat img_col1 = img.col(1);
876 vpImage<uint16_t> gray16_col1;
877 vpImageConvert::convert(img_col1, gray16_col1);
878
879 REQUIRE(gray16_col1.getHeight() == h);
880 REQUIRE(gray16_col1.getWidth() == 1);
881
882 for (int i = 0; i < img_col1.rows; i++) {
883 for (int j = 0; j < img_col1.cols; j++) {
884 REQUIRE(img_col1.at<uint16_t>(i, j) == gray16_col1[i][j]);
885 }
886 }
887 }
888}
889#endif
890
891#if (VISP_HAVE_DATASET_VERSION >= 0x030500)
892void col2im(const std::vector<uint8_t> &buffer, vpImage<uint8_t> &I_Bayer_8U)
893{
894 for (unsigned int i = 0; i < I_Bayer_8U.getHeight(); i++) {
895 for (unsigned int j = 0; j < I_Bayer_8U.getWidth(); j++) {
896 I_Bayer_8U[i][j] = buffer[j * I_Bayer_8U.getHeight() + i];
897 }
898 }
899}
900
901static void col2im(const std::vector<uint16_t> &buffer, vpImage<uint16_t> &I_Bayer_16U)
902{
903 for (unsigned int i = 0; i < I_Bayer_16U.getHeight(); i++) {
904 for (unsigned int j = 0; j < I_Bayer_16U.getWidth(); j++) {
905 I_Bayer_16U[i][j] = buffer[j * I_Bayer_16U.getHeight() + i];
906 }
907 }
908}
909
910static void convertTo(const vpImage<uint16_t> &I_RGBA_16U, vpImage<vpRGBa> &I_RGBA_8U, int divisor = 1 << (12 - 8))
911{
912 float divisor_ = static_cast<float>(divisor);
913 for (unsigned int i = 0; i < I_RGBA_8U.getHeight(); i++) {
914 for (unsigned int j = 0; j < I_RGBA_8U.getWidth(); j++) {
915 I_RGBA_8U[i][j] = vpRGBa(
916 vpMath::saturate<unsigned char>(I_RGBA_16U[0][(i * I_RGBA_8U.getWidth() + j) * 4 + 0] / divisor_),
917 vpMath::saturate<unsigned char>(I_RGBA_16U[0][(i * I_RGBA_8U.getWidth() + j) * 4 + 1] / divisor_),
918 vpMath::saturate<unsigned char>(I_RGBA_16U[0][(i * I_RGBA_8U.getWidth() + j) * 4 + 2] / divisor_));
919 }
920 }
921}
922
923static double computePSNR(const vpImage<vpRGBa> &I_RGBA_8U, const vpImage<vpRGBa> &I_RGBA_8U_ref)
924{
925 double mse = 0;
926 for (unsigned int i = 0; i < I_RGBA_8U.getHeight(); i++) {
927 for (unsigned int j = 0; j < I_RGBA_8U.getWidth(); j++) {
928 vpColVector err = I_RGBA_8U[i][j] - I_RGBA_8U_ref[i][j];
929 mse += vpMath::sqr(err[0]) + vpMath::sqr(err[1]) + vpMath::sqr(err[2]);
930 }
931 }
932 mse /= I_RGBA_8U.getHeight() * I_RGBA_8U.getWidth() * 3;
933
934 return 10 * std::log10(255 * 255 / mse);
935}
936
937static bool readBinaryFile(const std::string &filename, std::vector<uint16_t> &buffer)
938{
939 std::FILE *f = std::fopen(filename.c_str(), "rb");
940 CHECK(f != nullptr);
941 if (f == nullptr) {
942 return false;
943 }
944
945 size_t sread = std::fread(&buffer[0], sizeof buffer[0], buffer.size(), f);
946 REQUIRE(sread == buffer.size());
947
948#ifdef VISP_BIG_ENDIAN
949 std::vector<uint16_t> tmp = buffer;
950 for (size_t i = 0; i < tmp.size(); i++) {
951 buffer[i] = vpEndian::swap16bits(tmp[i]);
952 }
953#endif
954 std::fclose(f);
955 return true;
956}
957
958static bool readBinaryFile(const std::string &filename, std::vector<uint8_t> &buffer)
959{
960 std::FILE *f = std::fopen(filename.c_str(), "rb");
961 CHECK(f != nullptr);
962 if (f == nullptr) {
963 return false;
964 }
965
966 size_t sread = std::fread(&buffer[0], sizeof buffer[0], buffer.size(), f);
967 REQUIRE(sread == buffer.size());
968
969 std::fclose(f);
970 return true;
971}
972
973TEST_CASE("Bayer conversion", "[image_conversion]")
974{
975 // Load original Klimt image
976 vpImage<vpRGBa> I_RGBA_8U_ref;
978
979 vpImage<vpRGBa> I_RGBA_8U(I_RGBA_8U_ref.getHeight(), I_RGBA_8U_ref.getWidth());
980 int height = I_RGBA_8U_ref.getHeight(), width = I_RGBA_8U_ref.getWidth();
981 const double min_PSNR_bilinear = 21, min_PSNR_Malvar = 24;
982
983 SECTION("16-bit")
984 {
985 std::vector<uint16_t> buffer(height * width);
986 vpImage<uint16_t> I_Bayer_16U(height, width);
987 vpImage<uint16_t> I_RGBA_16U(1, I_Bayer_16U.getHeight() * I_Bayer_16U.getWidth() * 4);
988
989 SECTION("BGGR")
990 {
991 const std::string filename =
992 vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "Bayer/Klimt_Bayer_560x558_BGGR_12bits.raw");
993 if (readBinaryFile(filename, buffer)) {
994 col2im(buffer, I_Bayer_16U);
995
996 SECTION("Bilinear")
997 {
998 vpImageConvert::demosaicBGGRToRGBaBilinear(I_Bayer_16U.bitmap, I_RGBA_16U.bitmap, I_Bayer_16U.getWidth(),
999 I_Bayer_16U.getHeight());
1000
1001 convertTo(I_RGBA_16U, I_RGBA_8U);
1002 double PSNR = computePSNR(I_RGBA_8U, I_RGBA_8U_ref);
1003 std::cout << "16-bit - BGGR - Bilinear - PSNR: " << PSNR << " min required: " << min_PSNR_bilinear << std::endl;
1004 CHECK(PSNR >= min_PSNR_bilinear);
1005 }
1006
1007 SECTION("Malvar")
1008 {
1009 vpImageConvert::demosaicBGGRToRGBaMalvar(I_Bayer_16U.bitmap, I_RGBA_16U.bitmap, I_Bayer_16U.getWidth(),
1010 I_Bayer_16U.getHeight());
1011
1012 convertTo(I_RGBA_16U, I_RGBA_8U);
1013 double PSNR = computePSNR(I_RGBA_8U, I_RGBA_8U_ref);
1014 std::cout << "16-bit - BGGR - Malvar - PSNR: " << PSNR << " min required: " << min_PSNR_Malvar << std::endl;
1015 CHECK(PSNR >= min_PSNR_Malvar);
1016 }
1017 }
1018 }
1019
1020 SECTION("GBRG")
1021 {
1022 const std::string filename =
1023 vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "Bayer/Klimt_Bayer_560x558_GBRG_12bits.raw");
1024 if (readBinaryFile(filename, buffer)) {
1025 col2im(buffer, I_Bayer_16U);
1026
1027 SECTION("Bilinear")
1028 {
1029 vpImageConvert::demosaicGBRGToRGBaBilinear(I_Bayer_16U.bitmap, I_RGBA_16U.bitmap, I_Bayer_16U.getWidth(),
1030 I_Bayer_16U.getHeight());
1031
1032 convertTo(I_RGBA_16U, I_RGBA_8U);
1033 double PSNR = computePSNR(I_RGBA_8U, I_RGBA_8U_ref);
1034 std::cout << "16-bit - GBRG - Bilinear - PSNR: " << PSNR << " min required: " << min_PSNR_bilinear << std::endl;
1035 CHECK(PSNR >= min_PSNR_bilinear);
1036 }
1037
1038 SECTION("Malvar")
1039 {
1040 vpImageConvert::demosaicGBRGToRGBaMalvar(I_Bayer_16U.bitmap, I_RGBA_16U.bitmap, I_Bayer_16U.getWidth(),
1041 I_Bayer_16U.getHeight());
1042
1043 convertTo(I_RGBA_16U, I_RGBA_8U);
1044 double PSNR = computePSNR(I_RGBA_8U, I_RGBA_8U_ref);
1045 std::cout << "16-bit - GBRG - Malvar - PSNR: " << PSNR << " min required: " << min_PSNR_Malvar << std::endl;
1046 CHECK(PSNR >= min_PSNR_Malvar);
1047 }
1048 }
1049 }
1050
1051 SECTION("GRBG")
1052 {
1053 const std::string filename =
1054 vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "Bayer/Klimt_Bayer_560x558_GRBG_12bits.raw");
1055 if (readBinaryFile(filename, buffer)) {
1056 col2im(buffer, I_Bayer_16U);
1057
1058 SECTION("Bilinear")
1059 {
1060 vpImageConvert::demosaicGRBGToRGBaBilinear(I_Bayer_16U.bitmap, I_RGBA_16U.bitmap, I_Bayer_16U.getWidth(),
1061 I_Bayer_16U.getHeight());
1062
1063 convertTo(I_RGBA_16U, I_RGBA_8U);
1064 double PSNR = computePSNR(I_RGBA_8U, I_RGBA_8U_ref);
1065 std::cout << "16-bit - GRBG - Bilinear - PSNR: " << PSNR << " min required: " << min_PSNR_bilinear << std::endl;
1066 CHECK(PSNR >= min_PSNR_bilinear);
1067 }
1068
1069 SECTION("Malvar")
1070 {
1071 vpImageConvert::demosaicGRBGToRGBaMalvar(I_Bayer_16U.bitmap, I_RGBA_16U.bitmap, I_Bayer_16U.getWidth(),
1072 I_Bayer_16U.getHeight());
1073
1074 convertTo(I_RGBA_16U, I_RGBA_8U);
1075 double PSNR = computePSNR(I_RGBA_8U, I_RGBA_8U_ref);
1076 std::cout << "16-bit - GRBG - Malvar - PSNR: " << PSNR << " min required: " << min_PSNR_Malvar << std::endl;
1077 CHECK(PSNR >= min_PSNR_Malvar);
1078 }
1079 }
1080 }
1081
1082 SECTION("RGGB")
1083 {
1084 const std::string filename =
1085 vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "Bayer/Klimt_Bayer_560x558_RGGB_12bits.raw");
1086 if (readBinaryFile(filename, buffer)) {
1087 col2im(buffer, I_Bayer_16U);
1088
1089 SECTION("Bilinear")
1090 {
1091 vpImageConvert::demosaicRGGBToRGBaBilinear(I_Bayer_16U.bitmap, I_RGBA_16U.bitmap, I_Bayer_16U.getWidth(),
1092 I_Bayer_16U.getHeight());
1093
1094 convertTo(I_RGBA_16U, I_RGBA_8U);
1095 double PSNR = computePSNR(I_RGBA_8U, I_RGBA_8U_ref);
1096 std::cout << "16-bit - RGGB - Bilinear - PSNR: " << PSNR << " min required: " << min_PSNR_bilinear << std::endl;
1097 CHECK(PSNR >= min_PSNR_bilinear);
1098 }
1099
1100 SECTION("Malvar")
1101 {
1102 vpImageConvert::demosaicRGGBToRGBaMalvar(I_Bayer_16U.bitmap, I_RGBA_16U.bitmap, I_Bayer_16U.getWidth(),
1103 I_Bayer_16U.getHeight());
1104
1105 convertTo(I_RGBA_16U, I_RGBA_8U);
1106 double PSNR = computePSNR(I_RGBA_8U, I_RGBA_8U_ref);
1107 std::cout << "16-bit - RGGB - Malvar - PSNR: " << PSNR << " min required: " << min_PSNR_Malvar << std::endl;
1108 CHECK(PSNR >= min_PSNR_Malvar);
1109 }
1110 }
1111 }
1112 }
1113
1114 SECTION("8-bit")
1115 {
1116 std::vector<uint8_t> buffer(height * width);
1117 vpImage<uint8_t> I_Bayer_8U(height, width);
1118 vpImage<vpRGBa> I_RGBA_8U(I_Bayer_8U.getHeight(), I_Bayer_8U.getWidth());
1119
1120 SECTION("BGGR")
1121 {
1122 const std::string filename =
1123 vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "Bayer/Klimt_Bayer_560x558_BGGR_08bits.raw");
1124
1125 if (readBinaryFile(filename, buffer)) {
1126 col2im(buffer, I_Bayer_8U);
1127
1128 SECTION("Bilinear")
1129 {
1130 vpImageConvert::demosaicBGGRToRGBaBilinear(I_Bayer_8U.bitmap, reinterpret_cast<uint8_t *>(I_RGBA_8U.bitmap),
1131 I_Bayer_8U.getWidth(), I_Bayer_8U.getHeight());
1132
1133 double PSNR = computePSNR(I_RGBA_8U, I_RGBA_8U_ref);
1134 std::cout << "8-bit - BGGR - Bilinear - PSNR: " << PSNR <<" min required: " << min_PSNR_bilinear << std::endl;
1135 CHECK(PSNR >= min_PSNR_bilinear);
1136 }
1137
1138 SECTION("Malvar")
1139 {
1140 vpImageConvert::demosaicBGGRToRGBaMalvar(I_Bayer_8U.bitmap, reinterpret_cast<uint8_t *>(I_RGBA_8U.bitmap),
1141 I_Bayer_8U.getWidth(), I_Bayer_8U.getHeight());
1142
1143 double PSNR = computePSNR(I_RGBA_8U, I_RGBA_8U_ref);
1144 std::cout << "8-bit - BGGR - Malvar - PSNR: " << PSNR << " min required: " << min_PSNR_Malvar << std::endl;
1145 CHECK(PSNR >= min_PSNR_Malvar);
1146 }
1147 }
1148 }
1149
1150 SECTION("GBRG")
1151 {
1152 const std::string filename =
1153 vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "Bayer/Klimt_Bayer_560x558_GBRG_08bits.raw");
1154
1155 if (readBinaryFile(filename, buffer)) {
1156 col2im(buffer, I_Bayer_8U);
1157
1158 SECTION("Bilinear")
1159 {
1160 vpImageConvert::demosaicGBRGToRGBaBilinear(I_Bayer_8U.bitmap, reinterpret_cast<uint8_t *>(I_RGBA_8U.bitmap),
1161 I_Bayer_8U.getWidth(), I_Bayer_8U.getHeight());
1162
1163 double PSNR = computePSNR(I_RGBA_8U, I_RGBA_8U_ref);
1164 std::cout << "8-bit - GBRG - Bilinear - PSNR: " << PSNR << " min required: " << min_PSNR_bilinear << std::endl;
1165 CHECK(PSNR >= min_PSNR_bilinear);
1166 }
1167
1168 SECTION("Malvar")
1169 {
1170 vpImageConvert::demosaicGBRGToRGBaMalvar(I_Bayer_8U.bitmap, reinterpret_cast<uint8_t *>(I_RGBA_8U.bitmap),
1171 I_Bayer_8U.getWidth(), I_Bayer_8U.getHeight());
1172
1173 double PSNR = computePSNR(I_RGBA_8U, I_RGBA_8U_ref);
1174 std::cout << "8-bit - GBRG - Malvar - PSNR: " << PSNR << " min required: " << min_PSNR_Malvar << std::endl;
1175 CHECK(PSNR >= min_PSNR_Malvar);
1176 }
1177 }
1178 }
1179
1180 SECTION("GRBG")
1181 {
1182 const std::string filename =
1183 vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "Bayer/Klimt_Bayer_560x558_GRBG_08bits.raw");
1184
1185 if (readBinaryFile(filename, buffer)) {
1186 col2im(buffer, I_Bayer_8U);
1187
1188 SECTION("Bilinear")
1189 {
1190 vpImageConvert::demosaicGRBGToRGBaBilinear(I_Bayer_8U.bitmap, reinterpret_cast<uint8_t *>(I_RGBA_8U.bitmap),
1191 I_Bayer_8U.getWidth(), I_Bayer_8U.getHeight());
1192
1193 double PSNR = computePSNR(I_RGBA_8U, I_RGBA_8U_ref);
1194 std::cout << "8-bit - GRBG - Bilinear - PSNR: " << PSNR << " min required: " << min_PSNR_bilinear << std::endl;
1195 CHECK(PSNR >= min_PSNR_bilinear);
1196 }
1197
1198 SECTION("Malvar")
1199 {
1200 vpImageConvert::demosaicGRBGToRGBaMalvar(I_Bayer_8U.bitmap, reinterpret_cast<uint8_t *>(I_RGBA_8U.bitmap),
1201 I_Bayer_8U.getWidth(), I_Bayer_8U.getHeight());
1202
1203 double PSNR = computePSNR(I_RGBA_8U, I_RGBA_8U_ref);
1204 std::cout << "8-bit - GRBG - Malvar - PSNR: " << PSNR << " min required: " << min_PSNR_Malvar << std::endl;
1205 CHECK(PSNR >= min_PSNR_Malvar);
1206 }
1207 }
1208 }
1209
1210 SECTION("RGGB")
1211 {
1212 const std::string filename =
1213 vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "Bayer/Klimt_Bayer_560x558_RGGB_08bits.raw");
1214
1215 if (readBinaryFile(filename, buffer)) {
1216 col2im(buffer, I_Bayer_8U);
1217
1218 SECTION("Bilinear")
1219 {
1220 vpImageConvert::demosaicRGGBToRGBaBilinear(I_Bayer_8U.bitmap, reinterpret_cast<uint8_t *>(I_RGBA_8U.bitmap),
1221 I_Bayer_8U.getWidth(), I_Bayer_8U.getHeight());
1222
1223 double PSNR = computePSNR(I_RGBA_8U, I_RGBA_8U_ref);
1224 std::cout << "8-bit - RGGB - Bilinear - PSNR: " << PSNR << " min required: " << min_PSNR_bilinear << std::endl;
1225 CHECK(PSNR >= min_PSNR_bilinear);
1226 }
1227
1228 SECTION("Malvar")
1229 {
1230 vpImageConvert::demosaicRGGBToRGBaMalvar(I_Bayer_8U.bitmap, reinterpret_cast<uint8_t *>(I_RGBA_8U.bitmap),
1231 I_Bayer_8U.getWidth(), I_Bayer_8U.getHeight());
1232
1233 double PSNR = computePSNR(I_RGBA_8U, I_RGBA_8U_ref);
1234 std::cout << "8-bit - RGGB - Malvar - PSNR: " << PSNR << " min required: " << min_PSNR_Malvar << std::endl;
1235 CHECK(PSNR >= min_PSNR_Malvar);
1236 }
1237 }
1238 }
1239 }
1240}
1241#endif
1242
1243template<typename Type>
1244bool test_hsv(const std::vector<Type> &hue, const std::vector<Type> &saturation,
1245 const std::vector<Type> &value, const std::vector< std::vector<unsigned char> > &rgb_truth,
1246 const std::vector< std::vector<double> > &hsv_truth, size_t step, size_t size, double max_range)
1247{
1248 // Compare HSV values
1249 for (size_t i = 0; i < size; ++i) {
1250 if (!vpMath::equal(hue[i]*max_range, static_cast<Type>(hsv_truth[i][0])) ||
1251 !vpMath::equal(saturation[i]*max_range, static_cast<Type>(hsv_truth[i][1])) ||
1252 !vpMath::equal(value[i]*max_range, static_cast<Type>(hsv_truth[i][2]))) {
1253 if (step == 3) {
1254 std::cout << "Error in rgb to hsv conversion for rgb (";
1255 }
1256 else {
1257 std::cout << "Error in rgba to hsv conversion for rgba (";
1258 }
1259 std::cout << static_cast<int>(rgb_truth[i][0]) << ","
1260 << static_cast<int>(rgb_truth[i][1]) << ","
1261 << static_cast<int>(rgb_truth[i][2]) << "): Expected hsv value: ("
1262 << static_cast<Type>(hsv_truth[i][0]) << ","
1263 << static_cast<Type>(hsv_truth[i][1]) << ","
1264 << static_cast<Type>(hsv_truth[i][2]) << ") converted value: ("
1265 << static_cast<Type>(hue[i]*max_range) << ","
1266 << static_cast<Type>(saturation[i]*max_range) << ","
1267 << static_cast<Type>(value[i]*max_range) << ")" << std::endl;
1268 return false;
1269 }
1270 }
1271 return true;
1272}
1273
1274bool test_rgb(const std::vector<unsigned char> &rgb, const std::vector< std::vector<unsigned char> > rgb_truth,
1275 const std::vector< std::vector<double> > &hsv_truth, size_t step, size_t size, double epsilon = 0.)
1276{
1277 // Compare RGB values
1278 if (epsilon > 0.) {
1279 for (size_t i = 0; i < size; ++i) {
1280 if ((!vpMath::equal(rgb[i*step], rgb_truth[i][0], epsilon)) ||
1281 (!vpMath::equal(rgb[i*step+1], rgb_truth[i][1], epsilon)) ||
1282 (!vpMath::equal(rgb[i*step+2], rgb_truth[i][2], epsilon))) {
1283 std::cout << "Error in hsv to rgb conversion for hsv ("
1284 << static_cast<int>(hsv_truth[i][0]) << ","
1285 << static_cast<int>(hsv_truth[i][1]) << ","
1286 << static_cast<int>(hsv_truth[i][2]) << "): Expected rgb value: ("
1287 << static_cast<int>(rgb_truth[i][0]) << ","
1288 << static_cast<int>(rgb_truth[i][1]) << ","
1289 << static_cast<int>(rgb_truth[i][2]) << ") converted value: ("
1290 << static_cast<int>(rgb[i*step]) << ","
1291 << static_cast<int>(rgb[(i*step)+1]) << ","
1292 << static_cast<int>(rgb[(i*step)+2]) << ") epsilon: " << epsilon << std::endl;
1293 return false;
1294 }
1295 }
1296 }
1297 else {
1298 for (size_t i = 0; i < size; ++i) {
1299 if ((rgb[i*step] != rgb_truth[i][0]) || (rgb[i*step+1] != rgb_truth[i][1]) || (rgb[i*step+2] != rgb_truth[i][2])) {
1300 std::cout << "Error in hsv to rgb conversion for hsv ("
1301 << static_cast<int>(hsv_truth[i][0]) << ","
1302 << static_cast<int>(hsv_truth[i][1]) << ","
1303 << static_cast<int>(hsv_truth[i][2]) << "): Expected rgb value: ("
1304 << static_cast<int>(rgb_truth[i][0]) << ","
1305 << static_cast<int>(rgb_truth[i][1]) << ","
1306 << static_cast<int>(rgb_truth[i][2]) << ") converted value: ("
1307 << static_cast<int>(rgb[i*step]) << ","
1308 << static_cast<int>(rgb[(i*step)+1]) << ","
1309 << static_cast<int>(rgb[(i*step)+2]) << ")" << std::endl;
1310 return false;
1311 }
1312 }
1313 }
1314
1315 return true;
1316}
1317
1318TEST_CASE("RGB to HSV conversion", "[image_conversion]")
1319{
1320 std::vector< std::vector<unsigned char> > rgb_truth;
1321 rgb_truth.push_back({ 0, 0, 0 });
1322 rgb_truth.push_back({ 255, 255, 255 });
1323 rgb_truth.push_back({ 255, 0, 0 });
1324 rgb_truth.push_back({ 0, 255, 0 });
1325 rgb_truth.push_back({ 0, 0, 255 });
1326 rgb_truth.push_back({ 255, 255, 0 });
1327 rgb_truth.push_back({ 0, 255, 255 });
1328 rgb_truth.push_back({ 255, 0, 255 });
1329 rgb_truth.push_back({ 128, 128, 128 });
1330 rgb_truth.push_back({ 128, 128, 0 });
1331 rgb_truth.push_back({ 128, 0, 0 });
1332 rgb_truth.push_back({ 0, 128, 0 });
1333 rgb_truth.push_back({ 0, 128, 128 });
1334 rgb_truth.push_back({ 0, 0, 128 });
1335 rgb_truth.push_back({ 128, 0, 128 });
1336
1337 double h_max;
1338 bool h_full;
1339
1340 for (size_t test = 0; test < 2; ++test) {
1341 if (test == 0) {
1342 h_max = 255;
1343 h_full = true;
1344 }
1345 else {
1346 h_max = 180;
1347 h_full = false;
1348 }
1349 std::vector< std::vector<double> > hsv_truth;
1350 // See https://www.rapidtables.com/convert/color/hsv-to-rgb.html
1351 hsv_truth.push_back({ 0, 0, 0 });
1352 hsv_truth.push_back({ 0, 0, 255 });
1353 hsv_truth.push_back({ 0, 255, 255 });
1354 hsv_truth.push_back({ h_max * 120 / 360, 255, 255 });
1355 hsv_truth.push_back({ h_max * 240 / 360, 255, 255 });
1356 hsv_truth.push_back({ h_max * 60 / 360, 255, 255 });
1357 hsv_truth.push_back({ h_max * 180 / 360, 255, 255 });
1358 hsv_truth.push_back({ h_max * 300 / 360, 255, 255 });
1359 hsv_truth.push_back({ 0, 0, 128 });
1360 hsv_truth.push_back({ h_max * 60 / 360, 255, 128 });
1361 hsv_truth.push_back({ 0, 255, 128 });
1362 hsv_truth.push_back({ h_max * 120 / 360, 255, 128 });
1363 hsv_truth.push_back({ h_max * 180 / 360, 255, 128 });
1364 hsv_truth.push_back({ h_max * 240 / 360, 255, 128 });
1365 hsv_truth.push_back({ h_max * 300 / 360, 255, 128 });
1366
1367 size_t size = rgb_truth.size();
1368
1369 std::vector<unsigned char> rgb_truth_continuous;
1370 for (size_t i = 0; i < size; ++i) {
1371 for (size_t j = 0; j < rgb_truth[i].size(); ++j) {
1372 rgb_truth_continuous.push_back(rgb_truth[i][j]);
1373 }
1374 }
1375 std::vector<unsigned char> rgba_truth_continuous;
1376 for (size_t i = 0; i < size; ++i) {
1377 for (size_t j = 0; j < rgb_truth[i].size(); ++j) {
1378 rgba_truth_continuous.push_back(rgb_truth[i][j]);
1379 }
1380 rgba_truth_continuous.push_back(vpRGBa::alpha_default);
1381 }
1382 SECTION("RGB -> HSV (unsigned char) -> RGB")
1383 {
1384 std::vector<unsigned char> hue(size);
1385 std::vector<unsigned char> saturation(size);
1386 std::vector<unsigned char> value(size);
1387 std::cout << "Test rgb -> hsv (unsigned char) conversion with h full scale: " << (h_full ? "yes" : "no") << std::endl;
1388 vpImageConvert::RGBToHSV(reinterpret_cast<unsigned char *>(&rgb_truth_continuous.front()),
1389 reinterpret_cast<unsigned char *>(&hue.front()),
1390 reinterpret_cast<unsigned char *>(&saturation.front()),
1391 reinterpret_cast<unsigned char *>(&value.front()), static_cast<unsigned int>(size), h_full);
1392 CHECK(test_hsv(hue, saturation, value, rgb_truth, hsv_truth, 3, size, 1.));
1393
1394 std::cout << "Test hsv (unsigned char) -> rgb conversion with h full scale: " << (h_full ? "yes" : "no") << std::endl;
1395 std::vector< unsigned char> rgb_continuous(rgb_truth_continuous.size() * 3);
1396 vpImageConvert::HSVToRGB(&hue.front(), &saturation.front(), &value.front(), &rgb_continuous.front(), static_cast<unsigned int>(size), h_full);
1397 CHECK(test_rgb(rgb_continuous, rgb_truth, hsv_truth, 3, size, 5.));
1398 }
1399 SECTION("RGBa -> HSV (unsigned char) -> RGBa")
1400 {
1401 std::vector<unsigned char> hue(size);
1402 std::vector<unsigned char> saturation(size);
1403 std::vector<unsigned char> value(size);
1404 std::cout << "Test rgba -> hsv (unsigned char) conversion with h full scale: " << (h_full ? "yes" : "no") << std::endl;
1405 vpImageConvert::RGBaToHSV(reinterpret_cast<unsigned char *>(&rgba_truth_continuous.front()),
1406 reinterpret_cast<unsigned char *>(&hue.front()),
1407 reinterpret_cast<unsigned char *>(&saturation.front()),
1408 reinterpret_cast<unsigned char *>(&value.front()), static_cast<unsigned int>(size), h_full);
1409 CHECK(test_hsv(hue, saturation, value, rgb_truth, hsv_truth, 4, size, 1.));
1410
1411 std::cout << "Test hsv (unsigned char) -> rgba conversion with h full scale: " << (h_full ? "yes" : "no") << std::endl;
1412 std::vector< unsigned char> rgba_continuous(rgb_truth_continuous.size() * 4);
1413 vpImageConvert::HSVToRGBa(&hue.front(), &saturation.front(), &value.front(), &rgba_continuous.front(), static_cast<unsigned int>(size), h_full);
1414 CHECK(test_rgb(rgba_continuous, rgb_truth, hsv_truth, 4, size, 5.));
1415 }
1416 if (h_full) {
1417 SECTION("RGB -> HSV (double) -> RGB")
1418 {
1419 std::vector<double> hue(size);
1420 std::vector<double> saturation(size);
1421 std::vector<double> value(size);
1422 vpImageConvert::RGBToHSV(reinterpret_cast<unsigned char *>(&rgb_truth_continuous.front()),
1423 reinterpret_cast<double *>(&hue.front()),
1424 reinterpret_cast<double *>(&saturation.front()),
1425 reinterpret_cast<double *>(&value.front()), static_cast<unsigned int>(size));
1426 CHECK(test_hsv(hue, saturation, value, rgb_truth, hsv_truth, 3, size, 255.));
1427
1428 std::cout << "Test hsv (double) -> rgb conversion" << std::endl;
1429 std::vector< unsigned char> rgb_continuous(rgb_truth_continuous.size());
1430 vpImageConvert::HSVToRGB(&hue.front(), &saturation.front(), &value.front(), &rgb_continuous.front(), static_cast<unsigned int>(size));
1431 CHECK(test_rgb(rgb_continuous, rgb_truth, hsv_truth, 3, size));
1432 }
1433 }
1434
1435 if (h_full) {
1436 SECTION("RGBa -> HSV (double) -> RGBa")
1437 {
1438 std::vector<double> hue(size);
1439 std::vector<double> saturation(size);
1440 std::vector<double> value(size);
1441 std::cout << "Test rgba -> hsv (double) conversion" << std::endl;
1442 vpImageConvert::RGBaToHSV(reinterpret_cast<unsigned char *>(&rgba_truth_continuous.front()),
1443 reinterpret_cast<double *>(&hue.front()),
1444 reinterpret_cast<double *>(&saturation.front()),
1445 reinterpret_cast<double *>(&value.front()), static_cast<unsigned int>(size));
1446 CHECK(test_hsv(hue, saturation, value, rgb_truth, hsv_truth, 4, size, 255.));
1447
1448 std::cout << "Test hsv (double) -> rgba conversion" << std::endl;
1449 std::vector< unsigned char> rgba_continuous(rgb_truth_continuous.size()*4);
1450 vpImageConvert::HSVToRGBa(&hue.front(), &saturation.front(), &value.front(), &rgba_continuous.front(), static_cast<unsigned int>(size));
1451 CHECK(test_rgb(rgba_continuous, rgb_truth, hsv_truth, 4, size));
1452 }
1453 }
1454 }
1455}
1456
1457int main(int argc, char *argv[])
1458{
1459 Catch::Session session;
1460 session.applyCommandLine(argc, argv);
1461 int numFailed = session.run();
1462 std::cout << (numFailed ? "Test failed" : "Test succeed") << std::endl;
1463 return numFailed;
1464}
1465#else
1466int main() { return EXIT_SUCCESS; }
1467#endif
Implementation of column vector and the associated operations.
static void HSVToRGBa(const double *hue, const double *saturation, const double *value, unsigned char *rgba, unsigned int size)
static void demosaicBGGRToRGBaBilinear(const uint8_t *bggr, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void demosaicGRBGToRGBaBilinear(const uint8_t *grbg, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void RGBToHSV(const unsigned char *rgb, double *hue, double *saturation, double *value, unsigned int size)
static void demosaicGRBGToRGBaMalvar(const uint8_t *grbg, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void demosaicGBRGToRGBaMalvar(const uint8_t *gbrg, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void merge(const vpImage< unsigned char > *R, const vpImage< unsigned char > *G, const vpImage< unsigned char > *B, const vpImage< unsigned char > *a, vpImage< vpRGBa > &RGBa)
static void demosaicBGGRToRGBaMalvar(const uint8_t *bggr, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void demosaicGBRGToRGBaBilinear(const uint8_t *gbrg, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void split(const vpImage< vpRGBa > &src, vpImage< unsigned char > *pR, vpImage< unsigned char > *pG, vpImage< unsigned char > *pB, vpImage< unsigned char > *pa=nullptr)
static void RGBaToHSV(const unsigned char *rgba, double *hue, double *saturation, double *value, unsigned int size)
static void demosaicRGGBToRGBaMalvar(const uint8_t *rggb, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
static void RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false)
static void RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int size)
static void BGRaToGrey(unsigned char *bgra, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false, unsigned int nThreads=0)
static void BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false, unsigned int nThreads=0)
static void demosaicRGGBToRGBaBilinear(const uint8_t *rggb, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void BGRaToRGBa(unsigned char *bgra, unsigned char *rgba, unsigned int width, unsigned int height, bool flip=false)
static void RGBaToRGB(unsigned char *rgba, unsigned char *rgb, unsigned int size)
static void HSVToRGB(const double *hue, const double *saturation, const double *value, unsigned char *rgb, unsigned int size)
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition of the vpImage class member functions.
Definition vpImage.h:131
unsigned int getWidth() const
Definition vpImage.h:242
unsigned int getSize() const
Definition vpImage.h:221
Type * bitmap
points toward the bitmap
Definition vpImage.h:135
unsigned int getHeight() const
Definition vpImage.h:181
static std::string getViSPImagesDataPath()
static std::string createFilePath(const std::string &parent, const std::string &child)
static Tp saturate(unsigned char v)
Definition vpMath.h:306
static double sqr(double x)
Definition vpMath.h:203
static bool equal(double x, double y, double threshold=0.001)
Definition vpMath.h:470
@ alpha_default
Definition vpRGBa.h:76
VISP_EXPORT uint16_t swap16bits(uint16_t val)
Definition vpEndian.cpp:48