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