Visual Servoing Platform  version 3.2.0 under development (2019-01-22)
displaySequence.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  * Read an image sequence from the disk and display it.
33  *
34  * Authors:
35  * Eric Marchand
36  * Fabien Spindler
37  * Anthony Saunier
38  *
39  *****************************************************************************/
50 #include <iomanip>
51 #include <sstream>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <visp3/core/vpConfig.h>
55 #include <visp3/core/vpDebug.h>
56 #include <visp3/core/vpIoTools.h>
57 #include <visp3/io/vpParseArgv.h>
58 #if (defined(VISP_HAVE_GTK) || defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI))
59 
60 #include <visp3/core/vpImage.h>
61 #include <visp3/io/vpImageIo.h>
62 
63 #include <visp3/gui/vpDisplayGDI.h>
64 #include <visp3/gui/vpDisplayGTK.h>
65 #include <visp3/gui/vpDisplayX.h>
66 
67 #include <visp3/core/vpTime.h>
68 
79 // List of allowed command line options
80 #define GETOPTARGS "di:p:hf:n:s:w"
81 
82 void usage(const char *name, const char *badparam, std::string ipath, std::string ppath, unsigned first,
83  unsigned nimages, unsigned step);
84 bool getOptions(int argc, const char **argv, std::string &ipath, std::string &ppath, unsigned &first, unsigned &nimages,
85  unsigned &step, bool &display, bool &wait);
86 
100 void usage(const char *name, const char *badparam, std::string ipath, std::string ppath, unsigned first,
101  unsigned nimages, unsigned step)
102 {
103  fprintf(stdout, "\n\
104 Read an image sequence from the disk and display it.\n\
105 The sequence is made of separate images. Each image corresponds\n\
106 to a PGM file.\n\
107 \n\
108 SYNOPSIS\n\
109  %s [-i <test image path>] [-p <personal image path>]\n\
110  [-f <first image>] [-n <number of images>] [-s <step>] \n\
111  [-w] [-d] [-h]\n \
112  ", name);
113 
114  fprintf(stdout, "\n\
115  OPTIONS: Default\n\
116  -i <test image path> %s\n\
117  Set image input path.\n\
118  From this path read \"cube/image.%%04d.pgm\"\n\
119  images. These images come from ViSP-images-x.y.z.tar.gz\n\
120  available on the ViSP website.\n\
121  Setting the VISP_INPUT_IMAGE_PATH environment\n\
122  variable produces the same behaviour than using\n\
123  this option.\n\
124  \n\
125  -p <personal image path> %s\n\
126  Specify a personal sequence containing images \n\
127  to process.\n\
128  By image sequence, we mean one file per image.\n\
129  The following image file formats PNM (PGM P5, PPM P6)\n\
130  are supported. The format is selected by analysing \n\
131  the filename extension.\n\
132  Example : \"/Temp/ViSP-images/cube/image.%%04d.pgm\"\n\
133  %%04d is for the image numbering.\n\
134  \n\
135  -f <first image> %u\n\
136  First image number of the sequence.\n\
137  \n\
138  -n <number of images> %u\n\
139  Number of images to load from the sequence.\n\
140  \n\
141  -s <step> %u\n\
142  Step between two images.\n\
143 \n\
144  -d \n\
145  Disable the image display. This can be useful \n\
146  for automatic tests using crontab under Unix or \n\
147  using the task manager under Windows.\n\
148 \n\
149  -w\n\
150  Wait for a mouse click between two images.\n\
151  If the image display is disabled (using -d)\n\
152  this option is without effect.\n\
153 \n\
154  -h\n\
155  Print the help.\n\n", ipath.c_str(), ppath.c_str(), first, nimages, step);
156 
157  if (badparam)
158  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
159 }
181 bool getOptions(int argc, const char **argv, std::string &ipath, std::string &ppath, unsigned &first, unsigned &nimages,
182  unsigned &step, bool &display, bool &wait)
183 {
184  const char *optarg_;
185  int c;
186  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
187 
188  switch (c) {
189  case 'd':
190  display = false;
191  break;
192  case 'i':
193  ipath = optarg_;
194  break;
195  case 'p':
196  ppath = optarg_;
197  break;
198  case 'f':
199  first = (unsigned)atoi(optarg_);
200  break;
201  case 'n':
202  nimages = (unsigned)atoi(optarg_);
203  break;
204  case 's':
205  step = (unsigned)atoi(optarg_);
206  break;
207  case 'w':
208  wait = true;
209  break;
210  case 'h':
211  usage(argv[0], NULL, ipath, ppath, first, nimages, step);
212  return false;
213  break;
214 
215  default:
216  usage(argv[0], optarg_, ipath, ppath, first, nimages, step);
217  return false;
218  break;
219  }
220  }
221 
222  if ((c == 1) || (c == -1)) {
223  // standalone param or error
224  usage(argv[0], NULL, ipath, ppath, first, nimages, step);
225  std::cerr << "ERROR: " << std::endl;
226  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
227  return false;
228  }
229 
230  return true;
231 }
232 
233 int main(int argc, const char **argv)
234 {
235  try {
236  std::string env_ipath;
237  std::string opt_ipath;
238  std::string ipath;
239  std::string opt_ppath;
240  std::string dirname;
241  std::string filename;
242  unsigned opt_first = 0;
243  unsigned opt_nimages = 80;
244  unsigned opt_step = 1;
245  bool opt_display = true;
246  bool opt_wait = false;
247 
248  // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
249  // environment variable value
250  env_ipath = vpIoTools::getViSPImagesDataPath();
251 
252  // Set the default input path
253  if (!env_ipath.empty())
254  ipath = env_ipath;
255 
256  // Read the command line options
257  if (getOptions(argc, argv, opt_ipath, opt_ppath, opt_first, opt_nimages, opt_step, opt_display, opt_wait) ==
258  false) {
259  exit(-1);
260  }
261 
262  if (!opt_display)
263  opt_wait = false; // turn off the waiting
264 
265  // Get the option values
266  if (!opt_ipath.empty())
267  ipath = opt_ipath;
268 
269  // Compare ipath and env_ipath. If they differ, we take into account
270  // the input path comming from the command line option
271  if (!opt_ipath.empty() && !env_ipath.empty() && opt_ppath.empty()) {
272  if (ipath != env_ipath) {
273  std::cout << std::endl << "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;
277  }
278  }
279 
280  // Test if an input path is set
281  if (opt_ipath.empty() && env_ipath.empty() && opt_ppath.empty()) {
282  usage(argv[0], NULL, ipath, opt_ppath, opt_first, opt_nimages, opt_step);
283  std::cerr << std::endl << "ERROR:" << std::endl;
284  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
285  << " environment variable to specify the location of the " << std::endl
286  << " image path where test images are located." << std::endl
287  << " Use -p <personal image path> option if you want to " << std::endl
288  << " use personal images." << std::endl
289  << std::endl;
290 
291  exit(-1);
292  }
293 
294  // Declare an image, this is a gray level image (unsigned char)
295  // it size is not defined yet, it will be defined when the image will
296  // read on the disk
298 
299  unsigned iter = opt_first;
300  std::ostringstream s;
301  char cfilename[FILENAME_MAX];
302 
303  if (opt_ppath.empty()) {
304 
305  // Warning :
306  // the image sequence is not provided with the ViSP package
307  // therefore the program will return you an error :
308  // !! vpImageIoPnm.cpp: readPGM(#210) :couldn't read file
309  // ViSP-images/cube/image.0001.pgm
310  // !! vpDotExample.cpp: main(#95) :Error while reading the image
311  // terminate called after throwing an instance of 'vpImageException'
312  //
313  // The sequence is available on the visp www site
314  // https://visp.inria.fr/download/
315  // in the download section. It is named "ViSP-images.tar.gz"
316 
317  // Set the path location of the image sequence
318  dirname = vpIoTools::createFilePath(ipath, "cube");
319 
320  // Build the name of the image file
321 
322  s.setf(std::ios::right, std::ios::adjustfield);
323  s << "image." << std::setw(4) << std::setfill('0') << iter << ".pgm";
324  filename = vpIoTools::createFilePath(dirname, s.str());
325  } else {
326  sprintf(cfilename, opt_ppath.c_str(), iter);
327  filename = cfilename;
328  }
329  // Read the PGM image named "filename" on the disk, and put the
330  // bitmap into the image structure I. I is initialized to the
331  // correct size
332  //
333  // exception readPGM may throw various exception if, for example,
334  // the file does not exist, or if the memory cannot be allocated
335  try {
336  vpImageIo::read(I, filename);
337  } catch (...) {
338  // an exception is throwned if an exception from readPGM has been
339  // catched here this will result in the end of the program Note that
340  // another error message has been printed from readPGM to give more
341  // information about the error
342  std::cerr << std::endl << "ERROR:" << std::endl;
343  std::cerr << " Cannot read " << filename << std::endl;
344  std::cerr << " Check your -i " << ipath << " option, " << std::endl
345  << " or your -p " << opt_ppath << " option " << std::endl
346  << " or VISP_INPUT_IMAGE_PATH environment variable" << std::endl;
347  exit(-1);
348  }
349 
350 #if defined VISP_HAVE_GTK
351  vpDisplayGTK display;
352 #elif defined VISP_HAVE_X11
353  vpDisplayX display;
354 #elif defined VISP_HAVE_GDI
355  vpDisplayGDI display;
356 #endif
357  if (opt_display) {
358 
359  // We open a window using either X11 or GTK or GDI.
360  // Its size is automatically defined by the image (I) size
361  display.init(I, 100, 100, "Display...");
362 
363  // Display the image
364  // The image class has a member that specify a pointer toward
365  // the display that has been initialized in the display declaration
366  // therefore is is no longuer necessary to make a reference to the
367  // display variable.
369  vpDisplay::flush(I);
370  }
371 
372  // double tms_1 = vpTime::measureTimeMs() ;
373  unsigned niter = 0;
374  // this is the loop over the image sequence
375  while (iter < opt_first + opt_nimages * opt_step) {
376  double tms = vpTime::measureTimeMs();
377 
378  // set the new image name
379 
380  if (opt_ppath.empty()) {
381  s.str("");
382  s << "image." << std::setw(4) << std::setfill('0') << iter << ".pgm";
383  filename = vpIoTools::createFilePath(dirname, s.str());
384  } else {
385  sprintf(cfilename, opt_ppath.c_str(), iter);
386  filename = cfilename;
387  }
388 
389  std::cout << "read : " << filename << std::endl;
390  // read the image
391  vpImageIo::read(I, filename);
392  if (opt_display) {
393  // Display the image
395  // Flush the display
396  vpDisplay::flush(I);
397  }
398  if (opt_wait) {
399  std::cout << "A click in the image to continue..." << std::endl;
400  // Wait for a blocking mouse click
402  } else {
403  // Synchronise the loop to 40 ms
404  vpTime::wait(tms, 40);
405  }
406  niter++;
407 
408  iter += opt_step;
409  }
410  // double tms_2 = vpTime::measureTimeMs() ;
411  // double tms_total = tms_2 - tms_1 ;
412  // std::cout << "Total Time : "<< tms_total<<std::endl;
413  return EXIT_SUCCESS;
414  } catch (const vpException &e) {
415  std::cout << "Catch an exception: " << e << std::endl;
416  return EXIT_FAILURE;
417  }
418 }
419 #else
420 int main() {
421  std::cout << "You do not have X11, or GDI (Graphical Device Interface), or GTK functionalities to display images..." << std::endl;
422  std::cout << "Tip if you are on a unix-like system:" << std::endl;
423  std::cout << "- Install X11, configure again ViSP using cmake and build again this example" << std::endl;
424  std::cout << "Tip if you are on a windows-like system:" << std::endl;
425  std::cout << "- Install GDI, configure again ViSP using cmake and build again this example" << std::endl;
426  return EXIT_SUCCESS;
427 }
428 #endif
VISP_EXPORT int wait(double t0, double t)
Definition: vpTime.cpp:150
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1316
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:129
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition: vpDisplayX.h:151
error that can be emited by ViSP classes.
Definition: vpException.h:71
static void flush(const vpImage< unsigned char > &I)
VISP_EXPORT double measureTimeMs()
Definition: vpTime.cpp:88
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:69
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1541
static void display(const vpImage< unsigned char > &I)
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
Definition: vpDisplayGTK.h:138
static void read(vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:207
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="")