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