Visual Servoing Platform  version 3.2.0 under development (2019-01-22)
testConversion.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 for image conversions.
33  *
34  * Authors:
35  * Fabien Spindler
36  *
37  *****************************************************************************/
38 
39 #include <iomanip>
40 #include <stdlib.h>
41 
42 #include <visp3/core/vpConfig.h>
43 #include <visp3/core/vpDebug.h>
44 #include <visp3/core/vpImage.h>
45 #include <visp3/core/vpImageConvert.h>
46 #include <visp3/core/vpIoTools.h>
47 #include <visp3/core/vpTime.h>
48 #include <visp3/io/vpImageIo.h>
49 #include <visp3/io/vpParseArgv.h>
50 
57 // List of allowed command line options
58 #define GETOPTARGS "cdi:o:n:h"
59 
60 /*
61  Print the program options.
62 
63  \param name : Program name.
64  \param badparam : Bad parameter name.
65  \param ipath: Input image path.
66  \param opath : Output image path.
67  \param user : Username.
68  \param nbiter : Iteration number.
69 
70  */
71 void usage(const char *name, const char *badparam, std::string ipath, std::string opath, std::string user, int nbiter)
72 {
73  fprintf(stdout, "\n\
74 Test image conversions.\n\
75 \n\
76 SYNOPSIS\n\
77  %s [-i <input image path>] [-o <output image path>] [-n <nb benchmark iterations>]\n\
78  [-h]\n \
79 ", name);
80 
81  fprintf(stdout, "\n\
82 OPTIONS: Default\n\
83  -i <input image path> %s\n\
84  Set image input path.\n\
85  From this path read \"Klimt/Klimt.pgm\"\n\
86  and \"Klimt/Klimt.ppm\" images.\n\
87  Setting the VISP_INPUT_IMAGE_PATH environment\n\
88  variable produces the same behaviour than using\n\
89  this option.\n\
90 \n\
91  -o <output image path> %s\n\
92  Set image output path.\n\
93  From this directory, creates the \"%s\"\n\
94  subdirectory depending on the username, where \n\
95  Klimt_grey.pgm and Klimt_color.ppm output images\n\
96  are written.\n\
97 \n\
98  -n <nb benchmark iterations> %d\n\
99  Set the number of benchmark iterations.\n\
100 \n\
101  -h\n\
102  Print the help.\n\n", ipath.c_str(), opath.c_str(), user.c_str(), nbiter);
103 
104  if (badparam)
105  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
106 }
107 
121 bool getOptions(int argc, const char **argv, std::string &ipath, std::string &opath, const std::string &user,
122  int &nbIterations)
123 {
124  const char *optarg_;
125  int c;
126  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
127 
128  switch (c) {
129  case 'i':
130  ipath = optarg_;
131  break;
132  case 'o':
133  opath = optarg_;
134  break;
135  case 'n':
136  nbIterations = atoi(optarg_);
137  break;
138  case 'h':
139  usage(argv[0], NULL, ipath, opath, user, nbIterations);
140  return false;
141  break;
142 
143  case 'c':
144  case 'd':
145  break;
146 
147  default:
148  usage(argv[0], optarg_, ipath, opath, user, nbIterations);
149  return false;
150  break;
151  }
152  }
153 
154  if ((c == 1) || (c == -1)) {
155  // standalone param or error
156  usage(argv[0], NULL, ipath, opath, user, nbIterations);
157  std::cerr << "ERROR: " << std::endl;
158  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
159  return false;
160  }
161 
162  return true;
163 }
164 
165 void computeRegularRGBaToGrayscale(const unsigned char *rgba, unsigned char *grey, unsigned int size)
166 {
167  const unsigned char *pt_input = rgba;
168  const unsigned char *pt_end = rgba + size * 4;
169  unsigned char *pt_output = grey;
170 
171  while (pt_input != pt_end) {
172  *pt_output = (unsigned char)(0.2126 * (*pt_input) + 0.7152 * (*(pt_input + 1)) + 0.0722 * (*(pt_input + 2)));
173  pt_input += 4;
174  pt_output++;
175  }
176 }
177 
178 void computeRegularRGBToGrayscale(const unsigned char *rgb, unsigned char *grey, unsigned int size)
179 {
180  const unsigned char *pt_input = rgb;
181  const unsigned char *pt_end = rgb + size * 3;
182  unsigned char *pt_output = grey;
183 
184  while (pt_input != pt_end) {
185  *pt_output = (unsigned char)(0.2126 * (*pt_input) + 0.7152 * (*(pt_input + 1)) + 0.0722 * (*(pt_input + 2)));
186  pt_input += 3;
187  pt_output++;
188  }
189 }
190 
191 void computeRegularBGRToGrayscale(unsigned char *bgr, unsigned char *grey, unsigned int width, unsigned int height,
192  bool flip)
193 {
194  // if we have to flip the image, we start from the end last scanline so the
195  // step is negative
196  int lineStep = (flip) ? -(int)(width * 3) : (int)(width * 3);
197 
198  // starting source address = last line if we need to flip the image
199  unsigned char *src = (flip) ? bgr + (width * height * 3) + lineStep : bgr;
200 
201  unsigned int j = 0;
202  unsigned int i = 0;
203 
204  for (i = 0; i < height; i++) {
205  unsigned char *line = src;
206  for (j = 0; j < width; j++) {
207  *grey++ = (unsigned char)(0.2126 * *(line + 2) + 0.7152 * *(line + 1) + 0.0722 * *(line + 0));
208  line += 3;
209  }
210 
211  // go to the next line
212  src += lineStep;
213  }
214 }
215 
216 #if (VISP_HAVE_OPENCV_VERSION >= 0x020101)
217 void computeRegularBGRToGrayscale(const cv::Mat &src, vpImage<unsigned char> &dest)
218 {
219  if (src.type() == CV_8UC3) {
220  dest.resize((unsigned int)src.rows, (unsigned int)src.cols);
221 
222  if (src.isContinuous()) {
223  computeRegularBGRToGrayscale((unsigned char *)src.data, (unsigned char *)dest.bitmap, (unsigned int)src.cols,
224  (unsigned int)src.rows, false);
225  }
226  }
227 }
228 #endif
229 
230 int main(int argc, const char **argv)
231 {
232  try {
233  std::string env_ipath;
234  std::string opt_ipath;
235  std::string opt_opath;
236  std::string ipath;
237  std::string opath;
238  std::string filename;
239  std::string username;
240  int nbIterations = 1;
241 
242  // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
243  // environment variable value
244  env_ipath = vpIoTools::getViSPImagesDataPath();
245 
246  // Set the default input path
247  if (!env_ipath.empty())
248  ipath = env_ipath;
249 
250 // Set the default output path
251 #if defined(_WIN32)
252  opt_opath = "C:/temp";
253 #else
254  opt_opath = "/tmp";
255 #endif
256 
257  // Get the user login name
258  vpIoTools::getUserName(username);
259 
260  // Read the command line options
261  if (getOptions(argc, argv, opt_ipath, opt_opath, username, nbIterations) == false) {
262  exit(-1);
263  }
264 
265  // Get the option values
266  if (!opt_ipath.empty())
267  ipath = opt_ipath;
268  if (!opt_opath.empty())
269  opath = opt_opath;
270 
271  // Append to the output path string, the login name of the user
272  opath = vpIoTools::createFilePath(opath, username);
273 
274  // Test if the output path exist. If no try to create it
275  if (vpIoTools::checkDirectory(opath) == false) {
276  try {
277  // Create the dirname
279  } catch (...) {
280  usage(argv[0], NULL, ipath, opt_opath, username, nbIterations);
281  std::cerr << std::endl << "ERROR:" << std::endl;
282  std::cerr << " Cannot create " << opath << std::endl;
283  std::cerr << " Check your -o " << opt_opath << " option " << std::endl;
284  exit(-1);
285  }
286  }
287 
288  // Compare ipath and env_ipath. If they differ, we take into account
289  // the input path comming from the command line option
290  if (opt_ipath.empty()) {
291  if (ipath != env_ipath) {
292  std::cout << std::endl << "WARNING: " << std::endl;
293  std::cout << " Since -i <visp image path=" << ipath << "> "
294  << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
295  << " we skip the environment variable." << std::endl;
296  }
297  }
298 
299  // Test if an input path is set
300  if (opt_ipath.empty() && env_ipath.empty()) {
301  usage(argv[0], NULL, ipath, opt_opath, username, nbIterations);
302  std::cerr << std::endl << "ERROR:" << std::endl;
303  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
304  << " environment variable to specify the location of the " << std::endl
305  << " image path where test images are located." << std::endl
306  << std::endl;
307  exit(-1);
308  }
309 
310  //
311  // Here starts really the test
312  //
313 
314  vpImage<unsigned char> Ig; // Grey image
315  vpImage<vpRGBa> Ic; // Color image
316 
317  //-------------------- .pgm -> .ppm
318  std::cout << "** Convert a grey image (.pgm) to a color image (.ppm)" << std::endl;
319  // Load a grey image from the disk
320  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.pgm");
321  std::cout << " Load " << filename << std::endl;
322  vpImageIo::read(Ig, filename);
323  // Create a color image from the grey
324  vpImageConvert::convert(Ig, Ic);
325  filename = vpIoTools::createFilePath(opath, "Klimt_color.ppm");
326  std::cout << " Resulting image saved in: " << filename << std::endl;
327  vpImageIo::write(Ic, filename);
328 
329  //-------------------- .ppm -> .pgm
330  std::cout << "** Convert a color image (.ppm) to a grey image (.pgm)" << std::endl;
331  // Load a color image from the disk
332  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
333  std::cout << " Load " << filename << std::endl;
334  vpImageIo::read(Ic, filename);
335  // Create a grey image from the color
336  vpImageConvert::convert(Ic, Ig);
337  filename = vpIoTools::createFilePath(opath, "Klimt_grey.pgm");
338  std::cout << " Resulting image saved in: " << filename << std::endl;
339  vpImageIo::write(Ig, filename);
340 
341  //-------------------- YUV -> RGB
342  std::cout << "** Convert YUV pixel value to a RGB value" << std::endl;
343  unsigned char y = 187, u = 10, v = 30;
344  unsigned char r, g, b;
345 
346  // Convert a YUV pixel value to a RGB value
347  vpImageConvert::YUVToRGB(y, u, v, r, g, b);
348  std::cout << " y(" << (int)y << ") u(" << (int)u << ") v(" << (int)v << ") = r(" << (int)r << ") g(" << (int)g
349  << ") b(" << (int)b << ")" << std::endl;
350 
351 #ifdef VISP_HAVE_OPENCV
352 #if VISP_HAVE_OPENCV_VERSION < 0x020408
353  double t0 = vpTime::measureTimeMs();
355  // Convert a IplImage to a vpImage<vpRGBa>
357  std::cout << "** Convert an IplImage to a vpImage<vpRGBa>" << std::endl;
358  IplImage *image = NULL;
359  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
360 
361  /* Read the color image */
362 
363  std::cout << " Reading the color image with opencv: " << filename << std::endl;
364  if ((image = cvLoadImage(filename.c_str(), CV_LOAD_IMAGE_COLOR)) == NULL) {
365  std::cout << " Cannot read image: " << filename << std::endl;
366  return (-1);
367  }
368  vpImageConvert::convert(image, Ic);
369  filename = vpIoTools::createFilePath(opath, "Klimt_color_cv.ppm");
370  std::cout << " Resulting image saved in: " << filename << std::endl;
371  vpImageIo::write(Ic, filename);
372 
373  std::cout << " Convert result in " << filename << std::endl;
374 
375  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.pgm");
376 
377  /* Read the pgm image */
378  std::cout << " Reading the greyscale image with opencv: " << filename << std::endl;
379  if (image != NULL)
380  cvReleaseImage(&image);
381  if ((image = cvLoadImage(filename.c_str(), CV_LOAD_IMAGE_GRAYSCALE)) == NULL) {
382  std::cout << " Cannot read image: " << filename << std::endl;
383  return (-1);
384  }
385  vpImageConvert::convert(image, Ic);
386  filename = vpIoTools::createFilePath(opath, "Klimt_grey_cv.ppm");
387  std::cout << " Resulting image saved in: " << filename << std::endl;
388  vpImageIo::write(Ic, filename);
389 
390  std::cout << " Convert result in " << filename << std::endl;
391 
393  // Convert a IplImage to a vpImage<unsigned char>
395  std::cout << "** Convert an IplImage to a vpImage<unsigned char>" << std::endl;
396  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
397 
398  /* Read the color image */
399 
400  std::cout << " Reading the color image with opencv: " << filename << std::endl;
401  if (image != NULL)
402  cvReleaseImage(&image);
403  if ((image = cvLoadImage(filename.c_str(), CV_LOAD_IMAGE_COLOR)) == NULL) {
404  std::cout << " Cannot read image: " << filename << std::endl;
405  return (-1);
406  }
407  vpImageConvert::convert(image, Ig);
408  filename = vpIoTools::createFilePath(opath, "Klimt_color_cv.pgm");
409  std::cout << " Resulting image saved in: " << filename << std::endl;
410  vpImageIo::write(Ig, filename);
411 
412  std::cout << " Convert result in " << filename << std::endl;
413 
414  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.pgm");
415 
416  /* Read the pgm image */
417 
418  std::cout << " Reading the greyscale image with opencv: " << filename << std::endl;
419  if (image != NULL)
420  cvReleaseImage(&image);
421  if ((image = cvLoadImage(filename.c_str(), CV_LOAD_IMAGE_GRAYSCALE)) == NULL) {
422  std::cout << " Cannot read image: " << filename << std::endl;
423  return (-1);
424  }
425  vpImageConvert::convert(image, Ig);
426  filename = vpIoTools::createFilePath(opath, "Klimt_grey_cv.pgm");
427  std::cout << " Resulting image saved in: " << filename << std::endl;
428  vpImageIo::write(Ig, filename);
429 
430  std::cout << " Convert result in " << filename << std::endl;
431 
433  // Convert a vpImage<vpRGBa> to a IplImage
435  std::cout << "** Convert a vpImage<vpRGBa> to an IplImage" << std::endl;
436  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
437 
438  /* Read the color image */
439 
440  // Load a color image from the disk
441  std::cout << " Load " << filename << std::endl;
442  vpImageIo::read(Ic, filename);
443  vpImageConvert::convert(Ic, image);
444  filename = vpIoTools::createFilePath(opath, "Klimt_ipl_color_cv.ppm");
445  /* Save the the current image */
446  std::cout << " Write " << filename << std::endl;
447  if ((cvSaveImage(filename.c_str(), image)) == 0) {
448  std::cout << " Cannot write image: " << filename << std::endl;
449  if (image != NULL)
450  cvReleaseImage(&image);
451  return (-1);
452  }
453  std::cout << " Convert result in " << filename << std::endl;
454 
456  // Convert a vpImage<unsigned char> to an IplImage
458  std::cout << "** Convert a vpImage<unsigned char> to an IplImage" << std::endl;
459  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.pgm");
460 
461  /* Read the grey image */
462 
463  // Load a color image from the disk
464  std::cout << " Load " << filename << std::endl;
465  vpImageIo::read(Ig, filename);
466  vpImageConvert::convert(Ig, image);
467  filename = vpIoTools::createFilePath(opath, "Klimt_ipl_grey_cv.pgm");
468  /* Save the the current image */
469 
470  std::cout << " Write " << filename << std::endl;
471  if ((cvSaveImage(filename.c_str(), image)) == 0) {
472  std::cout << " Cannot write image: " << std::endl << filename << std::endl;
473  if (image != NULL)
474  cvReleaseImage(&image);
475  return (-1);
476  }
477  std::cout << " Convert result in " << filename << std::endl;
478 
479  if (image != NULL)
480  cvReleaseImage(&image);
481  double t1 = vpTime::measureTimeMs();
482  std::cout << "== Conversion c interface : " << t1 - t0 << " ms" << std::endl;
483 #endif
484 
485 /* ------------------------------------------------------------------------ */
486 /* conversion for the new c++ interface */
487 /* ------------------------------------------------------------------------ */
488 
489 #if VISP_HAVE_OPENCV_VERSION >= 0x020100
490  double t2 = vpTime::measureTimeMs();
492  // Convert a cv::Mat to a vpImage<vpRGBa>
494  std::cout << "** Convert a cv::Mat to a vpImage<vpRGBa>" << std::endl;
495  cv::Mat imageMat;
496  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
497  std::cout << " Reading the color image with c++ interface of opencv: " << filename << std::endl;
498  imageMat = cv::imread(filename, 1); // force to a three channel color image.
499  if (imageMat.data == NULL) {
500  std::cout << " Cannot read image: " << filename << std::endl;
501  return -1;
502  }
503  vpImageConvert::convert(imageMat, Ic);
504  filename = vpIoTools::createFilePath(opath, "Klimt_color_cvMat.ppm");
505  std::cout << " Resulting image saved in: " << filename << std::endl;
506  vpImageIo::write(Ic, filename);
507 
508  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.pgm");
509  /* Read the pgm image */
510 
511  std::cout << " Reading the greyscale image with opencv: " << filename << std::endl;
512  imageMat = cv::imread(filename, 0); // forced to grayscale.
513  if (imageMat.data == NULL) {
514  std::cout << " Cannot read image: " << filename << std::endl;
515  return (-1);
516  }
517  vpImageConvert::convert(imageMat, Ic);
518  filename = vpIoTools::createFilePath(opath, "Klimt_grey_cvMat.ppm");
519  std::cout << " Resulting image saved in: " << filename << std::endl;
520  vpImageIo::write(Ic, filename);
521 
523  // Convert a cv::Mat to a vpImage<unsigned char>
525  std::cout << "** Convert a cv::Mat to a vpImage<nsigned char>" << std::endl;
526  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
527 
528  /* Read the color image */
529 
530  std::cout << " Reading the color image with opencv: " << filename << std::endl;
531  imageMat = cv::imread(filename, 1); // force to a three channel color image.
532  if (imageMat.data == NULL) {
533  std::cout << " Cannot read image: " << filename << std::endl;
534  return -1;
535  }
536  vpImageConvert::convert(imageMat, Ig);
537  filename = vpIoTools::createFilePath(opath, "Klimt_color_cvMat.pgm");
538  std::cout << " Resulting image saved in: " << filename << std::endl;
539  vpImageIo::write(Ig, filename);
540 
541  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.pgm");
542 
543  /* Read the pgm image */
544 
545  std::cout << " Reading the greyscale image with opencv: " << filename << std::endl;
546  imageMat = cv::imread(filename, 0);
547  if (imageMat.data == NULL) {
548  std::cout << " Cannot read image: " << filename << std::endl;
549  return (-1);
550  }
551  vpImageConvert::convert(imageMat, Ig);
552  filename = vpIoTools::createFilePath(opath, "Klimt_grey_cvMat.pgm");
553  std::cout << " Resulting image saved in: " << filename << std::endl;
554  vpImageIo::write(Ig, filename);
555 
556  std::cout << " Convert result in " << filename << std::endl;
557 
559  // Convert a vpImage<vpRGBa> to a cv::Mat
561  std::cout << "** Convert a vpImage<vpRGBa> to a cv::Mat" << std::endl;
562  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
563 
564  /* Read the color image */
565 
566  // Load a color image from the disk
567  std::cout << " Load " << filename << std::endl;
568  vpImageIo::read(Ic, filename);
569  vpImageConvert::convert(Ic, imageMat);
570  filename = vpIoTools::createFilePath(opath, "Klimt_ipl_color_cvMat.ppm");
571  /* Save the the current image */
572  std::cout << " Resulting image saved in: " << filename << std::endl;
573  if (!cv::imwrite(filename, imageMat)) {
574  std::cout << " Cannot write image: " << filename << std::endl;
575  return (-1);
576  }
577  std::cout << " Convert result in " << filename << std::endl;
578 
580  // Convert a vpImage<unsigned char> to a cv::Mat
582  std::cout << "** Convert a vpImage<unsigned char> to a cv::Mat" << std::endl;
583  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.pgm");
584 
585  /* Read the grey image */
586 
587  // Load a color image from the disk
588  std::cout << " Load " << filename << std::endl;
589  vpImageIo::read(Ig, filename);
590  vpImageConvert::convert(Ig, imageMat);
591  filename = vpIoTools::createFilePath(opath, "Klimt_ipl_grey_cvMat.pgm");
592  /* Save the the current image */
593 
594  std::cout << " Resulting image saved in: " << filename << std::endl;
595  if (!cv::imwrite(filename, imageMat)) {
596  std::cout << " Cannot write image: " << filename << std::endl;
597  return (-1);
598  }
599  std::cout << " Convert result in " << filename << std::endl;
600  double t3 = vpTime::measureTimeMs();
601  std::cout << "== Conversion c++ interface : " << t3 - t2 << " ms" << std::endl;
602 #endif
603 #endif
604 
606  // Split a vpImage<vpRGBa> to vpImage<unsigned char>
608  std::cout << "** Split a vpImage<vpRGBa> to vpImage<unsigned char>" << std::endl;
609  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
610 
611  /* Read the color image */
612 
613  // Load a color image from the disk
614  std::cout << " Load " << filename << std::endl;
615  vpImageIo::read(Ic, filename);
616  vpImage<unsigned char> R, G, B, a;
617  vpImageConvert::split(Ic, &R, NULL, &B);
618  double begintime = vpTime::measureTimeMs();
619  for (int iteration = 0; iteration < nbIterations; iteration++) {
620  vpImageConvert::split(Ic, &R, NULL, &B);
621  }
622  double endtime = vpTime::measureTimeMs();
623 
624  std::cout << " Time for " << nbIterations << " split (ms): " << endtime - begintime << std::endl;
625 
626  filename = vpIoTools::createFilePath(opath, "Klimt_RChannel.pgm");
627  /* Save the the current image */
628  std::cout << " Save Klimt R channel: " << filename << std::endl;
629  vpImageIo::write(R, filename);
630 
631  filename = vpIoTools::createFilePath(opath, "Klimt_BChannel.pgm");
632  /* Save the the current image */
633  std::cout << " Save Klimt B channel: " << filename << std::endl;
634  vpImageIo::write(B, filename);
635 
637  // Merge 4 vpImage<unsigned char> (RGBa) to vpImage<vpRGBa>
639  std::cout << "** Merge 4 vpImage<unsigned char> (RGBa) to vpImage<vpRGBa>" << std::endl;
640  vpImageConvert::split(Ic, &R, &G, &B, &a);
641  begintime = vpTime::measureTimeMs();
642  vpImage<vpRGBa> I_merge;
643  for (int iteration = 0; iteration < nbIterations; iteration++) {
644  vpImageConvert::merge(&R, &G, &B, &a, I_merge);
645  }
646  endtime = vpTime::measureTimeMs();
647 
648  std::cout << " Time for 1000 merge (ms): " << endtime - begintime << std::endl;
649 
650  filename = vpIoTools::createFilePath(opath, "Klimt_merge.ppm");
651  std::cout << " Resulting image saved in: " << filename << std::endl;
652  vpImageIo::write(I_merge, filename);
653 
655  // Convert a vpImage<vpRGBa> in RGB color space to a vpImage<vpRGBa> in
656  // HSV color
658  std::cout << "** Convert a vpImage<vpRGBa> in RGB color space to a "
659  "vpImage<vpRGBa> in HSV color"
660  << std::endl;
661  unsigned int size = Ic.getSize();
662  unsigned int w = Ic.getWidth(), h = Ic.getHeight();
663  unsigned char *hue = new unsigned char[size];
664  unsigned char *saturation = new unsigned char[size];
665  unsigned char *value = new unsigned char[size];
666 
667  vpImageConvert::RGBaToHSV((unsigned char *)Ic.bitmap, hue, saturation, value, size);
668  vpImage<unsigned char> I_hue(hue, h, w);
669  vpImage<unsigned char> I_saturation(saturation, h, w);
670  vpImage<unsigned char> I_value(value, h, w);
671  vpImage<vpRGBa> I_HSV;
672  vpImageConvert::merge(&I_hue, &I_saturation, &I_value, NULL, I_HSV);
673 
674  filename = vpIoTools::createFilePath(opath, "Klimt_HSV.ppm");
675  std::cout << " Resulting image saved in: " << filename << std::endl;
676  vpImageIo::write(I_HSV, filename);
677 
678  // Check the conversion RGBa <==> HSV
679  double *hue2 = new double[size];
680  double *saturation2 = new double[size];
681  double *value2 = new double[size];
682  vpImageConvert::RGBaToHSV((unsigned char *)Ic.bitmap, hue2, saturation2, value2, size);
683 
684  unsigned char *rgba = new unsigned char[size * 4];
685  vpImageConvert::HSVToRGBa(hue2, saturation2, value2, rgba, size);
686 
687  if (hue2 != NULL) {
688  delete[] hue2;
689  hue2 = NULL;
690  }
691 
692  if (saturation2 != NULL) {
693  delete[] saturation2;
694  saturation2 = NULL;
695  }
696 
697  if (value2 != NULL) {
698  delete[] value2;
699  value2 = NULL;
700  }
701 
702  vpImage<vpRGBa> I_HSV2RGBa((vpRGBa *)rgba, h, w);
703  filename = vpIoTools::createFilePath(opath, "Klimt_HSV2RGBa.ppm");
704  std::cout << " Resulting image saved in: " << filename << std::endl;
705  vpImageIo::write(I_HSV2RGBa, filename);
706 
707  for (unsigned int i = 0; i < Ic.getHeight(); i++) {
708  for (unsigned int j = 0; j < Ic.getWidth(); j++) {
709  if (Ic[i][j].R != I_HSV2RGBa[i][j].R || Ic[i][j].G != I_HSV2RGBa[i][j].G || Ic[i][j].B != I_HSV2RGBa[i][j].B) {
710  std::cerr << "Ic[i][j].R=" << static_cast<unsigned>(Ic[i][j].R)
711  << " ; I_HSV2RGBa[i][j].R=" << static_cast<unsigned>(I_HSV2RGBa[i][j].R) << std::endl;
712  std::cerr << "Ic[i][j].G=" << static_cast<unsigned>(Ic[i][j].G)
713  << " ; I_HSV2RGBa[i][j].G=" << static_cast<unsigned>(I_HSV2RGBa[i][j].G) << std::endl;
714  std::cerr << "Ic[i][j].B=" << static_cast<unsigned>(Ic[i][j].B)
715  << " ; I_HSV2RGBa[i][j].B=" << static_cast<unsigned>(I_HSV2RGBa[i][j].B) << std::endl;
716  throw vpException(vpException::fatalError, "Problem with conversion between RGB <==> HSV");
717  }
718  }
719  }
720 
722  // Test construction of a vpImage from an array with copyData==true
724  std::cout << "** Construction of a vpImage from an array with copyData==true" << std::endl;
725  unsigned char *rgba2 = new unsigned char[size * 4];
726  memset(rgba2, 127, size * 4);
727  vpImage<vpRGBa> I_copyData((vpRGBa *)rgba2, h, w, true);
728 
729  // Delete the array
730  delete[] rgba2;
731 
732  filename = vpIoTools::createFilePath(opath, "I_copyData.ppm");
733  std::cout << " Resulting image saved in: " << filename << std::endl;
734  vpImageIo::write(I_copyData, filename);
735 
736  if (I_copyData.getSize() > 0) {
737  I_copyData[0][0].R = 10;
738  }
739 
740  // Benchmark and test RGBa / RGB / cv::Mat to Grayscale conversion
741  {
742  std::cout << "** Benchmark and test RGBa / RGB / cv::Mat to Grayscale "
743  "conversion"
744  << std::endl;
745  // RGBa to Grayscale
746  vpImage<vpRGBa> I_color;
747  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
748  vpImageIo::read(I_color, filename);
749 
750  vpImage<unsigned char> I_gray_sse(I_color.getHeight(), I_color.getWidth());
751  vpImage<unsigned char> I_gray_regular(I_color.getHeight(), I_color.getWidth());
752  unsigned char value_sse = 0, value_regular = 0;
753 
754  double t_sse = vpTime::measureTimeMs();
755  for (int iteration = 0; iteration < nbIterations; iteration++) {
756  vpImageConvert::convert(I_color, I_gray_sse);
757  value_sse += I_gray_sse[0][0];
758  }
759  t_sse = vpTime::measureTimeMs() - t_sse;
760 
761  double t_regular = vpTime::measureTimeMs();
762  for (int iteration = 0; iteration < nbIterations; iteration++) {
763  computeRegularRGBaToGrayscale((unsigned char *)I_color.bitmap, I_gray_regular.bitmap, I_color.getSize());
764  value_regular += I_gray_regular[0][0];
765  }
766  t_regular = vpTime::measureTimeMs() - t_regular;
767 
768  // Compute the error between the SSE and regular version
769  double rmse_error = 0.0;
770  for (unsigned int i = 0; i < I_color.getHeight(); i++) {
771  for (unsigned int j = 0; j < I_color.getWidth(); j++) {
772  rmse_error += (I_gray_sse[i][j] - I_gray_regular[i][j]) * (I_gray_sse[i][j] - I_gray_regular[i][j]);
773  }
774  }
775 
776  std::cout << "\n RGBa to Grayscale" << std::endl;
777  std::cout << " t_regular (" << nbIterations << " iterations)=" << t_regular << " ms"
778  << " ; t_sse (" << nbIterations << " iterations)=" << t_sse << " ms" << std::endl;
779  std::cout << " Speed-up=" << (t_regular / t_sse) << "X" << std::endl;
780  std::cout << " RMSE error between SSE and regular version: " << (std::sqrt(rmse_error / I_color.getSize()))
781  << std::endl;
782 
783  // To prevent the iteration loop to not be optimized?
784  std::cout << " value_sse=" << static_cast<unsigned>(value_sse)
785  << " ; value_regular=" << static_cast<unsigned>(value_regular) << std::endl;
786 
787  filename = vpIoTools::createFilePath(opath, "I_rgba2gray_sse.pgm");
788  std::cout << " Resulting image saved in: " << filename << std::endl;
789  vpImageIo::write(I_gray_sse, filename);
790 
791  filename = vpIoTools::createFilePath(opath, "I_rgba2gray_regular.pgm");
792  std::cout << " Resulting image saved in: " << filename << std::endl;
793  vpImageIo::write(I_gray_regular, filename);
794 
795  // RGB to Grayscale conversion
796  unsigned char *rgb_array = new unsigned char[I_color.getSize() * 3];
797  vpImageConvert::RGBaToRGB((unsigned char *)I_color.bitmap, rgb_array, I_color.getSize());
798 
799  value_sse = 0;
800  value_regular = 0;
801 
802  unsigned char *rgb2gray_array_sse = new unsigned char[I_color.getSize()];
803  t_sse = vpTime::measureTimeMs();
804  for (int iteration = 0; iteration < nbIterations; iteration++) {
805  vpImageConvert::RGBToGrey(rgb_array, rgb2gray_array_sse, I_color.getWidth(), I_color.getHeight(), false);
806  value_sse += rgb2gray_array_sse[0];
807  }
808  t_sse = vpTime::measureTimeMs() - t_sse;
809 
810  unsigned char *rgb2gray_array_regular = new unsigned char[I_color.getSize()];
811  t_regular = vpTime::measureTimeMs();
812  for (int iteration = 0; iteration < nbIterations; iteration++) {
813  computeRegularRGBToGrayscale(rgb_array, rgb2gray_array_regular, I_color.getSize());
814  value_regular += rgb2gray_array_regular[0];
815  }
816  t_regular = vpTime::measureTimeMs() - t_regular;
817 
818  vpImage<unsigned char> I_gray2rgba_sse(rgb2gray_array_sse, I_color.getHeight(), I_color.getWidth(), false);
819  vpImage<unsigned char> I_gray2rgba_regular(rgb2gray_array_regular, I_color.getHeight(), I_color.getWidth(),
820  false);
821 
822  // Compute the error between the SSE and regular version
823  rmse_error = 0.0;
824  for (unsigned int i = 0; i < I_color.getHeight(); i++) {
825  for (unsigned int j = 0; j < I_color.getWidth(); j++) {
826  rmse_error +=
827  (I_gray2rgba_sse[i][j] - I_gray2rgba_regular[i][j]) * (I_gray2rgba_sse[i][j] - I_gray2rgba_regular[i][j]);
828  }
829  }
830 
831  std::cout << "\n RGB to Grayscale" << std::endl;
832  std::cout << " t_regular (" << nbIterations << " iterations)=" << t_regular << " ms"
833  << " ; t_sse (" << nbIterations << " iterations)=" << t_sse << " ms" << std::endl;
834  std::cout << " Speed-up=" << (t_regular / t_sse) << "X" << std::endl;
835  std::cout << " RMSE error between SSE and regular version: " << (std::sqrt(rmse_error / I_color.getSize()))
836  << std::endl;
837 
838  // To prevent the iteration loop to not be optimized?
839  std::cout << " value_sse=" << static_cast<unsigned>(value_sse)
840  << " ; value_regular=" << static_cast<unsigned>(value_regular) << std::endl;
841 
842  filename = vpIoTools::createFilePath(opath, "I_rgb2gray_sse.pgm");
843  std::cout << " Resulting image saved in: " << filename << std::endl;
844  vpImageIo::write(I_gray2rgba_sse, filename);
845 
846  filename = vpIoTools::createFilePath(opath, "I_rgb2gray_regular.pgm");
847  std::cout << " Resulting image saved in: " << filename << std::endl;
848  vpImageIo::write(I_gray2rgba_regular, filename);
849 
850 #if (VISP_HAVE_OPENCV_VERSION >= 0x020101)
851  // BGR cv::Mat to Grayscale
852  std::cout << "\n BGR cv::Mat to Grayscale" << std::endl;
853  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
854  cv::Mat colorMat = cv::imread(filename);
855  std::cout << " colorMat=" << colorMat.cols << "x" << colorMat.rows << std::endl;
856 
857  vpImage<unsigned char> I_mat2gray_sse, I_mat2gray_regular;
858  value_sse = 0;
859  value_regular = 0;
860 
861  t_sse = vpTime::measureTimeMs();
862  for (int iteration = 0; iteration < nbIterations; iteration++) {
863  vpImageConvert::convert(colorMat, I_mat2gray_sse, false);
864  value_sse += I_mat2gray_sse[0][0];
865  }
866  t_sse = vpTime::measureTimeMs() - t_sse;
867 
868  t_regular = vpTime::measureTimeMs();
869  for (int iteration = 0; iteration < nbIterations; iteration++) {
870  computeRegularBGRToGrayscale(colorMat, I_mat2gray_regular);
871  value_regular += I_mat2gray_sse[0][0];
872  }
873  t_regular = vpTime::measureTimeMs() - t_regular;
874 
875  // Compute the error between the SSE and regular version
876  rmse_error = 0.0;
877  for (unsigned int i = 0; i < I_color.getHeight(); i++) {
878  for (unsigned int j = 0; j < I_color.getWidth(); j++) {
879  rmse_error +=
880  (I_mat2gray_sse[i][j] - I_mat2gray_regular[i][j]) * (I_mat2gray_sse[i][j] - I_mat2gray_regular[i][j]);
881  }
882  }
883 
884  std::cout << " t_regular (" << nbIterations << " iterations)=" << t_regular << " ms"
885  << " ; t_sse (" << nbIterations << " iterations)=" << t_sse << " ms" << std::endl;
886  std::cout << " Speed-up=" << (t_regular / t_sse) << "X" << std::endl;
887  std::cout << " RMSE error between SSE and regular version: " << (std::sqrt(rmse_error / I_color.getSize()))
888  << std::endl;
889 
890  // To prevent the iteration loop to not be optimized?
891  std::cout << " value_sse=" << static_cast<unsigned>(value_sse)
892  << " ; value_regular=" << static_cast<unsigned>(value_regular) << std::endl;
893 
894  filename = vpIoTools::createFilePath(opath, "I_mat2gray_sse.pgm");
895  std::cout << " Resulting image saved in: " << filename << std::endl;
896  vpImageIo::write(I_mat2gray_sse, filename);
897 
898  filename = vpIoTools::createFilePath(opath, "I_mat2gray_regular.pgm");
899  std::cout << " Resulting image saved in: " << filename << std::endl;
900  vpImageIo::write(I_mat2gray_regular, filename);
901 
902  // BGR cv::Mat to Grayscale cv::Mat
903  std::cout << "\n BGR Mat to Grayscale Mat" << std::endl;
904  cv::Mat grayscaleMat(colorMat.size(), CV_8U);
905  unsigned char value_mat = 0;
906 
907  double t_opencv = vpTime::measureTimeMs();
908  for (int iteration = 0; iteration < nbIterations; iteration++) {
909  cv::cvtColor(colorMat, grayscaleMat, cv::COLOR_BGR2GRAY);
910  value_mat += grayscaleMat.ptr<uchar>(0)[0];
911  }
912  t_opencv = vpTime::measureTimeMs() - t_opencv;
913 
914  std::cout << " t_opencv (" << nbIterations << " iterations)=" << t_opencv << " ms"
915  << " ; t_sse (" << nbIterations << " iterations)=" << t_sse << " ms" << std::endl;
916  std::cout << " Speed-up=" << (t_opencv / t_sse) << "X" << std::endl;
917  std::cout << " value_mat=" << static_cast<unsigned>(value_mat) << std::endl;
918 
919  vpImage<unsigned char> I_grayscale_mat;
920  vpImageConvert::convert(grayscaleMat, I_grayscale_mat);
921  filename = vpIoTools::createFilePath(opath, "grayscaleMat.pgm");
922  std::cout << " Resulting image saved in: " << filename << std::endl;
923  vpImageIo::write(I_grayscale_mat, filename);
924 
925  // Test RGB to Grayscale + Flip
926  std::cout << "\n RGB to Grayscale + Flip" << std::endl;
927  unsigned char *rgb2gray_flip_array_sse = new unsigned char[I_color.getSize()];
928  vpImageConvert::RGBToGrey(rgb_array, rgb2gray_flip_array_sse, I_color.getWidth(), I_color.getHeight(), true);
929  vpImage<unsigned char> I_rgb2gray_flip_sse(rgb2gray_flip_array_sse, I_color.getHeight(), I_color.getWidth());
930 
931  filename = vpIoTools::createFilePath(opath, "I_rgb2gray_flip_sse.pgm");
932  std::cout << " Resulting image saved in: " << filename << std::endl;
933  vpImageIo::write(I_rgb2gray_flip_sse, filename);
934 
935  // Test BGR to Grayscale + Flip
936  std::cout << "\n Conversion BGR to Grayscale + Flip" << std::endl;
937  unsigned char *bgr2gray_flip_array_sse = new unsigned char[I_color.getSize()];
938  vpImage<unsigned char> I_bgr2gray_flip_sse(bgr2gray_flip_array_sse, I_color.getHeight(), I_color.getWidth());
939  vpImageConvert::convert(colorMat, I_bgr2gray_flip_sse, true);
940 
941  filename = vpIoTools::createFilePath(opath, "I_bgr2gray_flip_sse.pgm");
942  std::cout << " Resulting image saved in: " << filename << std::endl;
943  vpImageIo::write(I_bgr2gray_flip_sse, filename);
944 
945  // Test RGB to Grayscale + Flip + Crop
946  std::cout << "\n RGB to Grayscale + Flip + Crop" << std::endl;
947  cv::Rect rect_roi(11, 17, 347, 449);
948  cv::Mat colorMat_crop = colorMat(rect_roi);
949  cv::Mat colorMat_crop_continous = colorMat(rect_roi).clone();
950  std::cout << " colorMat_crop: " << colorMat_crop.cols << "x" << colorMat_crop.rows << " is continuous? "
951  << colorMat_crop.isContinuous() << std::endl;
952  std::cout << " colorMat_crop_continous: " << colorMat_crop_continous.cols << "x" << colorMat_crop_continous.rows
953  << " is continuous? " << colorMat_crop_continous.isContinuous() << std::endl;
954 
955  vpImage<vpRGBa> I_color_crop((unsigned int)(rect_roi.height - rect_roi.y),
956  (unsigned int)(rect_roi.width - rect_roi.x));
957  for (unsigned int i = (unsigned int)rect_roi.y; i < (unsigned int)rect_roi.height; i++) {
958  for (unsigned int j = (unsigned int)rect_roi.x; j < (unsigned int)rect_roi.width; j++) {
959  I_color_crop[(unsigned int)((int)i - rect_roi.y)][(unsigned int)((int)j - rect_roi.x)] = I_color[i][j];
960  }
961  }
962  filename = vpIoTools::createFilePath(opath, "I_color_crop.ppm");
963  std::cout << " Resulting image saved in: " << filename << std::endl;
964  vpImageIo::write(I_color_crop, filename);
965 
966  unsigned char *rgb_array_crop = new unsigned char[I_color_crop.getSize() * 3];
967  vpImageConvert::RGBaToRGB((unsigned char *)I_color_crop.bitmap, rgb_array_crop, I_color_crop.getSize());
968 
969  unsigned char *rgb2gray_flip_crop_array_sse = new unsigned char[I_color_crop.getSize()];
970  vpImageConvert::RGBToGrey(rgb_array_crop, rgb2gray_flip_crop_array_sse, I_color_crop.getWidth(),
971  I_color_crop.getHeight(), true);
972  vpImage<unsigned char> I_rgb2gray_flip_crop_sse(rgb2gray_flip_crop_array_sse, I_color_crop.getHeight(),
973  I_color_crop.getWidth());
974 
975  filename = vpIoTools::createFilePath(opath, "I_rgb2gray_flip_crop_sse.pgm");
976  std::cout << " Resulting image saved in: " << filename << std::endl;
977  vpImageIo::write(I_rgb2gray_flip_crop_sse, filename);
978 
979  // Test BGR to Grayscale + Flip + Crop
980  std::cout << "\n BGR to Grayscale + Flip + Crop" << std::endl;
981  vpImage<unsigned char> I_bgr2gray_flip_crop_sse(I_color_crop.getHeight(), I_color_crop.getWidth());
982  vpImageConvert::convert(colorMat_crop_continous, I_bgr2gray_flip_crop_sse, true);
983 
984  filename = vpIoTools::createFilePath(opath, "I_bgr2gray_flip_crop_sse.pgm");
985  std::cout << " Resulting image saved in: " << filename << std::endl;
986  vpImageIo::write(I_bgr2gray_flip_crop_sse, filename);
987 
988  // Test BGR to Grayscale + Flip + Crop + No continuous Mat
989  std::cout << "\n BGR to Grayscale + Flip + Crop + No continuous Mat" << std::endl;
990  vpImage<unsigned char> I_bgr2gray_flip_crop_no_continuous_sse(I_color_crop.getHeight(), I_color_crop.getWidth());
991  vpImageConvert::convert(colorMat_crop, I_bgr2gray_flip_crop_no_continuous_sse, true);
992 
993  filename = vpIoTools::createFilePath(opath, "I_bgr2gray_flip_crop_no_continuous_sse.pgm");
994  std::cout << " Resulting image saved in: " << filename << std::endl;
995  vpImageIo::write(I_bgr2gray_flip_crop_no_continuous_sse, filename);
996 
997  delete[] rgb_array_crop;
998 #endif
999  delete[] rgb_array;
1000  std::cout << "Test succeed" << std::endl;
1001  }
1002 
1003  return 0;
1004  } catch (const vpException &e) {
1005  std::cout << "Catch an exception: " << e.getMessage() << std::endl;
1006  return 1;
1007  }
1008 }
static bool checkDirectory(const char *dirname)
Definition: vpIoTools.cpp:467
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1316
static void RGBToGrey(unsigned char *rgb, unsigned char *grey, unsigned int size)
unsigned int getWidth() const
Definition: vpImage.h:239
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
Type * bitmap
points toward the bitmap
Definition: vpImage.h:133
File and directories basic tools.
Definition: vpIoTools.h:156
error that can be emited by ViSP classes.
Definition: vpException.h:71
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 YUVToRGB(unsigned char y, unsigned char u, unsigned char v, unsigned char &r, unsigned char &g, unsigned char &b)
VISP_EXPORT double measureTimeMs()
Definition: vpTime.cpp:88
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:69
Definition: vpRGBa.h:66
static void write(const vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:375
static void makeDirectory(const char *dirname)
Definition: vpIoTools.cpp:597
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1541
unsigned int getSize() const
Definition: vpImage.h:219
static std::string getUserName()
Definition: vpIoTools.cpp:298
void resize(const unsigned int h, const unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:866
Read/write images with various image format.
Definition: vpImageIo.h:120
const char * getMessage(void) const
Definition: vpException.cpp:90
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 RGBaToHSV(const unsigned char *rgba, double *hue, double *saturation, double *value, const unsigned int size)
static void read(vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:207
static void HSVToRGBa(const double *hue, const double *saturation, const double *value, unsigned char *rgba, const unsigned int size)
unsigned int getHeight() const
Definition: vpImage.h:178
static void RGBaToRGB(unsigned char *rgba, unsigned char *rgb, unsigned int size)