38 #include <visp3/core/vpImage.h>
39 #include <visp3/io/vpImageIo.h>
40 #include <visp3/io/vpParseArgv.h>
41 #include <visp3/core/vpIoTools.h>
42 #include <visp3/core/vpMath.h>
54 #define GETOPTARGS "cdi:o:t:h"
66 void usage(
const char *name,
const char *badparam, std::string ipath, std::string opath, std::string user)
69 Test performance between methods to iterate over pixel image.\n\
72 %s [-i <input image path>] [-o <output image path>] [-t <nb threads>]\n\
78 -i <input image path> %s\n\
79 Set image input path.\n\
80 From this path read \"ViSP-images/Klimt/Klimt.pgm\"\n\
82 Setting the VISP_INPUT_IMAGE_PATH environment\n\
83 variable produces the same behaviour than using\n\
86 -o <output image path> %s\n\
87 Set image output path.\n\
88 From this directory, creates the \"%s\"\n\
89 subdirectory depending on the username, where \n\
90 Klimt_grey.pgm output image is written.\n\
93 Set the number of threads to use for the computation.\n\
97 ipath.c_str(), opath.c_str(), user.c_str());
100 fprintf(stdout,
"\nERROR: Bad parameter [%s]\n", badparam);
116 bool getOptions(
int argc,
const char **argv, std::string &ipath, std::string &opath,
117 std::string user,
unsigned int &nbThreads)
124 case 'i': ipath = optarg_;
break;
125 case 'o': opath = optarg_;
break;
126 case 't': nbThreads = (
unsigned int) atoi(optarg_);
break;
127 case 'h': usage(argv[0], NULL, ipath, opath, user);
return false;
break;
134 usage(argv[0], optarg_, ipath, opath, user);
return false;
break;
138 if ((c == 1) || (c == -1)) {
140 usage(argv[0], NULL, ipath, opath, user);
141 std::cerr <<
"ERROR: " << std::endl;
142 std::cerr <<
" Bad argument " << optarg_ << std::endl << std::endl;
157 void iterate_method1(
vpImage<vpRGBa> &I,
const double alpha,
const double beta) {
159 unsigned char *ptrStart = (
unsigned char*) I.
bitmap;
160 unsigned char *ptrEnd = ptrStart + size*4;
161 unsigned char *ptrCurrent = ptrStart;
163 while(ptrCurrent != ptrEnd) {
164 *ptrCurrent = vpMath::saturate<unsigned char>((*ptrCurrent) * alpha + beta);
179 unsigned char *ptrStart = (
unsigned char*) I.
bitmap;
180 unsigned char *ptrEnd = ptrStart + size;
181 unsigned char *ptrCurrent = ptrStart;
183 while(ptrCurrent != ptrEnd) {
184 *ptrCurrent = vpMath::saturate<unsigned char>((*ptrCurrent) * alpha + beta);
197 void iterate_method2(
vpImage<vpRGBa> &I,
const double alpha,
const double beta) {
198 for(
unsigned int i = 0; i < I.
getHeight(); i++) {
199 for(
unsigned int j = 0; j < I.
getWidth(); j++) {
200 I[i][j].R = vpMath::saturate<unsigned char>(I[i][j].R * alpha + beta);
201 I[i][j].G = vpMath::saturate<unsigned char>(I[i][j].G * alpha + beta);
202 I[i][j].B = vpMath::saturate<unsigned char>(I[i][j].B * alpha + beta);
203 I[i][j].A = vpMath::saturate<unsigned char>(I[i][j].A * alpha + beta);
209 main(
int argc,
const char ** argv)
212 std::string env_ipath;
213 std::string opt_ipath;
214 std::string opt_opath;
217 std::string filename;
218 std::string username;
219 unsigned int nbThreads = 4;
225 if (! env_ipath.empty())
230 opt_opath =
"C:/temp";
239 if (getOptions(argc, argv, opt_ipath, opt_opath, username, nbThreads) ==
false) {
244 if (!opt_ipath.empty())
246 if (!opt_opath.empty())
259 usage(argv[0], NULL, ipath, opt_opath, username);
260 std::cerr << std::endl
261 <<
"ERROR:" << std::endl;
262 std::cerr <<
" Cannot create " << opath << std::endl;
263 std::cerr <<
" Check your -o " << opt_opath <<
" option " << std::endl;
270 if (!opt_ipath.empty() && !env_ipath.empty()) {
271 if (ipath != env_ipath) {
272 std::cout << std::endl
273 <<
"WARNING: " << std::endl;
274 std::cout <<
" Since -i <visp image path=" << ipath <<
"> "
275 <<
" is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
276 <<
" we skip the environment variable." << std::endl;
281 if (opt_ipath.empty() && env_ipath.empty()){
282 usage(argv[0], NULL, ipath, opt_opath, username);
283 std::cerr << std::endl
284 <<
"ERROR:" << std::endl;
285 std::cerr <<
" Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH "
287 <<
" environment variable to specify the location of the " << std::endl
288 <<
" image path where test images are located." << std::endl << std::endl;
302 std::cout <<
"\nRead image: " << filename << std::endl;
307 std::cout <<
"I=" << I_iterate1.
getWidth() <<
"x" << I_iterate1.
getHeight() << std::endl;
309 double alpha = 1.5, beta = -30.0;
310 unsigned int nbIterations = 10;
314 for(
unsigned int cpt = 0; cpt < nbIterations; cpt++) {
315 iterate_method1(I_iterate1, alpha, beta);
318 std::cout <<
"t_iterate1=" << t_iterate1 <<
" ms ; t_iterate1/" << nbIterations <<
"="
319 << (t_iterate1/nbIterations) <<
" ms" << std::endl;
327 for(
unsigned int cpt = 0; cpt < nbIterations; cpt++) {
328 iterate_method2(I_iterate2, alpha, beta);
331 std::cout <<
"t_iterate2=" << t_iterate2 <<
" ms ; t_iterate2/" << nbIterations <<
"="
332 << (t_iterate2/nbIterations) <<
" ms" << std::endl;
340 for(
unsigned int cpt = 0; cpt < nbIterations; cpt++) {
343 for(
unsigned int i = 0; i < 256; i++) {
344 lut[i].
R = vpMath::saturate<unsigned char>(alpha * i + beta);
345 lut[i].
G = vpMath::saturate<unsigned char>(alpha * i + beta);
346 lut[i].
B = vpMath::saturate<unsigned char>(alpha * i + beta);
347 lut[i].
A = vpMath::saturate<unsigned char>(alpha * i + beta);
353 std::cout <<
"t_lut=" << t_lut <<
" ms ; t_lut/" << nbIterations <<
"="
354 << (t_lut/nbIterations) <<
" ms" << std::endl;
362 for(
unsigned int i = 0; i < I_iterate1.
getHeight() && same; i++) {
363 for(
unsigned int j = 0; j < I_iterate1.
getWidth() && same; j++) {
364 if(I_iterate1[i][j] != I_iterate2[i][j] || I_iterate1[i][j] != I_lut[i][j]) {
371 std::cerr <<
"Color images are different!" << std::endl;
381 std::cout <<
"\nRead image: " << filename << std::endl;
385 std::cout <<
"I_grayscale=" << I_lut_grayscale.
getWidth() <<
"x" << I_lut_grayscale.
getHeight() << std::endl;
390 for(
unsigned int cpt = 0; cpt < nbIterations; cpt++) {
391 iterate_method1(I_iterate_grayscale1, alpha, beta);
394 std::cout <<
"t_iterate_grayscale1=" << t_iterate_grayscale1 <<
" ms ; t_iterate1/" << nbIterations <<
"="
395 << (t_iterate_grayscale1/nbIterations) <<
" ms" << std::endl;
403 for(
unsigned int cpt = 0; cpt < nbIterations; cpt++) {
405 unsigned char lut[256];
406 for(
unsigned int i = 0; i < 256; i++) {
407 lut[i] = vpMath::saturate<unsigned char>(alpha * i + beta);
413 std::cout <<
"t_lut_grayscale=" << t_lut_grayscale <<
" ms ; t_lut_grayscale/" << nbIterations <<
"="
414 << (t_lut_grayscale/nbIterations) <<
" ms" << std::endl;
422 for(
unsigned int i = 0; i < I_lut_grayscale.
getHeight() && same; i++) {
423 for(
unsigned int j = 0; j < I_lut_grayscale.
getWidth() && same; j++) {
424 if(I_lut_grayscale[i][j] != I_iterate_grayscale1[i][j]) {
431 std::cerr <<
"Grayscale images are different!" << std::endl;
440 for(
unsigned int cpt = 0; cpt < nbIterations*10; cpt++) {
443 for(
unsigned int i = 0; i < 256; i++) {
444 lut[i].
R = vpMath::saturate<unsigned char>(alpha * i + beta);
445 lut[i].
G = vpMath::saturate<unsigned char>(alpha * i + beta);
446 lut[i].
B = vpMath::saturate<unsigned char>(alpha * i + beta);
447 lut[i].
A = vpMath::saturate<unsigned char>(alpha * i + beta);
458 for(
unsigned int cpt = 0; cpt < nbIterations*10; cpt++) {
461 for(
unsigned int i = 0; i < 256; i++) {
462 lut[i].
R = vpMath::saturate<unsigned char>(alpha * i + beta);
463 lut[i].
G = vpMath::saturate<unsigned char>(alpha * i + beta);
464 lut[i].
B = vpMath::saturate<unsigned char>(alpha * i + beta);
465 lut[i].
A = vpMath::saturate<unsigned char>(alpha * i + beta);
472 std::cout <<
"\nt_lut_singlethread/t_lut_multithread (color)="
473 << t_lut_singlethread/t_lut_multithread <<
"X" << std::endl;
480 for(
unsigned int cpt = 0; cpt < nbIterations*10; cpt++) {
482 unsigned char lut[256];
483 for(
unsigned int i = 0; i < 256; i++) {
484 lut[i] = vpMath::saturate<unsigned char>(alpha * i + beta);
495 for(
unsigned int cpt = 0; cpt < nbIterations*10; cpt++) {
497 unsigned char lut[256];
498 for(
unsigned int i = 0; i < 256; i++) {
499 lut[i] = vpMath::saturate<unsigned char>(alpha * i + beta);
506 std::cout <<
"\nt_lut_singlethread/t_lut_multithread (grayscale)="
507 << t_lut_singlethread/t_lut_multithread <<
"X" << std::endl;
514 unsigned char lut_grayscale[256];
515 for(
unsigned int i = 0; i < 256; i++) {
516 lut_grayscale[i] = vpMath::saturate<unsigned char>(alpha * i + beta);
518 I_test_grayscale.performLut(lut_grayscale, nbThreads);
523 for(
unsigned int i = 0; i < 256; i++) {
524 lut_color[i].
R = vpMath::saturate<unsigned char>(alpha * i + beta);
525 lut_color[i].
G = vpMath::saturate<unsigned char>(alpha * i + beta);
526 lut_color[i].
B = vpMath::saturate<unsigned char>(alpha * i + beta);
527 lut_color[i].
A = vpMath::saturate<unsigned char>(alpha * i + beta);
529 I_test_color.performLut(lut_color, nbThreads);
535 std::cerr <<
"Catch an exception: " << e.
what() << std::endl;
unsigned int getWidth() const
unsigned char B
Blue component.
Type * bitmap
points toward the bitmap
error that can be emited by ViSP classes.
unsigned char G
Green component.
VISP_EXPORT double measureTimeMs()
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
static void write(const vpImage< unsigned char > &I, const std::string &filename)
const char * what() const
unsigned char A
Additionnal component.
static void read(vpImage< unsigned char > &I, const std::string &filename)
unsigned char R
Red component.
unsigned int getHeight() const
void performLut(const Type(&lut)[256], const unsigned int nbThreads=1)