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