ViSP  2.10.0
trackDot2WithAutoDetection.cpp
1 /****************************************************************************
2  *
3  * $Id: trackDot2WithAutoDetection.cpp 5108 2015-01-05 07:48:58Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2014 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) || defined(VISP_HAVE_OPENCV))
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/vpDisplayOpenCV.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 
77 void usage(const char *name, const char *badparam, std::string ipath, std::string ppath,
78  unsigned first, unsigned nimages, unsigned step, double sizePrecision,
79  double grayLevelPrecision, double ellipsoidShapePrecision );
80 bool getOptions(int argc, const char **argv, std::string &ipath,
81  std::string &ppath,unsigned &first, unsigned &nimages,
82  unsigned &step, double &sizePrecision, double &grayLevelPrecision,
83  double &ellipsoidShapePrecision, bool &click_allowed, bool &display);
84 
102 void usage(const char *name, const char *badparam, std::string ipath, std::string ppath,
103  unsigned first, unsigned nimages, unsigned step, double sizePrecision,
104  double grayLevelPrecision, double ellipsoidShapePrecision)
105 {
106  fprintf(stdout, "\n\
107 Test auto detection of dots using vpDot2.\n\
108  \n\
109 SYNOPSIS\n\
110  %s [-i <input image path>] [-p <personal image path>]\n\
111  [-f <first image>] [-n <number of images>] [-s <step>] \n\
112  [-S <size precision>] [-G <gray level precision>]\n\
113  [-E <ellipsoid shape precision>] [-c] [-d] [-h]\n", name);
114 
115  fprintf(stdout, "\n\
116 OPTIONS: Default\n\
117  -i <input image path> %s\n\
118  Set image input path.\n\
119  From this path read images \n\
120  \"ViSP-images/mire-2/image.%%04d.pgm\"\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  -S <size precision> %f\n\
145  Precision of the size of the dot. \n\
146  It is a double precision float witch value is in ]0,1].\n\
147  1 means full precision, the sizes (width, heigth, surface) \n\
148  of the dots must the same, whereas values close to 0 \n\
149  show a very bad precision.\n\
150 \n\
151  -G <gray level precision> %f\n\
152  Precision of the gray level of the dot. \n\
153  It is a double precision float witch value is in ]0,1].\n\
154  1 means full precision, the gray level must the same in \n\
155  the wall dot, whereas values close to 0 \n\
156  show a very bad precision.\n\
157 \n\
158  -E <ellipsoid shape precision> %f\n\
159  Precision of the ellipsoid shape of the dot. \n\
160  It is a double precision float witch value is in [0,1].\n\
161  1 means full precision, the shape should be a perfect ellipsoid,\n\
162  whereas values close to 0 show a very bad precision.\n\
163  0 means the shape of dots is not tested \n\
164 \n",
165 ipath.c_str(),ppath.c_str(), first, nimages, step, sizePrecision,
166 grayLevelPrecision, ellipsoidShapePrecision );
167 
168  fprintf(stdout, "\
169  -c\n\
170  Disable the mouse click. Useful to automaze the \n\
171  execution of this program without humain intervention.\n\
172  \n\
173  -d \n\
174  Turn off the display.\n\
175  \n\
176  -h\n\
177  Print the help.\n");
178 
179  if (badparam)
180  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
181 }
202 bool getOptions(int argc, const char **argv, std::string &ipath,
203  std::string &ppath,unsigned &first, unsigned &nimages,
204  unsigned &step, double &sizePrecision, double &grayLevelPrecision,
205  double &ellipsoidShapePrecision, bool &click_allowed, bool &display)
206 {
207  const char *optarg_;
208  int c;
209  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
210 
211  switch (c) {
212  case 'c': click_allowed = false; break;
213  case 'd': display = false; break;
214  case 'i': ipath = optarg_; break;
215  case 'p': ppath = optarg_; break;
216  case 'f': first = (unsigned) atoi(optarg_); break;
217  case 'n': nimages = (unsigned) atoi(optarg_); break;
218  case 's': step = (unsigned) atoi(optarg_); break;
219  case 'S': sizePrecision = atof(optarg_);break;
220  case 'G': grayLevelPrecision = atof(optarg_);break;
221  case 'E': ellipsoidShapePrecision = atof(optarg_);break;
222  case 'h': usage(argv[0], NULL, ipath, ppath, first, nimages, step,
223  sizePrecision,grayLevelPrecision,ellipsoidShapePrecision);
224  return false; break;
225 
226  default:
227  usage(argv[0], optarg_, ipath, ppath, first, nimages, step,
228  sizePrecision,grayLevelPrecision,ellipsoidShapePrecision);
229  return false; break;
230  }
231  }
232 
233  if ((c == 1) || (c == -1)) {
234  // standalone param or error
235  usage(argv[0], NULL, ipath, ppath, first, nimages, step,
236  sizePrecision,grayLevelPrecision,ellipsoidShapePrecision);
237  std::cerr << "ERROR: " << std::endl;
238  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
239  return false;
240  }
241 
242  return true;
243 }
244 
245 
246 int
247 main(int argc, const char ** argv)
248 {
249  try {
250  std::string env_ipath;
251  std::string opt_ipath;
252  std::string ipath;
253  std::string opt_ppath;
254  std::string dirname;
255  std::string filename;
256  unsigned opt_first = 1;
257  unsigned opt_nimages = 10;
258  unsigned opt_step = 1;
259  double opt_sizePrecision = 0.65;
260  double opt_grayLevelPrecision = 0.85;
261  double opt_ellipsoidShapePrecision = 0.8;
262  bool opt_click_allowed = true;
263  bool opt_display = true;
264 
265  // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH environment variable value
266  env_ipath = vpIoTools::getViSPImagesDataPath();
267 
268  // Set the default input path
269  if (! env_ipath.empty())
270  ipath = env_ipath;
271 
272  // Read the command line options
273  if (getOptions(argc, argv, opt_ipath, opt_ppath,opt_first, opt_nimages,
274  opt_step,opt_sizePrecision,opt_grayLevelPrecision,
275  opt_ellipsoidShapePrecision, opt_click_allowed, opt_display) == false) {
276  exit (-1);
277  }
278 
279  // Get the option values
280  if (!opt_ipath.empty())
281  ipath = opt_ipath;
282 
283  // Compare ipath and env_ipath. If they differ, we take into account
284  // the input path comming from the command line option
285  if (!opt_ipath.empty() && !env_ipath.empty() && opt_ppath.empty()) {
286  if (ipath != env_ipath) {
287  std::cout << std::endl
288  << "WARNING: " << std::endl;
289  std::cout << " Since -i <visp image path=" << ipath << "> "
290  << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
291  << " we skip the environment variable." << std::endl;
292  }
293  }
294 
295  // Test if an input path is set
296  if (opt_ipath.empty() && env_ipath.empty()){
297  usage(argv[0], NULL, ipath, opt_ppath, opt_first, opt_nimages,
298  opt_step,opt_sizePrecision,opt_grayLevelPrecision, opt_ellipsoidShapePrecision);
299  std::cerr << std::endl
300  << "ERROR:" << std::endl;
301  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH "
302  << std::endl
303  << " environment variable to specify the location of the " << std::endl
304  << " image path where test images are located." << std::endl << std::endl
305  << " Use -p <personal image path> option if you want to "<<std::endl
306  << " use personal images." << std::endl;
307  exit(-1);
308  }
309 
310 
311  // Declare an image, this is a gray level image (unsigned char)
312  // it size is not defined yet, it will be defined when the image will
313  // read on the disk
315  std::ostringstream s;
316  char cfilename[FILENAME_MAX];
317  unsigned iter = opt_first; // Image number
318 
319  if (opt_ppath.empty()){
320 
321 
322  // Warning :
323  // the image sequence is not provided with the ViSP package
324  // therefore the program will return you an error :
325  // !! vpImageIoPnm.cpp: readPGM(#210) :couldn't read file
326  // ViSP-images/cube/image.0001.pgm
327  // !! vpDotExample.cpp: main(#95) :Error while reading the image
328  // terminate called after throwing an instance of 'vpImageException'
329  //
330  // The sequence is available on the visp www site
331  // http://www.irisa.fr/lagadic/visp/visp.html
332  // in the download section. It is named "ViSP-images.tar.gz"
333 
334  // Set the path location of the image sequence
335  dirname = vpIoTools::createFilePath(ipath, "ViSP-images/mire-2");
336 
337  // Build the name of the image file
338 
339  s.setf(std::ios::right, std::ios::adjustfield);
340  s << "image." << std::setw(4) << std::setfill('0') << iter << ".pgm";
341  filename = vpIoTools::createFilePath(dirname, s.str());
342  }
343  else {
344 
345  sprintf(cfilename,opt_ppath.c_str(), iter) ;
346  filename = cfilename;
347  }
348  // Read the PGM image named "filename" on the disk, and put the
349  // bitmap into the image structure I. I is initialized to the
350  // correct size
351  //
352  // exception readPGM may throw various exception if, for example,
353  // the file does not exist, or if the memory cannot be allocated
354  try{
355  vpCTRACE << "Load: " << filename << std::endl;
356 
357  vpImageIo::read(I, filename) ;
358  }
359  catch(...)
360  {
361  // an exception is throwned if an exception from readPGM has been catched
362  // here this will result in the end of the program
363  // Note that another error message has been printed from readPGM
364  // to give more information about the error
365  std::cerr << std::endl
366  << "ERROR:" << std::endl;
367  std::cerr << " Cannot read " << filename << std::endl;
368  std::cerr << " Check your -i " << ipath << " option " << std::endl
369  << " or your -p " << opt_ppath << " option " <<std::endl
370  << " or VISP_INPUT_IMAGE_PATH environment variable."
371  << std::endl;
372  exit(-1);
373  }
374 
375 
376  // We open a window using either GTK, X11 or GDI.
377 #if defined VISP_HAVE_GTK
378  vpDisplayGTK display;
379 #elif defined VISP_HAVE_X11
380  vpDisplayX display;
381 #elif defined VISP_HAVE_GDI
382  vpDisplayGDI display;
383 #elif defined VISP_HAVE_OPENCV
384  vpDisplayOpenCV display;
385 #endif
386 
387  if (opt_display) {
388  // Display size is automatically defined by the image (I) size
389  display.init(I, 100, 100,"Display...") ;
390  // Display the image
391  // The image class has a member that specify a pointer toward
392  // the display that has been initialized in the display declaration
393  // therefore is is no longuer necessary to make a reference to the
394  // display variable.
395  vpDisplay::display(I) ;
396  vpDisplay::flush(I) ;
397  }
398 
399  // Dot declaration
400  vpDot2 d ;
401 
402  d.setGraphics(true);
403  if (opt_click_allowed & opt_display) {
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(" area: %lf\n", d.getArea());
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  else{
429  // Set dot characteristics for the auto detection
430  d.setGraphics(true);
431  d.setWidth(15.0);
432  d.setHeight(12.0);
433  d.setArea(124);
434  d.setGrayLevelMin(164);
435  d.setGrayLevelMax(255);
436  d.setGrayLevelPrecision(opt_grayLevelPrecision);
437  d.setSizePrecision(opt_sizePrecision);
438  d.setEllipsoidShapePrecision(opt_ellipsoidShapePrecision);
439  }
440 
441  while (iter < opt_first + opt_nimages*opt_step)
442  {
443  // set the new image name
444 
445  if (opt_ppath.empty()){
446 
447  s.str("");
448  s << "image." << std::setw(4) << std::setfill('0') << iter << ".pgm";
449  filename = vpIoTools::createFilePath(dirname, s.str());
450  }
451  else {
452  sprintf(cfilename, opt_ppath.c_str(), iter) ;
453  filename = cfilename;
454  }
455  // read the image
456  vpImageIo::read(I, filename);
457 
458  if (opt_display) {
459  // Display the image
460  vpDisplay::display(I) ;
461  }
462 
463  std::cout << "Search dots in image" << filename << std::endl;
464  std::list<vpDot2> list_d;
465  d.searchDotsInArea(I, 0, 0, I.getWidth(), I.getHeight(), list_d) ;
466 
467  if( list_d.empty() ) {
468  std::cout << "Dot auto detection did not work." << std::endl;
469  return(-1) ;
470  }
471  else {
472  std::cout << std::endl << list_d.size() << " dots are detected" << std::endl;
473 
474  if (opt_display) {
475  int i=0;
476  // Parse all founded dots for display
477  for (std::list<vpDot2>::const_iterator it = list_d.begin(); it != list_d.end(); ++ it)
478  {
479  vpImagePoint cog = (*it).getCog();
480 
481  std::cout << "Dot " << i++ << " : " << cog.get_u()
482  << " " << cog.get_v() << std::endl;
483 
484  vpDisplay::displayCross(I, cog, 16, vpColor::blue, 3) ;
485  }
486  vpDisplay::flush(I);
487  }
488  }
489 
490  // If click is allowed, wait for a mouse click to launch the next iteration
491  if (opt_display && opt_click_allowed) {
492  std::cout << "\nA click to continue..." << std::endl;
493  // Wait for a blocking mouse click
495  }
496 
497  iter += opt_step ;
498  }
499  if (opt_display && opt_click_allowed) {
500  std::cout << "\nA click to exit..." << std::endl;
501  // Wait for a blocking mouse click
503  }
504 
505  return 0;
506  }
507  catch(vpException e) {
508  std::cout << "Catch an exception: " << e << std::endl;
509  return 1;
510  }
511 }
512 #else
513 int
514 main()
515 {
516  vpERROR_TRACE("You do not have X11, GTK, GDI or OpenCV display functionalities...");
517 }
518 
519 #endif
520 
521 
522 /*
523  * Local variables:
524  * c-basic-offset: 2
525  * End:
526  */
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const char *title=NULL)
double getWidth() const
Definition: vpDot2.cpp:648
void setGrayLevelMax(const unsigned int &max)
Definition: vpDot2.h:347
double get_v() const
Definition: vpImagePoint.h:264
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:1045
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1071
unsigned int getWidth() const
Definition: vpImage.h:161
#define vpERROR_TRACE
Definition: vpDebug.h:395
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:132
double getGrayLevelPrecision() const
Definition: vpDot2.cpp:678
double get_u() const
Definition: vpImagePoint.h:253
Define the X11 console to display images.
Definition: vpDisplayX.h:152
error that can be emited by ViSP classes.
Definition: vpException.h:76
double getHeight() const
Definition: vpDot2.cpp:658
double getArea() const
Definition: vpDot2.cpp:668
double getEllipsoidShapePrecision() const
Definition: vpDot2.cpp:700
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:127
static void flush(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:2232
double getSizePrecision() const
Definition: vpDot2.cpp:688
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:80
#define vpCTRACE
Definition: vpDebug.h:341
vpImagePoint getCog() const
Definition: vpDot2.h:163
void setGrayLevelPrecision(const double &grayLevelPrecision)
Definition: vpDot2.cpp:788
static std::string createFilePath(const std::string &parent, const std::string child)
Definition: vpIoTools.cpp:1245
static void display(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:210
The vpDisplayOpenCV allows to display image using the opencv library.
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:212
void setArea(const double &area)
Definition: vpDot2.cpp:767
void setEllipsoidShapePrecision(const double &ellipsoidShapePrecision)
Definition: vpDot2.cpp:863
void setGrayLevelMin(const unsigned int &min)
Definition: vpDot2.h:331
void setWidth(const double &width)
Definition: vpDot2.cpp:738
void setSizePrecision(const double &sizePrecision)
Definition: vpDot2.cpp:818
void initTracking(const vpImage< unsigned char > &I, unsigned int size=0)
Definition: vpDot2.cpp:266
void setHeight(const double &height)
Definition: vpDot2.cpp:753
unsigned int getHeight() const
Definition: vpImage.h:152
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:93
static void read(vpImage< unsigned char > &I, const char *filename)
Definition: vpImageIo.cpp:278
unsigned int getGrayLevelMax() const
Definition: vpDot2.h:220
void setGraphics(const bool activate)
Definition: vpDot2.h:312
static const vpColor blue
Definition: vpColor.h:173