Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
testPerformanceLUT.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Test performance between iteration and LUT.
32 */
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <visp3/core/vpImage.h>
37#include <visp3/core/vpIoTools.h>
38#include <visp3/core/vpMath.h>
39#include <visp3/io/vpImageIo.h>
40#include <visp3/io/vpParseArgv.h>
41
42#ifdef ENABLE_VISP_NAMESPACE
43using namespace VISP_NAMESPACE_NAME;
44#endif
45
51
52// List of allowed command line options
53#define GETOPTARGS "cdi:o:t:h"
54
55void usage(const char *name, const char *badparam, const std::string &ipath, const std::string &opath,
56 const std::string &user);
57bool getOptions(int argc, const char **argv, std::string &ipath, std::string &opath, const std::string &user,
58 unsigned int &nbThreads);
59unsigned char getRandomValues(unsigned char min, unsigned char max);
60void generateRandomImage(vpImage<unsigned char> &I, unsigned int min = 0, unsigned int max = 255);
61void generateRandomImage(vpImage<vpRGBa> &I, unsigned int min = 0, unsigned int max = 255);
62void iterate_method1(vpImage<vpRGBa> &I, double alpha, double beta);
63void iterate_method1(vpImage<unsigned char> &I, double alpha, double beta);
64void iterate_method2(vpImage<vpRGBa> &I, double alpha, double beta);
65
66/*
67 * Print the program options.
68 *
69 * \param name : Program name.
70 * \param badparam : Bad parameter name.
71 * \param ipath : Input image path.
72 * \param opath : Output image path.
73 * \param user : Username.
74 */
75void usage(const char *name, const char *badparam, const std::string &ipath, const std::string &opath,
76 const std::string &user)
77{
78 fprintf(stdout, "\n\
79Test performance between methods to iterate over pixel image.\n\
80\n\
81SYNOPSIS\n\
82 %s [-i <input image path>] [-o <output image path>] [-t <nb threads>]\n\
83 [-h]\n\
84",
85name);
86
87 fprintf(stdout, "\n\
88OPTIONS: Default\n\
89 -i <input image path> %s\n\
90 Set image input path.\n\
91 From this path read \"Klimt/Klimt.pgm\"\n\
92 image.\n\
93 Setting the VISP_INPUT_IMAGE_PATH environment\n\
94 variable produces the same behaviour than using\n\
95 this option.\n\
96\n\
97 -o <output image path> %s\n\
98 Set image output path.\n\
99 From this directory, creates the \"%s\"\n\
100 subdirectory depending on the username, where \n\
101 Klimt_grey.pgm output image is written.\n\
102\n\
103 -t <nb threads> \n\
104 Set the number of threads to use for the computation.\n\
105\n\
106 -h\n\
107 Print the help.\n\n",
108 ipath.c_str(), opath.c_str(), user.c_str());
109
110 if (badparam)
111 fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
112}
113
125bool getOptions(int argc, const char **argv, std::string &ipath, std::string &opath, const std::string &user,
126 unsigned int &nbThreads)
127{
128 const char *optarg_;
129 int c;
130 while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
131
132 switch (c) {
133 case 'i':
134 ipath = optarg_;
135 break;
136 case 'o':
137 opath = optarg_;
138 break;
139 case 't':
140 nbThreads = static_cast<unsigned int>(atoi(optarg_));
141 break;
142 case 'h':
143 usage(argv[0], nullptr, ipath, opath, user);
144 return false;
145
146 case 'c':
147 case 'd':
148 break;
149
150 default:
151 usage(argv[0], optarg_, ipath, opath, user);
152 return false;
153 }
154 }
155
156 if ((c == 1) || (c == -1)) {
157 // standalone param or error
158 usage(argv[0], nullptr, ipath, opath, user);
159 std::cerr << "ERROR: " << std::endl;
160 std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
161 return false;
162 }
163
164 return true;
165}
166
167unsigned char getRandomValues(unsigned char min, unsigned char max)
168{
169 return static_cast<unsigned char>((max - min) * static_cast<double>(rand()) / static_cast<double>(RAND_MAX) + min);
170}
171
172void generateRandomImage(vpImage<unsigned char> &I, unsigned int min, unsigned int max)
173{
174 for (unsigned int i = 0; i < I.getHeight(); ++i) {
175 for (unsigned int j = 0; j < I.getWidth(); ++j) {
176 I[i][j] = getRandomValues(min, max);
177 }
178 }
179}
180
181void generateRandomImage(vpImage<vpRGBa> &I, unsigned int min, unsigned int max)
182{
183 for (unsigned int i = 0; i < I.getHeight(); ++i) {
184 for (unsigned int j = 0; j < I.getWidth(); ++j) {
185 I[i][j].R = getRandomValues(min, max);
186 I[i][j].G = getRandomValues(min, max);
187 I[i][j].B = getRandomValues(min, max);
188 I[i][j].A = getRandomValues(min, max);
189 }
190 }
191}
192
201void iterate_method1(vpImage<vpRGBa> &I, double alpha, double beta)
202{
203 unsigned int size = I.getWidth() * I.getHeight();
204 unsigned char *ptrStart = (unsigned char *)I.bitmap;
205 unsigned char *ptrEnd = ptrStart + size * 4;
206 unsigned char *ptrCurrent = ptrStart;
207
208 while (ptrCurrent != ptrEnd) {
209 *ptrCurrent = vpMath::saturate<unsigned char>((*ptrCurrent) * alpha + beta);
210 ++ptrCurrent;
211 }
212}
213
222void iterate_method1(vpImage<unsigned char> &I, double alpha, double beta)
223{
224 unsigned int size = I.getWidth() * I.getHeight();
225 unsigned char *ptrStart = (unsigned char *)I.bitmap;
226 unsigned char *ptrEnd = ptrStart + size;
227 unsigned char *ptrCurrent = ptrStart;
228
229 while (ptrCurrent != ptrEnd) {
230 *ptrCurrent = vpMath::saturate<unsigned char>((*ptrCurrent) * alpha + beta);
231 ++ptrCurrent;
232 }
233}
234
243void iterate_method2(vpImage<vpRGBa> &I, double alpha, double beta)
244{
245 for (unsigned int i = 0; i < I.getHeight(); i++) {
246 for (unsigned int j = 0; j < I.getWidth(); j++) {
247 I[i][j].R = vpMath::saturate<unsigned char>(I[i][j].R * alpha + beta);
248 I[i][j].G = vpMath::saturate<unsigned char>(I[i][j].G * alpha + beta);
249 I[i][j].B = vpMath::saturate<unsigned char>(I[i][j].B * alpha + beta);
250 I[i][j].A = vpMath::saturate<unsigned char>(I[i][j].A * alpha + beta);
251 }
252 }
253}
254
255int main(int argc, const char **argv)
256{
257 try {
258 std::string env_ipath;
259 std::string opt_ipath;
260 std::string opt_opath;
261 std::string ipath;
262 std::string opath;
263 std::string filename;
264 std::string username;
265 unsigned int nbThreads = 4;
266
267 // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
268 // environment variable value
270
271 // Set the default input path
272 if (!env_ipath.empty())
273 ipath = env_ipath;
274
275// Set the default output path
276#if defined(_WIN32)
277 opt_opath = "C:/temp";
278#else
279 opt_opath = "/tmp";
280#endif
281
282 // Get the user login name
283 vpIoTools::getUserName(username);
284
285 // Read the command line options
286 if (getOptions(argc, argv, opt_ipath, opt_opath, username, nbThreads) == false) {
287 return EXIT_FAILURE;
288 }
289
290 // Get the option values
291 if (!opt_ipath.empty())
292 ipath = opt_ipath;
293 if (!opt_opath.empty())
294 opath = opt_opath;
295
296 // Append to the output path string, the login name of the user
297 opath = vpIoTools::createFilePath(opath, username);
298
299 // Test if the output path exist. If no try to create it
300 if (vpIoTools::checkDirectory(opath) == false) {
301 try {
302 // Create the dirname
304 }
305 catch (...) {
306 usage(argv[0], nullptr, ipath, opt_opath, username);
307 std::cerr << std::endl << "ERROR:" << std::endl;
308 std::cerr << " Cannot create " << opath << std::endl;
309 std::cerr << " Check your -o " << opt_opath << " option " << std::endl;
310 return EXIT_FAILURE;
311 }
312 }
313
314 // Compare ipath and env_ipath. If they differ, we take into account
315 // the input path coming from the command line option
316 if (!opt_ipath.empty() && !env_ipath.empty()) {
317 if (ipath != env_ipath) {
318 std::cout << std::endl << "WARNING: " << std::endl;
319 std::cout << " Since -i <visp image path=" << ipath << "> "
320 << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
321 << " we skip the environment variable." << std::endl;
322 }
323 }
324
325 // Test if an input path is set
326 if (opt_ipath.empty() && env_ipath.empty()) {
327 usage(argv[0], nullptr, ipath, opt_opath, username);
328 std::cerr << std::endl << "ERROR:" << std::endl;
329 std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
330 << " environment variable to specify the location of the " << std::endl
331 << " image path where test images are located." << std::endl
332 << std::endl;
333 return EXIT_FAILURE;
334 }
335
336 double alpha = 1.5, beta = -30.0;
337 unsigned int nbIterations = 10;
338
339 //
340 // Here starts really the test
341 //
342 if (1) {
343 std::cout << "\n** Test LUT on color image" << std::endl;
344 // Create a color image
345 vpImage<vpRGBa> I_iterate1, I_iterate2, I_lut;
346
347 // Load a color image from the disk
348 filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
349 std::cout << "Read image: " << filename << std::endl;
350 vpImageIo::read(I_iterate1, filename);
351 vpImageIo::read(I_iterate2, filename);
352 vpImageIo::read(I_lut, filename);
353
354 std::cout << "Image size: " << I_iterate1.getWidth() << "x" << I_iterate1.getHeight() << std::endl;
355
356 // Iterate method 1
357 std::cout << "Run test n°1 " << nbIterations << " times" << std::endl;
358 double t_iterate1 = vpTime::measureTimeMs();
359 for (unsigned int cpt = 0; cpt < nbIterations; cpt++) {
360 iterate_method1(I_iterate1, alpha, beta);
361 }
362 t_iterate1 = vpTime::measureTimeMs() - t_iterate1;
363 std::cout << " Total time: " << t_iterate1 << " ms ; Mean time: "
364 << (t_iterate1 / nbIterations) << " ms" << std::endl;
365
366 filename = vpIoTools::createFilePath(opath, "Klimt_performance_iterate1.ppm");
367 std::cout << " Save " << filename << std::endl;
368 vpImageIo::write(I_iterate1, filename);
369
370 // Iterate method 2
371 std::cout << "Run test n°2 " << nbIterations << " times" << std::endl;
372 double t_iterate2 = vpTime::measureTimeMs();
373 for (unsigned int cpt = 0; cpt < nbIterations; cpt++) {
374 iterate_method2(I_iterate2, alpha, beta);
375 }
376 t_iterate2 = vpTime::measureTimeMs() - t_iterate2;
377 std::cout << " Total time: " << t_iterate2 << " ms ; Mean time: " << (t_iterate2 / nbIterations) << " ms" << std::endl;
378
379 filename = vpIoTools::createFilePath(opath, "Klimt_performance_iterate2.ppm");
380 std::cout << " Save " << filename << std::endl;
381 vpImageIo::write(I_iterate2, filename);
382
383 // Construct the LUT
384 vpRGBa lut[256];
385 for (unsigned int i = 0; i < 256; i++) {
386 lut[i].R = vpMath::saturate<unsigned char>(alpha * i + beta);
387 lut[i].G = vpMath::saturate<unsigned char>(alpha * i + beta);
388 lut[i].B = vpMath::saturate<unsigned char>(alpha * i + beta);
389 lut[i].A = vpMath::saturate<unsigned char>(alpha * i + beta);
390 }
391
392 // LUT method
393 std::cout << "Run test n°3 " << nbIterations << " times" << std::endl;
394 double t_lut = vpTime::measureTimeMs();
395 for (unsigned int cpt = 0; cpt < nbIterations; cpt++) {
396 I_lut.performLut(lut, nbThreads);
397 }
398 t_lut = vpTime::measureTimeMs() - t_lut;
399 std::cout << " Total time: " << t_lut << " ms ; Mean time: " << (t_lut / nbIterations) << " ms" << std::endl;
400
401 filename = vpIoTools::createFilePath(opath, "Klimt_performance_lut.ppm");
402 std::cout << " Save " << filename << std::endl;
403 vpImageIo::write(I_lut, filename);
404
405 if ((I_iterate1 == I_iterate2) && (I_iterate1 == I_lut)) {
406 std::cerr << "Color images are the same" << std::endl;
407 }
408 else {
409 std::cerr << "Color images are different!" << std::endl;
410 std::cout << "Test failed" << std::endl;
411 return EXIT_FAILURE;
412 }
413 }
414 {
415 // Test LUT on grayscale image
416 std::cout << "\n** Test LUT on grayscale image" << std::endl;
417 vpImage<unsigned char> I_iterate_grayscale1, I_lut_grayscale;
418
419 // Load a grayscale image from the disk
420 filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.pgm");
421 std::cout << "Read image: " << filename << std::endl;
422 vpImageIo::read(I_iterate_grayscale1, filename);
423 vpImageIo::read(I_lut_grayscale, filename);
424
425 std::cout << "Image size: " << I_lut_grayscale.getWidth() << "x" << I_lut_grayscale.getHeight() << std::endl;
426
427 // Iterate method 1 on grayscale
428 std::cout << "Run test n°1 " << nbIterations << " times" << std::endl;
429 double t_iterate_grayscale1 = vpTime::measureTimeMs();
430 for (unsigned int cpt = 0; cpt < nbIterations; cpt++) {
431 iterate_method1(I_iterate_grayscale1, alpha, beta);
432 }
433 t_iterate_grayscale1 = vpTime::measureTimeMs() - t_iterate_grayscale1;
434 std::cout << " Total time: " << t_iterate_grayscale1 << " ms ; Mean time: "
435 << (t_iterate_grayscale1 / nbIterations) << " ms" << std::endl;
436
437 filename = vpIoTools::createFilePath(opath, "Klimt_performance_iterate1_grayscale.pgm");
438 std::cout << " Save result in " << filename << std::endl;
439 vpImageIo::write(I_iterate_grayscale1, filename);
440
441 // Construct the LUT
442 unsigned char lut[256];
443 for (unsigned int i = 0; i < 256; i++) {
444 lut[i] = vpMath::saturate<unsigned char>(alpha * i + beta);
445 }
446
447 // LUT method on grayscale
448 std::cout << "Run test n°2 " << nbIterations << " times with " << nbThreads << " threads" << std::endl;
449 double t_lut_grayscale = vpTime::measureTimeMs();
450 for (unsigned int cpt = 0; cpt < nbIterations; cpt++) {
451 I_lut_grayscale.performLut(lut, nbThreads);
452 }
453 t_lut_grayscale = vpTime::measureTimeMs() - t_lut_grayscale;
454 std::cout << " Total time: " << t_lut_grayscale << " ms ; Mean time: "
455 << (t_lut_grayscale / nbIterations) << " ms" << std::endl;
456
457 filename = vpIoTools::createFilePath(opath, "Klimt_performance_lut_grayscale.pgm");
458 std::cout << " Save result in " << filename << std::endl;
459 vpImageIo::write(I_lut_grayscale, filename);
460
461 // Check grayscale image
462 if (I_lut_grayscale == I_iterate_grayscale1) {
463 std::cout << "Grayscale images are same" << std::endl;
464 }
465 else {
466 std::cerr << "Grayscale images are different!" << std::endl;
467 std::cout << "Test failed" << std::endl;
468 return EXIT_FAILURE;
469 }
470 }
471 {
472 std::cout << "\n** Test multi-threaded LUT on color image" << std::endl;
473 vpImage<vpRGBa> I_lut_multi, I_lut_single;
474
475 // Load a color image from the disk
476 filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
477 std::cout << "Read image: " << filename << std::endl;
478 vpImageIo::read(I_lut_multi, filename);
479
480 // Construct the LUT
481 vpRGBa lut[256];
482 for (unsigned int i = 0; i < 256; i++) {
483 lut[i].R = vpMath::saturate<unsigned char>(alpha * i + beta);
484 lut[i].G = vpMath::saturate<unsigned char>(alpha * i + beta);
485 lut[i].B = vpMath::saturate<unsigned char>(alpha * i + beta);
486 lut[i].A = vpMath::saturate<unsigned char>(alpha * i + beta);
487 }
488
489 // Computation time on color image
490 std::cout << "Run test n°1 " << nbIterations* 10 << " times with " << nbThreads << " threads" << std::endl;
491 double t_lut_multithread = vpTime::measureTimeMs();
492 for (unsigned int cpt = 0; cpt < nbIterations * 10; cpt++) {
493 I_lut_multi.performLut(lut, nbThreads);
494 }
495 t_lut_multithread = vpTime::measureTimeMs() - t_lut_multithread;
496
497 filename = vpIoTools::createFilePath(opath, "Klimt_performance_color_multi.ppm");
498 std::cout << " Save result in " << filename << std::endl;
499 vpImageIo::write(I_lut_multi, filename);
500
501 vpImageIo::read(I_lut_single, filename);
502
503 std::cout << "Run test n°2 " << nbIterations* 10 << " times in a single thread" << std::endl;
504 double t_lut_singlethread = vpTime::measureTimeMs();
505 for (unsigned int cpt = 0; cpt < nbIterations * 10; cpt++) {
506 I_lut_single.performLut(lut, 1);
507 }
508 t_lut_singlethread = vpTime::measureTimeMs() - t_lut_singlethread;
509
510 filename = vpIoTools::createFilePath(opath, "Klimt_performance_color_single.ppm");
511 std::cout << " Save result in " << filename << std::endl;
512 vpImageIo::write(I_lut_single, filename);
513
514 // Check color image
515 if (I_lut_multi == I_lut_single) {
516 std::cout << "Color images are the same" << std::endl;
517 std::cout << "Single-thread / multi-thread (color) gain: " << t_lut_singlethread / t_lut_multithread << std::endl;
518 }
519 else {
520 std::cerr << "Color images are different!" << std::endl;
521 std::cout << "Test failed" << std::endl;
522 return EXIT_FAILURE;
523 }
524 }
525 {
526 std::cout << "\n** Test multi-threaded LUT on gray image" << std::endl;
527 vpImage<unsigned char> I_lut_grayscale_multi, I_lut_grayscale_single;
528
529 // Load a gray image from the disk
530 filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.pgm");
531
532 std::cout << "Read image: " << filename << std::endl;
533 vpImageIo::read(I_lut_grayscale_multi, filename);
534
535 // Construct the LUT
536 unsigned char lut[256];
537 for (unsigned int i = 0; i < 256; i++) {
538 lut[i] = vpMath::saturate<unsigned char>(alpha * i + beta);
539 }
540
541 // Computation time on grayscale image
542 std::cout << "Run test n°1 " << nbIterations* 10 << " times with " << nbThreads << " threads" << std::endl;
543 double t_lut_multithread = vpTime::measureTimeMs();
544 for (unsigned int cpt = 0; cpt < nbIterations * 10; cpt++) {
545 I_lut_grayscale_multi.performLut(lut, nbThreads);
546 }
547 t_lut_multithread = vpTime::measureTimeMs() - t_lut_multithread;
548
549 filename = vpIoTools::createFilePath(opath, "Klimt_performance_gray_multi.pgm");
550 std::cout << " Save result in " << filename << std::endl;
551 vpImageIo::write(I_lut_grayscale_multi, filename);
552
553 vpImageIo::read(I_lut_grayscale_single, filename);
554
555 std::cout << "Run test n°2 " << nbIterations* 10 << " times in a single thread" << std::endl;
556 double t_lut_singlethread = vpTime::measureTimeMs();
557 for (unsigned int cpt = 0; cpt < nbIterations * 10; cpt++) {
558 I_lut_grayscale_single.performLut(lut, 1);
559 }
560 t_lut_singlethread = vpTime::measureTimeMs() - t_lut_singlethread;
561
562 filename = vpIoTools::createFilePath(opath, "Klimt_performance_gray_single.pgm");
563 std::cout << " Save result in " << filename << std::endl;
564 vpImageIo::write(I_lut_grayscale_single, filename);
565
566 // Check color image
567 if (I_lut_grayscale_multi == I_lut_grayscale_single) {
568 std::cout << "Gray images are the same" << std::endl;
569 std::cout << "Single-thread / multi-thread (color) gain: " << t_lut_singlethread / t_lut_multithread << std::endl;
570 }
571 else {
572 std::cerr << "Color images are different!" << std::endl;
573 std::cout << "Test failed" << std::endl;
574 return EXIT_FAILURE;
575 }
576 }
577 {
578 std::cout << "\n** Test multi-threaded LUT on gray image which size is not divisible by 8" << std::endl;
579
580 // Check performLut with multithreading and image size not divisible by 8
581 vpImage<unsigned char> I_test_grayscale_multi(49, 7), I_test_grayscale_single;
582 generateRandomImage(I_test_grayscale_multi);
583 I_test_grayscale_single = I_test_grayscale_multi;
584 // Construct the LUT
585 unsigned char lut_grayscale[256];
586 for (unsigned int i = 0; i < 256; i++) {
587 lut_grayscale[i] = vpMath::saturate<unsigned char>(alpha * i + beta);
588 }
589 std::cout << "Run test n°1 with " << nbThreads << " threads" << std::endl;
590 I_test_grayscale_multi.performLut(lut_grayscale, nbThreads);
591 std::cout << "Run test n°2 single threads" << std::endl;
592 I_test_grayscale_single.performLut(lut_grayscale, 1);
593
594 // Check gray images
595 if (I_test_grayscale_multi == I_test_grayscale_single) {
596 std::cout << "Gray images are the same" << std::endl;
597 }
598 else {
599 std::cerr << "Gray images are different!" << std::endl;
600 std::cout << "Test failed" << std::endl;
601 return EXIT_FAILURE;
602 }
603 }
604 {
605 std::cout << "\n** Test multi-threaded LUT on color image which size is not divisible by 8" << std::endl;
606
607 vpImage<vpRGBa> I_test_color_multi(49, 7), I_test_color_single;
608 generateRandomImage(I_test_color_multi);
609 I_test_color_single = I_test_color_multi;
610 // Construct the LUT
611 vpRGBa lut_color[256];
612 for (unsigned int i = 0; i < 256; i++) {
613 lut_color[i].R = vpMath::saturate<unsigned char>(alpha * i + beta);
614 lut_color[i].G = vpMath::saturate<unsigned char>(alpha * i + beta);
615 lut_color[i].B = vpMath::saturate<unsigned char>(alpha * i + beta);
616 lut_color[i].A = vpMath::saturate<unsigned char>(alpha * i + beta);
617 }
618 std::cout << "Run test n°1 with " << nbThreads << " threads" << std::endl;
619 I_test_color_multi.performLut(lut_color, nbThreads);
620 std::cout << "Run test n°2 single threads" << std::endl;
621 I_test_color_single.performLut(lut_color, 1);
622
623 // Check color images
624 if (I_test_color_multi == I_test_color_single) {
625 std::cout << "Color images are the same" << std::endl;
626 }
627 else {
628 std::cerr << "Color images are different!" << std::endl;
629 std::cout << "Test failed" << std::endl;
630 return EXIT_FAILURE;
631 }
632 }
633 std::cout << "Test succeed" << std::endl;
634 return EXIT_SUCCESS;
635 }
636 catch (const vpException &e) {
637 std::cerr << "Catch an exception: " << e.what() << std::endl;
638 return EXIT_FAILURE;
639 }
640}
error that can be emitted by ViSP classes.
Definition vpException.h:60
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
static void write(const vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition of the vpImage class member functions.
Definition vpImage.h:131
unsigned int getWidth() const
Definition vpImage.h:242
void performLut(const Type(&lut)[256], unsigned int nbThreads=1)
unsigned int getHeight() const
Definition vpImage.h:181
static std::string getViSPImagesDataPath()
static bool checkDirectory(const std::string &dirname)
static std::string getUserName()
static std::string createFilePath(const std::string &parent, const std::string &child)
static void makeDirectory(const std::string &dirname)
static Tp saturate(unsigned char v)
Definition vpMath.h:306
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
unsigned char B
Blue component.
Definition vpRGBa.h:327
unsigned char R
Red component.
Definition vpRGBa.h:325
unsigned char G
Green component.
Definition vpRGBa.h:326
unsigned char A
Additional component.
Definition vpRGBa.h:328
VISP_EXPORT double measureTimeMs()