ViSP  2.9.0
trackKltOpencv.cpp
1 /****************************************************************************
2  *
3  * $Id: trackKltOpencv.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  *****************************************************************************/
48 #include <visp/vpDebug.h>
49 #include <visp/vpConfig.h>
50 
51 #include <stdio.h>
52 #include <sstream>
53 #include <iomanip>
54 #include <vector>
55 
56 #if (defined (VISP_HAVE_X11) || defined(VISP_HAVE_GTK) || defined(VISP_HAVE_GDI))
57 
58 #if (defined (VISP_HAVE_OPENCV))
59 
60 #include <visp/vpKltOpencv.h>
61 #include <visp/vpImage.h>
62 #include <visp/vpImageIo.h>
63 #include <visp/vpDisplayX.h>
64 #include <visp/vpDisplayGTK.h>
65 #include <visp/vpDisplayGDI.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 void usage(const char *name, const char *badparam, std::string ipath, std::string ppath,
73  unsigned first, unsigned nimages, unsigned step);
74 bool getOptions(int argc, const char **argv, std::string &ipath, std::string &ppath, unsigned &first,
75  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 Example of KLT tracking using OpenCV library.\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 : \"/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_IMAGE_PATH environment variable value
222  char *ptenv = getenv("VISP_INPUT_IMAGE_PATH");
223  if (ptenv != NULL)
224  env_ipath = ptenv;
225 
226  // Set the default input path
227  if (! env_ipath.empty())
228  ipath = env_ipath;
229 
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
272  vpImage<unsigned char> vpI ; // This is a ViSP image used for display only
273  IplImage * cvI; // This is an OpenCV IPL image used by the tracker
274 
275  unsigned iter = opt_first;
276  std::ostringstream s;
277  char cfilename[FILENAME_MAX];
278 
279  if (opt_ppath.empty()){
280 
281 
282  // Warning :
283  // the image sequence is not provided with the ViSP package
284  // therefore the program will return you an error :
285  // !! vpImageIoPnm.cpp: readPGM(#210) :couldn't read file
286  // ViSP-images/mire-2/image.0001.pgm
287  // !! vpDotExample.cpp: main(#95) :Error while reading the image
288  // terminate called after throwing an instance of 'vpImageException'
289  //
290  // The sequence is available on the visp www site
291  // http://www.irisa.fr/lagadic/visp/visp.html
292  // in the download section. It is named "ViSP-images.tar.gz"
293 
294  // Set the path location of the image sequence
295  dirname = ipath + vpIoTools::path("/ViSP-images/mire-2/");
296 
297  // Build the name of the image file
298 
299  s.setf(std::ios::right, std::ios::adjustfield);
300  s << "image." << std::setw(4) << std::setfill('0') << iter << ".pgm";
301  filename = dirname + s.str();
302  }
303  else {
304 
305  sprintf(cfilename,opt_ppath.c_str(), iter) ;
306  filename = cfilename;
307  }
308 
309  // Read the PGM image named "filename" on the disk, and put the
310  // bitmap into the image structure I. I is initialized to the
311  // correct size
312  //
313  // exception readPGM may throw various exception if, for example,
314  // the file does not exist, or if the memory cannot be allocated
315  try{
316  vpCTRACE << "Load: " << filename << std::endl;
317 
318  // Load a ViSP image used for the display
319  vpImageIo::read(vpI, filename) ;
320  // Load an OpenCV IPL image used by the tracker
321  if((cvI = cvLoadImage(filename.c_str(), CV_LOAD_IMAGE_GRAYSCALE))== NULL) {
322  printf("Cannot read image: %s\n", filename.c_str());
323  return (0);
324  }
325  }
326  catch(...)
327  {
328  // an exception is throwned if an exception from readPGM has been catched
329  // here this will result in the end of the program
330  // Note that another error message has been printed from readPGM
331  // to give more information about the error
332  std::cerr << std::endl
333  << "ERROR:" << std::endl;
334  std::cerr << " Cannot read " << filename << std::endl;
335  std::cerr << " Check your -i " << ipath << " option " << std::endl
336  << " or VISP_INPUT_IMAGE_PATH environment variable."
337  << std::endl;
338  exit(-1);
339  }
340 
341  // We open a window using either X11, GTK or GDI.
342 #if defined VISP_HAVE_X11
343  vpDisplayX display;
344 #elif defined VISP_HAVE_GTK
345  vpDisplayGTK display;
346 #elif defined VISP_HAVE_GDI
347  vpDisplayGDI display;
348 #endif
349 
350  if (opt_display) {
351  // Display size is automatically defined by the image (I) size
352  display.init(vpI, 100, 100,"Display...") ;
353  // Display the image
354  // The image class has a member that specify a pointer toward
355  // the display that has been initialized in the display declaration
356  // therefore is is no longuer necessary to make a reference to the
357  // display variable.
358  vpDisplay::display(vpI) ;
359  vpDisplay::flush(vpI) ;
360  }
361 
362  // KLT tracker
363  vpKltOpencv tracker;
364 
365  // Event manager
366  //tracker.setOnNewFeature(&newFeature);
367  //tracker.setOnFeatureLost(&lostFeature);
368  //tracker.setIsFeatureValid(&isValid);
369 
370  // Tracker parameters
371  tracker.setTrackerId(1);
372  //tracker.setOnMeasureFeature(&modifyFeature);
373  tracker.setMaxFeatures(200);
374  tracker.setWindowSize(10);
375  tracker.setQuality(0.01);
376  tracker.setMinDistance(15);
377  tracker.setHarrisFreeParameter(0.04);
378  tracker.setBlockSize(9);
379  tracker.setUseHarris(1);
380  tracker.setPyramidLevels(3);
381 
382  // Point detection using Harris. In input we have an OpenCV IPL image
383  tracker.initTracking(cvI);
384 
385  if (opt_display) {
386  // Plot the Harris points on ViSP image
387  tracker.display(vpI, vpColor::red);
388  }
389 
390  // tracking is now initialized. We can start the tracker.
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  // Load a ViSP image used for the display
405  vpImageIo::read(vpI, filename) ;
406  // Load an OpenCV IPL image used by the tracker
407  if((cvI = cvLoadImage(filename.c_str(), CV_LOAD_IMAGE_GRAYSCALE))
408  == NULL) {
409  printf("Cannot read image: %s\n", filename.c_str());
410  return (0);
411  }
412 
413  // track the dot and returns its coordinates in the image
414  // results are given in float since many many are usually considered
415  //
416  // an expcetion is thrown by the track method if
417  // - dot is lost
418 
419  if (opt_display) {
420  // Display the image
421  vpDisplay::display(vpI) ;
422  }
423 
424  std::cout << "Tracking on image: " << filename << std::endl;
425  double time = vpTime::measureTimeMs();
426  // Tracking of the detected points
427  tracker.track(cvI);
428  std::cout << "Tracking performed in " <<
429  vpTime::measureTimeMs() - time << " ms): " << std::endl;
430 
431  if (opt_display) {
432  // Display the tracked points
433  tracker.display(vpI, vpColor::red);
434 
435  vpDisplay::flush(vpI) ;
436  }
437  iter += opt_step;
438  }
439  if (opt_display && opt_click_allowed) {
440  std::cout << "\nA click to exit..." << std::endl;
441  // Wait for a blocking mouse click
442  vpDisplay::getClick(vpI) ;
443  }
444  return 0;
445  }
446  catch(vpException e) {
447  std::cout << "Catch an exception: " << e << std::endl;
448  return 1;
449  }
450 }
451 #else
452 int
453 main()
454 {
455  vpERROR_TRACE("You do not have OpenCV functionalities...");
456 }
457 #endif
458 #else
459 int
460 main()
461 {
462  vpERROR_TRACE("You do not have X11, GTK or GDI display functionalities...");
463 }
464 
465 #endif
void setQuality(double input)
Definition: vpKltOpencv.h:264
void track(const IplImage *I)
#define vpERROR_TRACE
Definition: vpDebug.h:395
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:132
void setUseHarris(const int input)
Definition: vpKltOpencv.h:273
Define the X11 console to display images.
Definition: vpDisplayX.h:152
void display(const vpImage< unsigned char > &I, vpColor color=vpColor::red, unsigned int thickness=1)
error that can be emited by ViSP classes.
Definition: vpException.h:76
static std::string path(const char *pathname)
Definition: vpIoTools.cpp:715
void setPyramidLevels(const int input)
Definition: vpKltOpencv.h:263
void setBlockSize(const int input)
Definition: vpKltOpencv.h:219
static double measureTimeMs()
Definition: vpTime.cpp:86
static void flush(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:1994
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
void setWindowSize(const int input)
Definition: vpKltOpencv.h:274
static void display(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:206
void setTrackerId(int tid)
Definition: vpKltOpencv.h:265
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)
void initTracking(const IplImage *I, const IplImage *mask=NULL)
Wrapper for the KLT (Kanade-Lucas-Tomasi) feature tracker implemented in OpenCV.
Definition: vpKltOpencv.h:103
virtual bool getClick(bool blocking=true)=0
void setMaxFeatures(const int input)
static void read(vpImage< unsigned char > &I, const char *filename)
Definition: vpImageIo.cpp:278
void setMinDistance(double input)
Definition: vpKltOpencv.h:243
void setHarrisFreeParameter(double input)
Definition: vpKltOpencv.h:227