ViSP  2.8.0
trackDot2WithAutoDetection.cpp
1 /****************************************************************************
2  *
3  * $Id: trackDot2WithAutoDetection.cpp 4323 2013-07-18 09:24:01Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2013 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  *
34  * Description:
35  * Test auto detection of dots.
36  *
37  * Authors:
38  * Fabien Spindler
39  *
40  *****************************************************************************/
53 #include <visp/vpDebug.h>
54 #include <visp/vpConfig.h>
55 
56 #include <stdlib.h>
57 #include <stdio.h>
58 #include <sstream>
59 #include <iomanip>
60 
61 #if (defined (VISP_HAVE_X11) || defined(VISP_HAVE_GTK) || defined(VISP_HAVE_GDI))
62 
63 #include <visp/vpImage.h>
64 #include <visp/vpImageIo.h>
65 #include <visp/vpImagePoint.h>
66 #include <visp/vpDisplayX.h>
67 #include <visp/vpDisplayGTK.h>
68 #include <visp/vpDisplayGDI.h>
69 #include <visp/vpList.h>
70 #include <visp/vpDot2.h>
71 #include <visp/vpParseArgv.h>
72 #include <visp/vpIoTools.h>
73 
74 // List of allowed command line options
75 #define GETOPTARGS "cdi:p:f:n:s:S:G:E:h"
76 
94 void usage(const char *name, const char *badparam, std::string ipath, std::string ppath,
95  unsigned first, unsigned nimages, unsigned step, double sizePrecision,
96  double grayLevelPrecision, double ellipsoidShapePrecision )
97 {
98  fprintf(stdout, "\n\
99 Test auto detection of dots using vpDot2.\n\
100  \n\
101 SYNOPSIS\n\
102  %s [-i <input image path>] [-p <personal image path>]\n\
103  [-f <first image>] [-n <number of images>] [-s <step>] \n\
104  [-S <size precision>] [-G <gray level precision>]\n\
105  [-E <ellipsoid shape precision>] [-c] [-d] [-h]\n", name);
106 
107  fprintf(stdout, "\n\
108 OPTIONS: Default\n\
109  -i <input image path> %s\n\
110  Set image input path.\n\
111  From this path read images \n\
112  \"ViSP-images/mire-2/image.%%04d.pgm\"\n\
113  Setting the VISP_INPUT_IMAGE_PATH environment\n\
114  variable produces the same behaviour than using\n\
115  this option.\n\
116  \n\
117  -p <personal image path> %s\n\
118  Specify a personal sequence containing images \n\
119  to process.\n\
120  By image sequence, we mean one file per image.\n\
121  The following image file formats PNM (PGM P5, PPM P6)\n\
122  are supported. The format is selected by analysing \n\
123  the filename extension.\n\
124  Example : \"/Temp/ViSP-images/cube/image.%%04d.pgm\"\n\
125  %%04d is for the image numbering.\n\
126  \n\
127  -f <first image> %u\n\
128  First image number of the sequence.\n\
129  \n\
130  -n <number of images> %u\n\
131  Number of images to load from the sequence.\n\
132  \n\
133  -s <step> %u\n\
134  Step between two images.\n\
135  \n\
136  -S <size precision> %f\n\
137  Precision of the size of the dot. \n\
138  It is a double precision float witch value is in ]0,1].\n\
139  1 means full precision, the sizes (width, heigth, surface) \n\
140  of the dots must the same, whereas values close to 0 \n\
141  show a very bad precision.\n\
142 \n\
143  -G <gray level precision> %f\n\
144  Precision of the gray level of the dot. \n\
145  It is a double precision float witch value is in ]0,1].\n\
146  1 means full precision, the gray level must the same in \n\
147  the wall dot, whereas values close to 0 \n\
148  show a very bad precision.\n\
149 \n\
150  -E <ellipsoid shape precision> %f\n\
151  Precision of the ellipsoid shape of the dot. \n\
152  It is a double precision float witch value is in [0,1].\n\
153  1 means full precision, the shape should be a perfect ellipsoid,\n\
154  whereas values close to 0 show a very bad precision.\n\
155  0 means the shape of dots is not tested \n\
156 \n",
157 ipath.c_str(),ppath.c_str(), first, nimages, step, sizePrecision,
158 grayLevelPrecision, ellipsoidShapePrecision );
159 
160  fprintf(stdout, "\
161  -c\n\
162  Disable the mouse click. Useful to automaze the \n\
163  execution of this program without humain intervention.\n\
164  \n\
165  -d \n\
166  Turn off the display.\n\
167  \n\
168  -h\n\
169  Print the help.\n");
170 
171  if (badparam)
172  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
173 }
194 bool getOptions(int argc, const char **argv, std::string &ipath,
195  std::string &ppath,unsigned &first, unsigned &nimages,
196  unsigned &step, double &sizePrecision, double &grayLevelPrecision,
197  double &ellipsoidShapePrecision, bool &click_allowed, bool &display)
198 {
199  const char *optarg;
200  int c;
201  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg)) > 1) {
202 
203  switch (c) {
204  case 'c': click_allowed = false; break;
205  case 'd': display = false; break;
206  case 'i': ipath = optarg; break;
207  case 'p': ppath = optarg; break;
208  case 'f': first = (unsigned) atoi(optarg); break;
209  case 'n': nimages = (unsigned) atoi(optarg); break;
210  case 's': step = (unsigned) atoi(optarg); break;
211  case 'S': sizePrecision = atof(optarg);break;
212  case 'G': grayLevelPrecision = atof(optarg);break;
213  case 'E': ellipsoidShapePrecision = atof(optarg);break;
214  case 'h': usage(argv[0], NULL, ipath, ppath, first, nimages, step,
215  sizePrecision,grayLevelPrecision,ellipsoidShapePrecision);
216  return false; break;
217 
218  default:
219  usage(argv[0], optarg, ipath, ppath, first, nimages, step,
220  sizePrecision,grayLevelPrecision,ellipsoidShapePrecision);
221  return false; break;
222  }
223  }
224 
225  if ((c == 1) || (c == -1)) {
226  // standalone param or error
227  usage(argv[0], NULL, ipath, ppath, first, nimages, step,
228  sizePrecision,grayLevelPrecision,ellipsoidShapePrecision);
229  std::cerr << "ERROR: " << std::endl;
230  std::cerr << " Bad argument " << optarg << std::endl << std::endl;
231  return false;
232  }
233 
234  return true;
235 }
236 
237 
238 int
239 main(int argc, const char ** argv)
240 {
241  std::string env_ipath;
242  std::string opt_ipath;
243  std::string ipath;
244  std::string opt_ppath;
245  std::string dirname;
246  std::string filename;
247  unsigned opt_first = 1;
248  unsigned opt_nimages = 10;
249  unsigned opt_step = 1;
250  double opt_sizePrecision = 0.65;
251  double opt_grayLevelPrecision = 0.85;
252  double opt_ellipsoidShapePrecision = 0.8;
253  bool opt_click_allowed = true;
254  bool opt_display = true;
255 
256  // Get the VISP_IMAGE_PATH environment variable value
257  char *ptenv = getenv("VISP_INPUT_IMAGE_PATH");
258  if (ptenv != NULL)
259  env_ipath = ptenv;
260 
261  // Set the default input path
262  if (! env_ipath.empty())
263  ipath = env_ipath;
264 
265 
266  // Read the command line options
267  if (getOptions(argc, argv, opt_ipath, opt_ppath,opt_first, opt_nimages,
268  opt_step,opt_sizePrecision,opt_grayLevelPrecision,
269  opt_ellipsoidShapePrecision, opt_click_allowed, opt_display) == false) {
270  exit (-1);
271  }
272 
273  // Get the option values
274  if (!opt_ipath.empty())
275  ipath = opt_ipath;
276 
277  // Compare ipath and env_ipath. If they differ, we take into account
278  // the input path comming from the command line option
279  if (!opt_ipath.empty() && !env_ipath.empty() && opt_ppath.empty()) {
280  if (ipath != env_ipath) {
281  std::cout << std::endl
282  << "WARNING: " << std::endl;
283  std::cout << " Since -i <visp image path=" << ipath << "> "
284  << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
285  << " we skip the environment variable." << std::endl;
286  }
287  }
288 
289  // Test if an input path is set
290  if (opt_ipath.empty() && env_ipath.empty()){
291  usage(argv[0], NULL, ipath, opt_ppath, opt_first, opt_nimages,
292  opt_step,opt_sizePrecision,opt_grayLevelPrecision, opt_ellipsoidShapePrecision);
293  std::cerr << std::endl
294  << "ERROR:" << std::endl;
295  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH "
296  << std::endl
297  << " environment variable to specify the location of the " << std::endl
298  << " image path where test images are located." << std::endl << std::endl
299  << " Use -p <personal image path> option if you want to "<<std::endl
300  << " use personal images." << std::endl;
301  exit(-1);
302  }
303 
304 
305  // Declare an image, this is a gray level image (unsigned char)
306  // it size is not defined yet, it will be defined when the image will
307  // read on the disk
309  std::ostringstream s;
310  char cfilename[FILENAME_MAX];
311  unsigned iter = opt_first; // Image number
312 
313  if (opt_ppath.empty()){
314 
315 
316  // Warning :
317  // the image sequence is not provided with the ViSP package
318  // therefore the program will return you an error :
319  // !! vpImageIoPnm.cpp: readPGM(#210) :couldn't read file
320  // ViSP-images/cube/image.0001.pgm
321  // !! vpDotExample.cpp: main(#95) :Error while reading the image
322  // terminate called after throwing an instance of 'vpImageException'
323  //
324  // The sequence is available on the visp www site
325  // http://www.irisa.fr/lagadic/visp/visp.html
326  // in the download section. It is named "ViSP-images.tar.gz"
327 
328  // Set the path location of the image sequence
329  dirname = ipath + vpIoTools::path("/ViSP-images/mire-2/");
330 
331  // Build the name of the image file
332 
333  s.setf(std::ios::right, std::ios::adjustfield);
334  s << "image." << std::setw(4) << std::setfill('0') << iter << ".pgm";
335  filename = dirname + s.str();
336  }
337  else {
338 
339  sprintf(cfilename,opt_ppath.c_str(), iter) ;
340  filename = cfilename;
341  }
342  // Read the PGM image named "filename" on the disk, and put the
343  // bitmap into the image structure I. I is initialized to the
344  // correct size
345  //
346  // exception readPGM may throw various exception if, for example,
347  // the file does not exist, or if the memory cannot be allocated
348  try{
349  vpCTRACE << "Load: " << filename << std::endl;
350 
351  vpImageIo::read(I, filename) ;
352  }
353  catch(...)
354  {
355  // an exception is throwned if an exception from readPGM has been catched
356  // here this will result in the end of the program
357  // Note that another error message has been printed from readPGM
358  // to give more information about the error
359  std::cerr << std::endl
360  << "ERROR:" << std::endl;
361  std::cerr << " Cannot read " << filename << std::endl;
362  std::cerr << " Check your -i " << ipath << " option " << std::endl
363  << " or your -p " << opt_ppath << " option " <<std::endl
364  << " or VISP_INPUT_IMAGE_PATH environment variable."
365  << std::endl;
366  exit(-1);
367  }
368 
369 
370  // We open a window using either GTK, X11 or GDI.
371 #if defined VISP_HAVE_GTK
372  vpDisplayGTK display;
373 #elif defined VISP_HAVE_X11
374  vpDisplayX display;
375 #elif defined VISP_HAVE_GDI
376  vpDisplayGDI display;
377 #endif
378 
379  if (opt_display) {
380  try{
381  // Display size is automatically defined by the image (I) size
382  display.init(I, 100, 100,"Display...") ;
383  // Display the image
384  // The image class has a member that specify a pointer toward
385  // the display that has been initialized in the display declaration
386  // therefore is is no longuer necessary to make a reference to the
387  // display variable.
388  vpDisplay::display(I) ;
389  vpDisplay::flush(I) ;
390  }
391  catch(...)
392  {
393  vpERROR_TRACE("Error while displaying the image") ;
394  exit(-1);
395  }
396  }
397 
398  // Dot declaration
399  vpDot2 d ;
400 
401  d.setGraphics(true);
402  if (opt_click_allowed & opt_display) {
403  try{
404  d.setGrayLevelPrecision(opt_grayLevelPrecision);
405 
406  std::cout << "Please click on a dot to initialize detection"
407  << std::endl;
408 
409  d.initTracking(I) ;
410  if (opt_display) {
411  vpImagePoint cog;
412  cog = d.getCog();
414  vpDisplay::flush(I) ;
415  }
416  d.setSizePrecision(opt_sizePrecision);
417  d.setEllipsoidShapePrecision(opt_ellipsoidShapePrecision);
418  printf("Dot characteristics: \n");
419  printf(" width : %lf\n", d.getWidth());
420  printf(" height: %lf\n", d.getHeight());
421  printf(" surface: %lf\n", d.getSurface());
422  printf(" gray level min: %d\n", d.getGrayLevelMin());
423  printf(" gray level max: %d\n", d.getGrayLevelMax());
424  printf(" grayLevelPrecision: %lf\n", d.getGrayLevelPrecision());
425  printf(" sizePrecision: %lf\n", d.getSizePrecision());
426  printf(" ellipsoidShapePrecision: %lf\n", d.getEllipsoidShapePrecision());
427  }
428  catch(...)
429  {
430  std::cerr << "Cannot initialize the tracking..."<< std::endl;
431  exit(-1);
432  }
433  }
434  else{
435  // Set dot characteristics for the auto detection
436  d.setGraphics(true);
437  d.setWidth(15.0);
438  d.setHeight(12.0);
439  d.setSurface(124);
440  d.setGrayLevelMin(164);
441  d.setGrayLevelMax(255);
442  d.setGrayLevelPrecision(opt_grayLevelPrecision);
443  d.setSizePrecision(opt_sizePrecision);
444  d.setEllipsoidShapePrecision(opt_ellipsoidShapePrecision);
445  }
446 
447  while (iter < opt_first + opt_nimages*opt_step)
448  {
449 
450  // set the new image name
451 
452  if (opt_ppath.empty()){
453 
454  s.str("");
455  s << "image." << std::setw(4) << std::setfill('0') << iter << ".pgm";
456  filename = dirname + s.str();
457  }
458  else {
459  sprintf(cfilename, opt_ppath.c_str(), iter) ;
460  filename = cfilename;
461  }
462  // read the image
463  vpImageIo::read(I, filename);
464 
465  if (opt_display) {
466  // Display the image
467  vpDisplay::display(I) ;
468  }
469 
470  std::cout << "Search dots in image" << filename << std::endl;
471  std::list<vpDot2> list_d;
472  d.searchDotsInArea(I, 0, 0, I.getWidth(), I.getHeight(), list_d) ;
473 
474  if( list_d.empty() ) {
475  std::cout << "Dot auto detection did not work." << std::endl;
476  return(-1) ;
477  }
478  else {
479  std::cout << std::endl << list_d.size() << " dots are detected" << std::endl;
480 
481  if (opt_display) {
482  int i=0;
483  // Parse all founded dots for display
484  for (std::list<vpDot2>::const_iterator it = list_d.begin(); it != list_d.end(); ++ it)
485  {
486  vpImagePoint cog = (*it).getCog();
487 
488  std::cout << "Dot " << i++ << " : " << cog.get_u()
489  << " " << cog.get_v() << std::endl;
490 
491  vpDisplay::displayCross(I, cog, 16, vpColor::blue, 3) ;
492  }
493  vpDisplay::flush(I);
494  }
495  }
496 
497  // If click is allowed, wait for a mouse click to launch the next iteration
498  if (opt_display && opt_click_allowed) {
499  std::cout << "\nA click to continue..." << std::endl;
500  // Wait for a blocking mouse click
502  }
503 
504  iter += opt_step ;
505  }
506  if (opt_display && opt_click_allowed) {
507  std::cout << "\nA click to exit..." << std::endl;
508  // Wait for a blocking mouse click
510  }
511  vpTRACE("End...");
512 }
513 #else
514 int
515 main()
516 {
517  vpERROR_TRACE("You do not have X11, GTK or GDI display functionalities...");
518 }
519 
520 #endif
521 
522 
523 /*
524  * Local variables:
525  * c-basic-offset: 2
526  * End:
527  */
double getWidth() const
Definition: vpDot2.cpp:627
void setGrayLevelMax(const unsigned int &max)
Definition: vpDot2.h:347
double get_v() const
Definition: vpImagePoint.h:250
void searchDotsInArea(const vpImage< unsigned char > &I, int area_u, int area_v, unsigned int area_w, unsigned int area_h, std::list< vpDot2 > &niceDots)
Definition: vpDot2.cpp:1619
unsigned int getWidth() const
Definition: vpImage.h:159
#define vpERROR_TRACE
Definition: vpDebug.h:379
#define vpTRACE
Definition: vpDebug.h:401
double getSurface() const
Definition: vpDot2.cpp:652
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:133
double getGrayLevelPrecision() const
Definition: vpDot2.cpp:671
double get_u() const
Definition: vpImagePoint.h:239
Define the X11 console to display images.
Definition: vpDisplayX.h:152
static std::string path(const char *pathname)
Definition: vpIoTools.cpp:715
double getHeight() const
Definition: vpDot2.cpp:637
double getEllipsoidShapePrecision() const
Definition: vpDot2.cpp:693
static const vpColor green
Definition: vpColor.h:170
This tracker is meant to track a blob (connex pixels with same gray level) on a vpImage.
Definition: vpDot2.h:131
static void flush(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:1991
double getSizePrecision() const
Definition: vpDot2.cpp:681
void setSurface(const double &surface)
Definition: vpDot2.cpp:762
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:79
#define vpCTRACE
Definition: vpDebug.h:327
vpImagePoint getCog() const
Definition: vpDot2.h:167
void setGrayLevelPrecision(const double &grayLevelPrecision)
Definition: vpDot2.cpp:796
static void display(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:203
virtual void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)=0
The vpDisplayGTK allows to display image using the GTK+ library version 1.2.
Definition: vpDisplayGTK.h:145
unsigned int getGrayLevelMin() const
Definition: vpDot2.h:204
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const char *title=NULL)
void setEllipsoidShapePrecision(const double &ellipsoidShapePrecision)
Definition: vpDot2.cpp:871
void setGrayLevelMin(const unsigned int &min)
Definition: vpDot2.h:331
void setWidth(const double &width)
Definition: vpDot2.cpp:731
void setSizePrecision(const double &sizePrecision)
Definition: vpDot2.cpp:826
void initTracking(const vpImage< unsigned char > &I, unsigned int size=0)
Definition: vpDot2.cpp:245
void setHeight(const double &height)
Definition: vpDot2.cpp:746
unsigned int getHeight() const
Definition: vpImage.h:150
virtual bool getClick(bool blocking=true)=0
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:92
static void read(vpImage< unsigned char > &I, const char *filename)
Definition: vpImageIo.cpp:277
unsigned int getGrayLevelMax() const
Definition: vpDot2.h:212
void setGraphics(const bool activate)
Definition: vpDot2.h:312
static const vpColor blue
Definition: vpColor.h:173