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