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