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