ViSP  2.9.0
trackDot2WithAutoDetection.cpp
1 /****************************************************************************
2  *
3  * $Id: trackDot2WithAutoDetection.cpp 4658 2014-02-09 09:50:14Z 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))
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 
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_IMAGE_PATH environment variable value
266  char *ptenv = getenv("VISP_INPUT_IMAGE_PATH");
267  if (ptenv != NULL)
268  env_ipath = ptenv;
269 
270  // Set the default input path
271  if (! env_ipath.empty())
272  ipath = env_ipath;
273 
274 
275  // Read the command line options
276  if (getOptions(argc, argv, opt_ipath, opt_ppath,opt_first, opt_nimages,
277  opt_step,opt_sizePrecision,opt_grayLevelPrecision,
278  opt_ellipsoidShapePrecision, opt_click_allowed, opt_display) == false) {
279  exit (-1);
280  }
281 
282  // Get the option values
283  if (!opt_ipath.empty())
284  ipath = opt_ipath;
285 
286  // Compare ipath and env_ipath. If they differ, we take into account
287  // the input path comming from the command line option
288  if (!opt_ipath.empty() && !env_ipath.empty() && opt_ppath.empty()) {
289  if (ipath != env_ipath) {
290  std::cout << std::endl
291  << "WARNING: " << std::endl;
292  std::cout << " Since -i <visp image path=" << ipath << "> "
293  << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
294  << " we skip the environment variable." << std::endl;
295  }
296  }
297 
298  // Test if an input path is set
299  if (opt_ipath.empty() && env_ipath.empty()){
300  usage(argv[0], NULL, ipath, opt_ppath, opt_first, opt_nimages,
301  opt_step,opt_sizePrecision,opt_grayLevelPrecision, opt_ellipsoidShapePrecision);
302  std::cerr << std::endl
303  << "ERROR:" << std::endl;
304  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH "
305  << std::endl
306  << " environment variable to specify the location of the " << std::endl
307  << " image path where test images are located." << std::endl << std::endl
308  << " Use -p <personal image path> option if you want to "<<std::endl
309  << " use personal images." << std::endl;
310  exit(-1);
311  }
312 
313 
314  // Declare an image, this is a gray level image (unsigned char)
315  // it size is not defined yet, it will be defined when the image will
316  // read on the disk
318  std::ostringstream s;
319  char cfilename[FILENAME_MAX];
320  unsigned iter = opt_first; // Image number
321 
322  if (opt_ppath.empty()){
323 
324 
325  // Warning :
326  // the image sequence is not provided with the ViSP package
327  // therefore the program will return you an error :
328  // !! vpImageIoPnm.cpp: readPGM(#210) :couldn't read file
329  // ViSP-images/cube/image.0001.pgm
330  // !! vpDotExample.cpp: main(#95) :Error while reading the image
331  // terminate called after throwing an instance of 'vpImageException'
332  //
333  // The sequence is available on the visp www site
334  // http://www.irisa.fr/lagadic/visp/visp.html
335  // in the download section. It is named "ViSP-images.tar.gz"
336 
337  // Set the path location of the image sequence
338  dirname = ipath + vpIoTools::path("/ViSP-images/mire-2/");
339 
340  // Build the name of the image file
341 
342  s.setf(std::ios::right, std::ios::adjustfield);
343  s << "image." << std::setw(4) << std::setfill('0') << iter << ".pgm";
344  filename = dirname + s.str();
345  }
346  else {
347 
348  sprintf(cfilename,opt_ppath.c_str(), iter) ;
349  filename = cfilename;
350  }
351  // Read the PGM image named "filename" on the disk, and put the
352  // bitmap into the image structure I. I is initialized to the
353  // correct size
354  //
355  // exception readPGM may throw various exception if, for example,
356  // the file does not exist, or if the memory cannot be allocated
357  try{
358  vpCTRACE << "Load: " << filename << std::endl;
359 
360  vpImageIo::read(I, filename) ;
361  }
362  catch(...)
363  {
364  // an exception is throwned if an exception from readPGM has been catched
365  // here this will result in the end of the program
366  // Note that another error message has been printed from readPGM
367  // to give more information about the error
368  std::cerr << std::endl
369  << "ERROR:" << std::endl;
370  std::cerr << " Cannot read " << filename << std::endl;
371  std::cerr << " Check your -i " << ipath << " option " << std::endl
372  << " or your -p " << opt_ppath << " option " <<std::endl
373  << " or VISP_INPUT_IMAGE_PATH environment variable."
374  << std::endl;
375  exit(-1);
376  }
377 
378 
379  // We open a window using either GTK, X11 or GDI.
380 #if defined VISP_HAVE_GTK
381  vpDisplayGTK display;
382 #elif defined VISP_HAVE_X11
383  vpDisplayX display;
384 #elif defined VISP_HAVE_GDI
385  vpDisplayGDI display;
386 #endif
387 
388  if (opt_display) {
389  // Display size is automatically defined by the image (I) size
390  display.init(I, 100, 100,"Display...") ;
391  // Display the image
392  // The image class has a member that specify a pointer toward
393  // the display that has been initialized in the display declaration
394  // therefore is is no longuer necessary to make a reference to the
395  // display variable.
396  vpDisplay::display(I) ;
397  vpDisplay::flush(I) ;
398  }
399 
400  // Dot declaration
401  vpDot2 d ;
402 
403  d.setGraphics(true);
404  if (opt_click_allowed & opt_display) {
405  d.setGrayLevelPrecision(opt_grayLevelPrecision);
406 
407  std::cout << "Please click on a dot to initialize detection"
408  << std::endl;
409 
410  d.initTracking(I) ;
411  if (opt_display) {
412  vpImagePoint cog;
413  cog = d.getCog();
415  vpDisplay::flush(I) ;
416  }
417  d.setSizePrecision(opt_sizePrecision);
418  d.setEllipsoidShapePrecision(opt_ellipsoidShapePrecision);
419  printf("Dot characteristics: \n");
420  printf(" width : %lf\n", d.getWidth());
421  printf(" height: %lf\n", d.getHeight());
422  printf(" area: %lf\n", d.getArea());
423  printf(" gray level min: %d\n", d.getGrayLevelMin());
424  printf(" gray level max: %d\n", d.getGrayLevelMax());
425  printf(" grayLevelPrecision: %lf\n", d.getGrayLevelPrecision());
426  printf(" sizePrecision: %lf\n", d.getSizePrecision());
427  printf(" ellipsoidShapePrecision: %lf\n", d.getEllipsoidShapePrecision());
428  }
429  else{
430  // Set dot characteristics for the auto detection
431  d.setGraphics(true);
432  d.setWidth(15.0);
433  d.setHeight(12.0);
434  d.setArea(124);
435  d.setGrayLevelMin(164);
436  d.setGrayLevelMax(255);
437  d.setGrayLevelPrecision(opt_grayLevelPrecision);
438  d.setSizePrecision(opt_sizePrecision);
439  d.setEllipsoidShapePrecision(opt_ellipsoidShapePrecision);
440  }
441 
442  while (iter < opt_first + opt_nimages*opt_step)
443  {
444 
445  // set the new image name
446 
447  if (opt_ppath.empty()){
448 
449  s.str("");
450  s << "image." << std::setw(4) << std::setfill('0') << iter << ".pgm";
451  filename = dirname + s.str();
452  }
453  else {
454  sprintf(cfilename, opt_ppath.c_str(), iter) ;
455  filename = cfilename;
456  }
457  // read the image
458  vpImageIo::read(I, filename);
459 
460  if (opt_display) {
461  // Display the image
462  vpDisplay::display(I) ;
463  }
464 
465  std::cout << "Search dots in image" << filename << std::endl;
466  std::list<vpDot2> list_d;
467  d.searchDotsInArea(I, 0, 0, I.getWidth(), I.getHeight(), list_d) ;
468 
469  if( list_d.empty() ) {
470  std::cout << "Dot auto detection did not work." << std::endl;
471  return(-1) ;
472  }
473  else {
474  std::cout << std::endl << list_d.size() << " dots are detected" << std::endl;
475 
476  if (opt_display) {
477  int i=0;
478  // Parse all founded dots for display
479  for (std::list<vpDot2>::const_iterator it = list_d.begin(); it != list_d.end(); ++ it)
480  {
481  vpImagePoint cog = (*it).getCog();
482 
483  std::cout << "Dot " << i++ << " : " << cog.get_u()
484  << " " << cog.get_v() << std::endl;
485 
486  vpDisplay::displayCross(I, cog, 16, vpColor::blue, 3) ;
487  }
488  vpDisplay::flush(I);
489  }
490  }
491 
492  // If click is allowed, wait for a mouse click to launch the next iteration
493  if (opt_display && opt_click_allowed) {
494  std::cout << "\nA click to continue..." << std::endl;
495  // Wait for a blocking mouse click
497  }
498 
499  iter += opt_step ;
500  }
501  if (opt_display && opt_click_allowed) {
502  std::cout << "\nA click to exit..." << std::endl;
503  // Wait for a blocking mouse click
505  }
506 
507  return 0;
508  }
509  catch(vpException e) {
510  std::cout << "Catch an exception: " << e << std::endl;
511  return 1;
512  }
513 }
514 #else
515 int
516 main()
517 {
518  vpERROR_TRACE("You do not have X11, GTK or GDI display functionalities...");
519 }
520 
521 #endif
522 
523 
524 /*
525  * Local variables:
526  * c-basic-offset: 2
527  * End:
528  */
double getWidth() const
Definition: vpDot2.cpp:648
void setGrayLevelMax(const unsigned int &max)
Definition: vpDot2.h:347
double get_v() const
Definition: vpImagePoint.h:263
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
unsigned int getWidth() const
Definition: vpImage.h:159
#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:252
Define the X11 console to display images.
Definition: vpDisplayX.h:152
error that can be emited by ViSP classes.
Definition: vpException.h:76
static std::string path(const char *pathname)
Definition: vpIoTools.cpp:715
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:1994
double getSizePrecision() const
Definition: vpDot2.cpp:688
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:79
#define vpCTRACE
Definition: vpDebug.h:341
vpImagePoint getCog() const
Definition: vpDot2.h:163
void setGrayLevelPrecision(const double &grayLevelPrecision)
Definition: vpDot2.cpp:788
static void display(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:206
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 init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const char *title=NULL)
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: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: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