ViSP  2.9.0
trackDot.cpp
1 /****************************************************************************
2  *
3  * $Id: trackDot.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  * 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))
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/vpDot.h>
73 #include <visp/vpParseArgv.h>
74 #include <visp/vpIoTools.h>
75 
76 // List of allowed command line options
77 #define GETOPTARGS "cdf:i:n:p:s:h"
78 
79 void usage(const char *name, const char *badparam, std::string ipath, std::string ppath,
80  unsigned first, unsigned nimages, unsigned step);
81 bool getOptions(int argc, const char **argv, std::string &ipath, std::string &ppath, unsigned &first,
82  unsigned &nimages, unsigned &step, bool &click_allowed, bool &display);
83 
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.\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 
206 int
207 main(int argc, const char ** argv)
208 {
209  try {
210  std::string env_ipath;
211  std::string opt_ipath;
212  std::string ipath;
213  std::string opt_ppath;
214  std::string dirname;
215  std::string filename;
216  unsigned opt_first = 1;
217  unsigned opt_nimages = 500;
218  unsigned opt_step = 1;
219  bool opt_click_allowed = true;
220  bool opt_display = true;
221 
222  // Get the VISP_IMAGE_PATH environment variable value
223  char *ptenv = getenv("VISP_INPUT_IMAGE_PATH");
224  if (ptenv != NULL)
225  env_ipath = ptenv;
226 
227  // Set the default input path
228  if (! env_ipath.empty())
229  ipath = env_ipath;
230 
231  // Read the command line options
232  if (getOptions(argc, argv, opt_ipath, opt_ppath,opt_first, opt_nimages,
233  opt_step, opt_click_allowed, opt_display) == false) {
234  exit (-1);
235  }
236 
237  // Get the option values
238  if (!opt_ipath.empty())
239  ipath = opt_ipath;
240 
241  // Compare ipath and env_ipath. If they differ, we take into account
242  // the input path comming from the command line option
243  if (!opt_ipath.empty() && !env_ipath.empty() && opt_ppath.empty()) {
244  if (ipath != env_ipath) {
245  std::cout << std::endl
246  << "WARNING: " << std::endl;
247  std::cout << " Since -i <visp image path=" << ipath << "> "
248  << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
249  << " we skip the environment variable." << std::endl;
250  }
251  }
252 
253  // Test if an input path is set
254  if (opt_ipath.empty() && env_ipath.empty() && opt_ppath.empty() ){
255  usage(argv[0], NULL, ipath, opt_ppath, opt_first, opt_nimages, opt_step);
256  std::cerr << std::endl
257  << "ERROR:" << std::endl;
258  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH "
259  << std::endl
260  << " environment variable to specify the location of the " << std::endl
261  << " image path where test images are located." << std::endl
262  << " Use -p <personal image path> option if you want to "<<std::endl
263  << " use personal images." << std::endl
264  << std::endl;
265 
266  exit(-1);
267  }
268 
269  // Declare an image, this is a gray level image (unsigned char)
270  // it size is not defined yet, it will be defined when the image will
271  // read on the disk
273 
274  unsigned iter = opt_first;
275  std::ostringstream s;
276  char cfilename[FILENAME_MAX];
277 
278  if (opt_ppath.empty()){
279 
280 
281  // Warning :
282  // the image sequence is not provided with the ViSP package
283  // therefore the program will return you an error :
284  // !! vpImageIoPnm.cpp: readPGM(#210) :couldn't read file
285  // ViSP-images/mire-2/image.0001.pgm
286  // !! vpDotExample.cpp: main(#95) :Error while reading the image
287  // terminate called after throwing an instance of 'vpImageException'
288  //
289  // The sequence is available on the visp www site
290  // http://www.irisa.fr/lagadic/visp/visp.html
291  // in the download section. It is named "ViSP-images.tar.gz"
292 
293  // Set the path location of the image sequence
294  dirname = ipath + vpIoTools::path("/ViSP-images/mire-2/");
295 
296  // Build the name of the image file
297 
298  s.setf(std::ios::right, std::ios::adjustfield);
299  s << "image." << std::setw(4) << std::setfill('0') << iter << ".pgm";
300  filename = dirname + s.str();
301  }
302  else {
303 
304  sprintf(cfilename,opt_ppath.c_str(), iter) ;
305  filename = cfilename;
306  }
307 
308  // Read the PGM image named "filename" on the disk, and put the
309  // bitmap into the image structure I. I is initialized to the
310  // correct size
311  //
312  // exception readPGM may throw various exception if, for example,
313  // the file does not exist, or if the memory cannot be allocated
314  try{
315  vpCTRACE << "Load: " << filename << std::endl;
316 
317  vpImageIo::read(I, filename) ;
318  }
319  catch(...)
320  {
321  // an exception is throwned if an exception from readPGM has been catched
322  // here this will result in the end of the program
323  // Note that another error message has been printed from readPGM
324  // to give more information about the error
325  std::cerr << std::endl
326  << "ERROR:" << std::endl;
327  std::cerr << " Cannot read " << filename << std::endl;
328  std::cerr << " Check your -i " << ipath << " option " << std::endl
329  << " or VISP_INPUT_IMAGE_PATH environment variable."
330  << std::endl;
331  exit(-1);
332  }
333 
334  // We open a window using either X11, GTK or GDI.
335 #if defined VISP_HAVE_X11
336  vpDisplayX display;
337 #elif defined VISP_HAVE_GTK
338  vpDisplayGTK display;
339 #elif defined VISP_HAVE_GDI
340  vpDisplayGDI display;
341 #endif
342 
343  if (opt_display) {
344  // Display size is automatically defined by the image (I) size
345  display.init(I, 100, 100,"Display...") ;
346  // Display the image
347  // The image class has a member that specify a pointer toward
348  // the display that has been initialized in the display declaration
349  // therefore is is no longuer necessary to make a reference to the
350  // display variable.
351  vpDisplay::display(I) ;
352  vpDisplay::flush(I) ;
353  }
354 
355  // by using setGraphics, we request to see the all the pixel of the dot
356  vpDot d ;
357  if (opt_display) {
358  // by using setGraphics, we request to see the all the pixel of the dot
359  // in green on the screen.
360  // It uses the overlay image plane.
361  // The default of this setting is that it is time consumming
362  d.setGraphics(true) ;
363  }
364  else {
365  d.setGraphics(false) ;
366  }
367  // we also request to compute the dot moment m00, m10, m01, m11, m20, m02
368  d.setComputeMoments(true);
370 
371  if (opt_display && opt_click_allowed) {
372  // tracking is initalized
373  // if no other parameters are given to the iniTracking(..) method
374  // a right mouse click on the dot is expected
375  std::cout << "Click on a white dot you want to track..." << std::endl;
376  d.initTracking(I) ;
377  }
378  else {
379  // dot location can also be specified explicitely in the
380  // initTracking method : d.initTracking(I,ip) where ip is the
381  // image point from which the dot is searched
382  vpImagePoint ip;
383  ip.set_u( 160 );
384  ip.set_v( 212 );
385  d.initTracking(I, ip) ;
386  }
387 
388 
389 
390  vpImagePoint cog;
391  while (iter < opt_first + opt_nimages*opt_step) {
392  // set the new image name
393  if (opt_ppath.empty()){
394  s.str("");
395  s << "image." << std::setw(4) << std::setfill('0') << iter << ".pgm";
396  filename = dirname + s.str();
397  }
398  else {
399  sprintf(cfilename, opt_ppath.c_str(), iter) ;
400  filename = cfilename;
401  }
402  // read the image
403  std::cout << "read : " << filename << std::endl;
404  vpImageIo::read(I, filename);
405 
406  if (opt_display) {
407  // Display the image
408  vpDisplay::display(I) ;
409  }
410  std::cout << "Tracking on image: " << filename << std::endl;
411 
412  // track the dot
413  double time = vpTime::measureTimeMs();
414  d.track(I) ;
415 
416  std::cout << "COG (" << vpTime::measureTimeMs() - time << " ms): "
417  << std::endl;
418  cog = d.getCog();
419  std::cout << cog.get_u() << " " << cog.get_v()
420  << " - "
421  << d.m10 / d.m00 << " " << d.m01 / d.m00 << std::endl;
422  std::cout << "Size:" << std::endl;
423  std::cout << " w: " << d.getWidth() << " h: " << d.getHeight() << std::endl;
424  std::cout << "Moments:" << std::endl;
425  std::cout << " m00: " << d.m00 << std::endl;
426  std::cout << " m10: " << d.m10 << std::endl;
427  std::cout << " m01: " << d.m01 << std::endl;
428  std::cout << " m11: " << d.m11 << std::endl;
429  std::cout << " m02: " << d.m02 << std::endl;
430  std::cout << " m20: " << d.m20 << std::endl;
431  std::cout << "Centered moments:" << std::endl;
432  std::cout << " mu11: " << d.mu11 << std::endl;
433  std::cout << " mu02: " << d.mu02 << std::endl;
434  std::cout << " mu20: " << d.mu20 << std::endl;
435 
436  if (0) {
437  std::list<vpImagePoint> edges = d.getEdges();
438  std::list<vpImagePoint>::const_iterator it;
439  for(it = edges.begin(); it != edges.end(); ++it) {
441  }
442  }
443 
444  if (opt_display) {
445  // display a red cross (size 10) in the image at the dot center
446  // of gravity location
448  // flush the X11 buffer
449  vpDisplay::flush(I) ;
450  }
451  iter ++;
452  }
453 
454 
455  if (opt_display && opt_click_allowed) {
456  std::cout << "\nA click to exit..." << std::endl;
457  // Wait for a blocking mouse click
459  }
460  return 0;
461  }
462  catch(vpException e) {
463  std::cout << "Catch an exception: " << e << std::endl;
464  return 1;
465  }
466 }
467 #else
468 int
469 main()
470 {
471  vpERROR_TRACE("You do not have X11, GTK or GDI display functionalities...");
472 }
473 
474 #endif
double get_v() const
Definition: vpImagePoint.h:263
double mu20
Definition: vpDot.h:182
void setConnexity(vpConnexityType type)
Definition: vpDot.h:327
unsigned int getHeight() const
Definition: vpDot.h:285
double m10
Definition: vpDot.h:143
#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:252
Define the X11 console to display images.
Definition: vpDisplayX.h:152
void track(const vpImage< unsigned char > &I)
Definition: vpDot.cpp:807
double m00
Definition: vpDot.h:129
error that can be emited by ViSP classes.
Definition: vpException.h:76
static std::string path(const char *pathname)
Definition: vpIoTools.cpp:715
double mu11
Definition: vpDot.h:177
static double measureTimeMs()
Definition: vpTime.cpp:86
double mu02
Definition: vpDot.h:187
static void flush(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:1994
double m20
Definition: vpDot.h:159
double m11
Definition: vpDot.h:150
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:79
static const vpColor red
Definition: vpColor.h:167
#define vpCTRACE
Definition: vpDebug.h:341
std::list< vpImagePoint > getEdges() const
Definition: vpDot.h:232
vpImagePoint getCog() const
Definition: vpDot.h:223
double m01
Definition: vpDot.h:136
void set_u(const double u)
Definition: vpImagePoint.h:216
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
void set_v(const double v)
Definition: vpImagePoint.h:227
unsigned int getWidth() const
Definition: vpDot.h:274
The vpDisplayGTK allows to display image using the GTK+ library version 1.2.
Definition: vpDisplayGTK.h:145
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const char *title=NULL)
double m02
Definition: vpDot.h:168
void setGraphics(const bool activate)
Definition: vpDot.h:350
This tracker is meant to track a dot (connected pixels with same gray level) on a vpImage...
Definition: vpDot.h:114
void setComputeMoments(const bool activate)
Definition: vpDot.h:322
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
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