ViSP
trackDot2.cpp
1 /****************************************************************************
2  *
3  * $Id: trackDot2.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  * Example of dot tracking.
36  *
37  * Authors:
38  * Eric Marchand
39  * Fabien Spindler
40  *
41  *****************************************************************************/
48 #include <visp/vpDebug.h>
49 #include <visp/vpConfig.h>
50 
51 #include <stdlib.h>
52 #include <stdio.h>
53 #include <sstream>
54 #include <iomanip>
55 
56 #if (defined (VISP_HAVE_X11) || defined(VISP_HAVE_GTK) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV))
57 
58 #include <visp/vpImage.h>
59 #include <visp/vpImageIo.h>
60 #include <visp/vpImagePoint.h>
61 #include <visp/vpDisplayX.h>
62 #include <visp/vpDisplayGTK.h>
63 #include <visp/vpDisplayGDI.h>
64 #include <visp/vpDisplayOpenCV.h>
65 #include <visp/vpDot2.h>
66 #include <visp/vpParseArgv.h>
67 #include <visp/vpIoTools.h>
68 
69 // List of allowed command line options
70 #define GETOPTARGS "cdf:i:n:p:s:h"
71 
72 //int gsl_warnings_off;
73 
74 void usage(const char *name, const char *badparam, std::string ipath, std::string ppath,
75  unsigned first, unsigned nimages, unsigned step);
76 bool getOptions(int argc, const char **argv, std::string &ipath, std::string &ppath, unsigned &first,
77  unsigned &nimages, unsigned &step, bool &click_allowed, bool &display);
97 void usage(const char *name, const char *badparam, std::string ipath, std::string ppath,
98  unsigned first, unsigned nimages, unsigned step)
99 {
100  fprintf(stdout, "\n\
101 Test dot tracking using vpDot2 class.\n\
102 \n\
103 SYNOPSIS\n\
104  %s [-i <test image path>] [-p <personal image path>]\n\
105  [-f <first image>] [-n <number of images>] [-s <step>]\n\
106  [-c] [-d] [-h]\n", name);
107 
108  fprintf(stdout, "\n\
109 OPTIONS: Default\n\
110  -i <input image path> %s\n\
111  Set image input path.\n\
112  From this path read images \n\
113  \"ViSP-images/mire-2/image.%%04d.pgm\". These \n\
114  images come from ViSP-images-x.y.z.tar.gz available \n\
115  on the ViSP website.\n\
116  Setting the VISP_INPUT_IMAGE_PATH environment\n\
117  variable produces the same behaviour than using\n\
118  this option.\n\
119  \n\
120  -p <personal image path> %s\n\
121  Specify a personal sequence containing images \n\
122  to process.\n\
123  By image sequence, we mean one file per image.\n\
124  The following image file formats PNM (PGM P5, PPM P6)\n\
125  are supported. The format is selected by analysing \n\
126  the filename extension.\n\
127  Example : \"C:/Temp/ViSP-images/cube/image.%%04d.pgm\"\n\
128  %%04d is for the image numbering.\n\
129  \n\
130  -f <first image> %u\n\
131  First image number of the sequence.\n\
132  \n\
133  -n <number of images> %u\n\
134  Number of images to load from the sequence.\n\
135  \n\
136  -s <step> %u\n\
137  Step between two images.\n\
138 \n\
139  -c\n\
140  Disable the mouse click. Useful to automaze the \n\
141  execution of this program without humain intervention.\n\
142 \n\
143  -d \n\
144  Turn off the display.\n\
145 \n\
146  -h\n\
147  Print the help.\n",
148  ipath.c_str(), ppath.c_str(), first, nimages, step);
149 
150  if (badparam)
151  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
152 }
170 bool getOptions(int argc, const char **argv, std::string &ipath, std::string &ppath, unsigned &first,
171  unsigned &nimages, unsigned &step, bool &click_allowed, bool &display)
172 {
173  const char *optarg_;
174  int c;
175  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
176 
177  switch (c) {
178  case 'c': click_allowed = false; break;
179  case 'd': display = false; break;
180  case 'i': ipath = optarg_; break;
181  case 'p': ppath = optarg_; break;
182  case 'f': first = (unsigned) atoi(optarg_); break;
183  case 'n': nimages = (unsigned) atoi(optarg_); break;
184  case 's': step = (unsigned) atoi(optarg_); break;
185  case 'h': usage(argv[0], NULL, ipath, ppath, first, nimages, step);
186  return false; break;
187 
188  default:
189  usage(argv[0], optarg_, ipath, ppath, first, nimages, step);
190  return false; break;
191  }
192  }
193 
194  if ((c == 1) || (c == -1)) {
195  // standalone param or error
196  usage(argv[0], NULL, ipath, ppath, first, nimages, step);
197  std::cerr << "ERROR: " << std::endl;
198  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
199  return false;
200  }
201 
202  return true;
203 }
204 
205 int
206 main(int argc, const char ** argv)
207 {
208  try {
209  std::string env_ipath;
210  std::string opt_ipath;
211  std::string ipath;
212  std::string opt_ppath;
213  std::string dirname;
214  std::string filename;
215  unsigned opt_first = 1;
216  unsigned opt_nimages = 500;
217  unsigned opt_step = 1;
218  bool opt_click_allowed = true;
219  bool opt_display = true;
220 
221  // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH environment variable value
222  env_ipath = vpIoTools::getViSPImagesDataPath();
223 
224  // Set the default input path
225  if (! env_ipath.empty())
226  ipath = env_ipath;
227 
228  // Read the command line options
229  if (getOptions(argc, argv, opt_ipath, opt_ppath,opt_first, opt_nimages,
230  opt_step, opt_click_allowed, opt_display) == false) {
231  exit (-1);
232  }
233 
234  // Get the option values
235  if (!opt_ipath.empty())
236  ipath = opt_ipath;
237 
238  // Compare ipath and env_ipath. If they differ, we take into account
239  // the input path comming from the command line option
240  if (!opt_ipath.empty() && !env_ipath.empty() && opt_ppath.empty()) {
241  if (ipath != env_ipath) {
242  std::cout << std::endl
243  << "WARNING: " << std::endl;
244  std::cout << " Since -i <visp image path=" << ipath << "> "
245  << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
246  << " we skip the environment variable." << std::endl;
247  }
248  }
249 
250  // Test if an input path is set
251  if (opt_ipath.empty() && env_ipath.empty() && opt_ppath.empty() ){
252  usage(argv[0], NULL, ipath, opt_ppath, opt_first, opt_nimages, opt_step);
253  std::cerr << std::endl
254  << "ERROR:" << std::endl;
255  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH "
256  << std::endl
257  << " environment variable to specify the location of the " << std::endl
258  << " image path where test images are located." << std::endl
259  << " Use -p <personal image path> option if you want to "<<std::endl
260  << " use personal images." << std::endl
261  << std::endl;
262 
263  exit(-1);
264  }
265 
266  // Declare an image, this is a gray level image (unsigned char)
267  // it size is not defined yet, it will be defined when the image will
268  // read on the disk
270 
271  unsigned iter = opt_first;
272  std::ostringstream s;
273  char cfilename[FILENAME_MAX];
274 
275  if (opt_ppath.empty()){
276 
277 
278  // Warning :
279  // the image sequence is not provided with the ViSP package
280  // therefore the program will return you an error :
281  // !! vpImageIoPnm.cpp: readPGM(#210) :couldn't read file
282  // ViSP-images/mire-2/image.0001.pgm
283  // !! vpDotExample.cpp: main(#95) :Error while reading the image
284  // terminate called after throwing an instance of 'vpImageException'
285  //
286  // The sequence is available on the visp www site
287  // http://www.irisa.fr/lagadic/visp/visp.html
288  // in the download section. It is named "ViSP-images.tar.gz"
289 
290  // Set the path location of the image sequence
291  dirname = vpIoTools::createFilePath(ipath, "ViSP-images/mire-2");
292 
293  // Build the name of the image file
294 
295  s.setf(std::ios::right, std::ios::adjustfield);
296  s << "image." << std::setw(4) << std::setfill('0') << iter << ".pgm";
297  filename = vpIoTools::createFilePath(dirname, s.str());
298  }
299  else {
300 
301  sprintf(cfilename,opt_ppath.c_str(), iter) ;
302  filename = cfilename;
303  }
304 
305  // Read the PGM image named "filename" on the disk, and put the
306  // bitmap into the image structure I. I is initialized to the
307  // correct size
308  //
309  // exception readPGM may throw various exception if, for example,
310  // the file does not exist, or if the memory cannot be allocated
311  try{
312  vpCTRACE << "Load: " << filename << std::endl;
313 
314  vpImageIo::read(I, filename) ;
315  }
316  catch(...)
317  {
318  // an exception is throwned if an exception from readPGM has been catched
319  // here this will result in the end of the program
320  // Note that another error message has been printed from readPGM
321  // to give more information about the error
322  std::cerr << std::endl
323  << "ERROR:" << std::endl;
324  std::cerr << " Cannot read " << filename << std::endl;
325  std::cerr << " Check your -i " << ipath << " option " << std::endl
326  << " or VISP_INPUT_IMAGE_PATH environment variable."
327  << std::endl;
328  exit(-1);
329  }
330 
331  // We open a window using either X11, GTK or GDI.
332 #if defined VISP_HAVE_X11
333  vpDisplayX display;
334 #elif defined VISP_HAVE_GTK
335  vpDisplayGTK display;
336 #elif defined VISP_HAVE_GDI
337  vpDisplayGDI display;
338 #elif defined VISP_HAVE_OPENCV
339  vpDisplayOpenCV display;
340 #endif
341 
342  if (opt_display) {
343  // Display size is automatically defined by the image (I) size
344  display.init(I, 100, 100,"Display...") ;
345  // Display the image
346  // The image class has a member that specify a pointer toward
347  // the display that has been initialized in the display declaration
348  // therefore is is no longuer necessary to make a reference to the
349  // display variable.
350  vpDisplay::display(I) ;
351  vpDisplay::flush(I) ;
352  }
353  // define the vpDot structure.
354 
355  // vpDot and vpDot2 correspond to two different algorithms designed to track
356  // a dot. vpDot is based on recurse connex componants (all the pixels of the
357  // dot are parsed), while vpDot2 is based on freeman chain code (only the
358  // contour of the dot is parsed)
359 
360  vpDot2 d ;
361  vpImagePoint cog;
362 
363  if (opt_display) {
364  // by using setGraphics, we request to see the all the pixel of the dot
365  // in green on the screen.
366  // It uses the overlay image plane.
367  // The default of this setting is that it is time consumming
368 
369  d.setGraphics(true) ;
370  }
371  else {
372 
373  d.setGraphics(false) ;
374  }
375  // We want to track an ellipsoid shape. If you want to track a non ellipsoid
376  // object, use d.setEllipsoidShape(0);
377  // we also request to compute the dot moment m00, m10, m01, m11, m20, m02
378  d.setComputeMoments(true);
379  d.setGrayLevelPrecision(0.90);
380 
381  // tracking is initalized if no other parameters are given to the
382  // iniTracking(..) method a right mouse click on the dot is expected
383  // dot location can also be specified explicitely in the
384  // initTracking method : d.initTracking(I,ip) where ip is the image
385  // point from which the dot is searched
386 
387  if (opt_display && opt_click_allowed) {
388  std::cout << "Click on a dot to track it."<< std::endl;
389  d.initTracking(I) ;
390  }
391  else {
392  vpImagePoint ip;
393  ip.set_u( 160 );
394  ip.set_v( 212 );
395  d.initTracking(I, ip) ;
396  }
397  if (1) {
398  std::cout << "COG: " << std::endl;
399  cog = d.getCog();
400  std::cout << " u: " << cog.get_u() << " v: " << cog.get_v()
401  << " - "
402  << d.m10 / d.m00 << " " << d.m01 / d.m00 << std::endl;
403  std::cout << "Size:" << std::endl;
404  std::cout << " w: " << d.getWidth() << " h: " << d.getHeight() << std::endl;
405  std::cout << "Area: " << d.getArea() << std::endl;
406  std::cout << "Moments:" << std::endl;
407  std::cout << " m00: " << d.m00 << std::endl;
408  std::cout << " m10: " << d.m10 << std::endl;
409  std::cout << " m01: " << d.m01 << std::endl;
410  std::cout << " m11: " << d.m11 << std::endl;
411  std::cout << " m02: " << d.m02 << std::endl;
412  std::cout << " m20: " << d.m20 << std::endl;
413  std::cout << "Centered moments:" << std::endl;
414  std::cout << " mu11: " << d.mu11 << std::endl;
415  std::cout << " mu02: " << d.mu02 << std::endl;
416  std::cout << " mu20: " << d.mu20 << std::endl;
417  std::cout << "Settings:" << std::endl;
418  std::cout << " gray level min: " << d.getGrayLevelMin() << std::endl;
419  std::cout << " gray level max: " << d.getGrayLevelMax() << std::endl;
420  std::cout << " size precision: " << d.getSizePrecision() << std::endl;
421  std::cout << " gray level precision: " << d.getGrayLevelPrecision() << std::endl;
422  }
423 
424  while (iter < opt_first + opt_nimages*opt_step) {
425  // set the new image name
426  if (opt_ppath.empty()){
427  s.str("");
428  s << "image." << std::setw(4) << std::setfill('0') << iter << ".pgm";
429  filename = vpIoTools::createFilePath(dirname, s.str());
430  }
431  else {
432  sprintf(cfilename, opt_ppath.c_str(), iter) ;
433  filename = cfilename;
434  }
435  // read the image
436  std::cout << "read : " << filename << std::endl;
437  vpImageIo::read(I, filename);
438 
439  // track the dot and returns its coordinates in the image
440  // results are given in float since many many are usually considered
441  //
442  // an expcetion is thrown by the track method if
443  // - dot is lost
444 
445  if (opt_display) {
446  // Display the image
447  vpDisplay::display(I) ;
448  }
449 
450  std::cout << "Tracking on image: " << filename << std::endl;
451  double time = vpTime::measureTimeMs();
452  d.track(I) ;
453 
454  std::cout << "COG (" << vpTime::measureTimeMs() - time << " ms): "
455  << std::endl;
456  cog = d.getCog();
457  std::cout << " u: " << cog.get_u() << " v: " << cog.get_v()
458  << " - "
459  << d.m10 / d.m00 << " " << d.m01 / d.m00 << std::endl;
460  std::cout << "Size:" << std::endl;
461  std::cout << " w: " << d.getWidth() << " h: " << d.getHeight() << std::endl;
462  std::cout << "Area: " << d.getArea() << std::endl;
463  std::cout << "Moments:" << std::endl;
464  std::cout << " m00: " << d.m00 << std::endl;
465  std::cout << " m10: " << d.m10 << std::endl;
466  std::cout << " m01: " << d.m01 << std::endl;
467  std::cout << " m11: " << d.m11 << std::endl;
468  std::cout << " m02: " << d.m02 << std::endl;
469  std::cout << " m20: " << d.m20 << std::endl;
470  std::cout << "Centered moments:" << std::endl;
471  std::cout << " mu11: " << d.mu11 << std::endl;
472  std::cout << " mu02: " << d.mu02 << std::endl;
473  std::cout << " mu20: " << d.mu20 << std::endl;
474  std::cout << "Settings:" << std::endl;
475  std::cout << " gray level min: " << d.getGrayLevelMin() << std::endl;
476  std::cout << " gray level max: " << d.getGrayLevelMax() << std::endl;
477  std::cout << " size precision: " << d.getSizePrecision() << std::endl;
478  std::cout << " gray level precision: " << d.getGrayLevelPrecision()
479  << std::endl;
480 
481  if (opt_display) {
482  if (0) {
483  std::list<vpImagePoint> edges;
484  d.getEdges(edges);
485  std::list<vpImagePoint>::const_iterator it;
486  for(it = edges.begin(); it != edges.end(); ++it) {
488  }
489  }
490 
491  // display a green cross (size 10) in the image at the dot center
492  // of gravity location
494  // flush the X11 buffer
495 
496  vpDisplay::flush(I) ;
497  }
498  iter ++;
499  }
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  return 0;
507  }
508  catch(vpException e) {
509  std::cout << "Catch an exception: " << e << std::endl;
510  return 1;
511  }
512 }
513 #else
514 int
515 main()
516 {
517  vpERROR_TRACE("You do not have X11, GTK, GDI or OpenCV display functionalities...");
518 }
519 
520 #endif
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const char *title=NULL)
double getWidth() const
Definition: vpDot2.cpp:648
double m02
Definition: vpDot2.h:414
double get_v() const
Definition: vpImagePoint.h:264
double mu02
Definition: vpDot2.h:433
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1071
#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 m11
Definition: vpDot2.h:398
double getHeight() const
Definition: vpDot2.cpp:658
static double measureTimeMs()
Definition: vpTime.cpp:86
double getArea() const
Definition: vpDot2.cpp:668
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
double m01
Definition: vpDot2.h:390
void track(const vpImage< unsigned char > &I)
Definition: vpDot2.cpp:465
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
double mu11
Definition: vpDot2.h:423
void set_u(const double u)
Definition: vpImagePoint.h:217
double m20
Definition: vpDot2.h:405
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
void set_v(const double v)
Definition: vpImagePoint.h:228
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 setComputeMoments(const bool activate)
Definition: vpDot2.h:274
void initTracking(const vpImage< unsigned char > &I, unsigned int size=0)
Definition: vpDot2.cpp:266
double m10
Definition: vpDot2.h:382
double mu20
Definition: vpDot2.h:428
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
double m00
Definition: vpDot2.h:374
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
virtual void displayPoint(const vpImagePoint &ip, const vpColor &color)=0
void getEdges(std::list< vpImagePoint > &edges_list) const
Definition: vpDot2.h:177
static const vpColor blue
Definition: vpColor.h:173