Visual Servoing Platform  version 3.5.0 under development (2022-02-15)
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 
52 static const double maxMeanPixelError = 1.5; // conversion to gray produce an error = 1.0
53 static const unsigned int width = 223, height = 151;
54 
55 TEST_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 
136 TEST_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 
229 TEST_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 
351 TEST_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 
438 TEST_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 
555 TEST_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 
672 TEST_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 
765 TEST_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
779 TEST_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 
841 void 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 
850 void 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 
859 void 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 
870 double 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 
884 void 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 
899 TEST_CASE("Bayer conversion", "[image_conversion]") {
900  // Load original Klimt image
901  vpImage<vpRGBa> I_RGBA_8U_ref;
902  vpImageIo::read(I_RGBA_8U_ref, vpIoTools::createFilePath(vpIoTools::getViSPImagesDataPath(), "Klimt/Klimt.ppm"));
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 
1155 int 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
1170 int main()
1171 {
1172  return 0;
1173 }
1174 #endif
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:149
static void demosaicBGGRToRGBaBilinear(const uint8_t *bggr, 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 std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1365
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
static void RGBToRGBa(unsigned char *rgb, unsigned char *rgba, unsigned int size)
Type * bitmap
points toward the bitmap
Definition: vpImage.h:143
static void BGRaToRGBa(unsigned char *bgra, unsigned char *rgba, unsigned int width, unsigned int height, bool flip=false)
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 demosaicGRBGToRGBaBilinear(const uint8_t *grbg, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
Definition: vpRGBa.h:66
static void RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false)
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1670
static void demosaicGBRGToRGBaBilinear(const uint8_t *gbrg, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static double sqr(double x)
Definition: vpMath.h:116
VISP_EXPORT uint16_t swap16bits(uint16_t val)
Definition: vpEndian.cpp:49
static void demosaicRGGBToRGBaBilinear(const uint8_t *rggb, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void demosaicGRBGToRGBaMalvar(const uint8_t *grbg, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
static void demosaicBGGRToRGBaMalvar(const uint8_t *bggr, 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 BGRToGrey(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false, unsigned int nThreads=0)
static void BGRaToGrey(unsigned char *bgra, unsigned char *grey, unsigned int width, unsigned int height, bool flip=false, unsigned int nThreads=0)
unsigned int getHeight() const
Definition: vpImage.h:188
Implementation of column vector and the associated operations.
Definition: vpColVector.h:130
static void RGBaToRGB(unsigned char *rgba, unsigned char *rgb, unsigned int size)
static void demosaicGBRGToRGBaMalvar(const uint8_t *gbrg, uint8_t *rgba, unsigned int width, unsigned int height, unsigned int nThreads=0)
unsigned int getWidth() const
Definition: vpImage.h:246