ViSP  2.10.0
templateTracker.cpp
1 /****************************************************************************
2  *
3  * $Id: templateTracker.cpp 5002 2014-11-24 08:18: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  * Description:
34  * Example of template tracking.
35  *
36  * Authors:
37  * Amaury Dame
38  * Aurelien Yol
39  * Fabien Spindler
40  *
41  *****************************************************************************/
42 
49 #include <visp/vpConfig.h>
50 #include <visp/vpDebug.h>
51 #include <visp/vpDisplayD3D.h>
52 #include <visp/vpDisplayGTK.h>
53 #include <visp/vpDisplayGDI.h>
54 #include <visp/vpDisplayOpenCV.h>
55 #include <visp/vpDisplayX.h>
56 #include <visp/vpHomogeneousMatrix.h>
57 #include <visp/vpImageIo.h>
58 #include <visp/vpIoTools.h>
59 #include <visp/vpMath.h>
60 #include <visp/vpVideoReader.h>
61 #include <visp/vpParseArgv.h>
62 
63 #include <visp/vpTemplateTrackerSSD.h>
64 #include <visp/vpTemplateTrackerSSDForwardAdditional.h>
65 #include <visp/vpTemplateTrackerSSDForwardCompositional.h>
66 #include <visp/vpTemplateTrackerSSDInverseCompositional.h>
67 #include <visp/vpTemplateTrackerSSDESM.h>
68 #include <visp/vpTemplateTrackerZNCCForwardAdditional.h>
69 #include <visp/vpTemplateTrackerZNCCInverseCompositional.h>
70 
71 #include <visp/vpTemplateTrackerWarpAffine.h>
72 #include <visp/vpTemplateTrackerWarpHomography.h>
73 #include <visp/vpTemplateTrackerWarpHomographySL3.h>
74 #include <visp/vpTemplateTrackerWarpSRT.h>
75 #include <visp/vpTemplateTrackerWarpTranslation.h>
76 
77 #if defined (VISP_HAVE_DISPLAY)
78 
79 
80 #define GETOPTARGS "cdhi:l:pt:w:"
81 
82 #ifndef DOXYGEN_SHOULD_SKIP_THIS
83 typedef enum {
84  WARP_AFFINE,
85  WARP_HOMOGRAPHY,
86  WARP_HOMOGRAPHY_SL3,
87  WARP_SRT,
88  WARP_TRANSLATION
89 } WarpType;
90 
91 typedef enum {
92  TRACKER_SSD_ESM,
93  TRACKER_SSD_FORWARD_ADDITIONAL,
94  TRACKER_SSD_FORWARD_COMPOSITIONAL,
95  TRACKER_SSD_INVERSE_COMPOSITIONAL, // The most efficient
96  TRACKER_ZNCC_FORWARD_ADDITIONEL,
97  TRACKER_ZNCC_INVERSE_COMPOSITIONAL
98 } TrackerType;
99 
100 #endif
101 
102 void usage(const char *name, const char *badparam, const WarpType &warp_type,
103  TrackerType &tracker_type, const long &last_frame);
104 bool getOptions(int argc, const char **argv, std::string &ipath, bool &click_allowed, bool &display,
105  bool &pyramidal, WarpType &warp_type, TrackerType &tracker_type, long &last_frame);
106 
107 void usage(const char *name, const char *badparam, const WarpType &warp_type,
108  TrackerType &tracker_type, const long &last_frame)
109 {
110  fprintf(stdout, "\n\
111 Example of template tracking.\n\
112 \n\
113 SYNOPSIS\n\
114  %s [-i <test image path>] [-c] [-d] [-p] \n\
115  [-w <warp type>] [-t <tracker type>] \n\
116  [-l <last frame number>] [-h]\n", name );
117 
118  fprintf(stdout, "\n\
119 OPTIONS: Default\n\
120  -i <input image path> \n\
121  Set image input path.\n\
122  From this path read images \n\
123  \"ViSP-images/cube/image%%04d.pgm\". These \n\
124  images come from ViSP-images-x.y.z.tar.gz available \n\
125  on the ViSP website.\n\
126  Setting the VISP_INPUT_IMAGE_PATH environment\n\
127  variable produces the same behaviour than using\n\
128  this option.\n\
129  \n\
130  -l <last frame number> %ld\n\
131  Last frame number to consider.\n\
132  \n\
133  -d \n\
134  Turn off the display.\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  -w <warp type=[0,1,2,3,4]> %d\n\
141  Set the model used to warp the template. \n\
142  Authorized values are:\n\
143  %d : Affine\n\
144  %d : Homography\n\
145  %d : Homography in SL3\n\
146  %d : SRT (scale, rotation, translation)\n\
147  %d : Translation\n\
148  \n\
149  -t <tracker type=[0,1,2,3,4,5]> %d\n\
150  Set the tracker used to track the template. \n\
151  Authorized values are:\n\
152  %d : SSD ESM\n\
153  %d : SSD forward additional\n\
154  %d : SSD forward compositional\n\
155  %d : SSD inverse compositional\n\
156  %d : ZNCC forward additional\n\
157  %d : ZNCC inverse compositional\n\
158  \n\
159  -p\n\
160  Enable pyramidal tracking.\n\
161  \n\
162  -h \n\
163  Print the help.\n\n",
164  last_frame, (int)warp_type,
165  (int)WARP_AFFINE, (int)WARP_HOMOGRAPHY, (int)WARP_HOMOGRAPHY_SL3, (int)WARP_SRT, (int)WARP_TRANSLATION,
166  (int)tracker_type,
167  (int)TRACKER_SSD_ESM, (int)TRACKER_SSD_FORWARD_ADDITIONAL, (int)TRACKER_SSD_FORWARD_COMPOSITIONAL,
168  (int)TRACKER_SSD_INVERSE_COMPOSITIONAL, (int)TRACKER_ZNCC_FORWARD_ADDITIONEL,
169  (int)TRACKER_ZNCC_INVERSE_COMPOSITIONAL);
170  if (badparam)
171  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
172 }
173 
174 
175 bool getOptions(int argc, const char **argv, std::string &ipath, bool &click_allowed, bool &display,
176  bool &pyramidal, WarpType &warp_type, TrackerType &tracker_type, long &last_frame)
177 {
178  const char *optarg_;
179  int c;
180  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
181 
182  switch (c) {
183  case 'c': click_allowed = false; break;
184  case 'd': display = false; break;
185  case 'h': usage(argv[0], NULL, warp_type, tracker_type, last_frame); return false; break;
186  case 'i': ipath = optarg_; break;
187  case 'l': last_frame = (long)atoi(optarg_); break;
188  case 'p': pyramidal = true; break;
189  case 't': tracker_type = (TrackerType)atoi(optarg_); break;
190  case 'w': warp_type = (WarpType)atoi(optarg_); break;
191 
192  default:
193  usage(argv[0], optarg_, warp_type, tracker_type, last_frame);
194  return false; break;
195  }
196  }
197 
198  if (warp_type > WARP_TRANSLATION) {
199  usage(argv[0], NULL, warp_type, tracker_type, last_frame);
200  std::cerr << "ERROR: " << std::endl;
201  std::cerr << " Bad argument -w <warp type> with \"warp type\"=" << (int)warp_type << std::endl << std::endl;
202  return false;
203  }
204  if (tracker_type > TRACKER_ZNCC_INVERSE_COMPOSITIONAL) {
205  usage(argv[0], NULL, warp_type, tracker_type, last_frame);
206  std::cerr << "ERROR: " << std::endl;
207  std::cerr << " Bad argument -t <tracker type> with \"tracker type\"=" << (int)tracker_type << std::endl << std::endl;
208  return false;
209  }
210  if ((c == 1) || (c == -1)) {
211  // standalone param or error
212  usage(argv[0], NULL, warp_type, tracker_type, last_frame);
213  std::cerr << "ERROR: " << std::endl;
214  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
215  return false;
216  }
217 
218  return true;
219 }
220 
221 int
222 main(int argc, const char ** argv)
223 {
224  try {
225  std::string env_ipath;
226  std::string opt_ipath;
227  std::string ipath;
228  bool opt_click_allowed = true;
229  bool opt_display = true;
230  bool opt_pyramidal = false;
231  TrackerType opt_tracker_type = TRACKER_SSD_INVERSE_COMPOSITIONAL;
232  WarpType opt_warp_type = WARP_AFFINE;
233  long opt_last_frame = 30;
234 
235  // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH 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_click_allowed, opt_display, opt_pyramidal,
244  opt_warp_type, opt_tracker_type, opt_last_frame)) {
245  return (-1);
246  }
247 
248  // Test if an input path is set
249  if (opt_ipath.empty() && env_ipath.empty() ){
250  usage(argv[0], NULL, opt_warp_type, opt_tracker_type, opt_last_frame);
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  << std::endl;
258 
259  return (-1);
260  }
261 
262  // Get the option values
263  if (!opt_ipath.empty())
264  ipath = vpIoTools::createFilePath(opt_ipath, "ViSP-images/mire-2/image.%04d.pgm");
265  else
266  ipath = vpIoTools::createFilePath(env_ipath, "ViSP-images/mire-2/image.%04d.pgm");
267 
269  vpVideoReader reader;
270 
271  reader.setFileName(ipath.c_str());
272  reader.setFirstFrameIndex(1);
273  reader.setLastFrameIndex(opt_last_frame);
274  try{
275  reader.open(I);
276  }catch(...){
277  std::cout << "Cannot open sequence: " << ipath << std::endl;
278  return -1;
279  }
280  reader.acquire(I);
281 
282  vpDisplay *display = NULL;
283  if (opt_display)
284  {
285  // initialise a display
286 #if defined VISP_HAVE_X11
287  display = new vpDisplayX;
288 #elif defined VISP_HAVE_GDI
289  display = new vpDisplayGDI;
290 #elif defined VISP_HAVE_OPENCV
291  display = new vpDisplayOpenCV;
292 #elif defined VISP_HAVE_D3D9
293  display = new vpDisplayD3D;
294 #elif defined VISP_HAVE_GTK
295  display = new vpDisplayGTK;
296 #else
297  opt_display = false;
298 #endif
299 #if (defined VISP_HAVE_DISPLAY)
300  display->init(I, 100, 100, "Test tracking") ;
301 #endif
302  vpDisplay::display(I) ;
303  vpDisplay::flush(I);
304  }
305 
306  vpTemplateTrackerWarp *warp = NULL;
307  switch(opt_warp_type) {
308  case WARP_AFFINE: warp = new vpTemplateTrackerWarpAffine; break;
309  case WARP_HOMOGRAPHY: warp = new vpTemplateTrackerWarpHomography; break;
310  case WARP_HOMOGRAPHY_SL3: warp = new vpTemplateTrackerWarpHomographySL3; break;
311  case WARP_SRT: warp = new vpTemplateTrackerWarpSRT; break;
312  case WARP_TRANSLATION: warp = new vpTemplateTrackerWarpTranslation; break;
313  }
314 
315  vpTemplateTracker *tracker = NULL;
316  switch(opt_tracker_type) {
317  case TRACKER_SSD_ESM: tracker = new vpTemplateTrackerSSDESM(warp); break;
318  case TRACKER_SSD_FORWARD_ADDITIONAL: tracker = new vpTemplateTrackerSSDForwardAdditional(warp); break;
319  case TRACKER_SSD_FORWARD_COMPOSITIONAL: tracker = new vpTemplateTrackerSSDForwardCompositional(warp); break;
320  case TRACKER_SSD_INVERSE_COMPOSITIONAL: tracker = new vpTemplateTrackerSSDInverseCompositional(warp); break;
321  case TRACKER_ZNCC_FORWARD_ADDITIONEL: tracker = new vpTemplateTrackerZNCCForwardAdditional(warp); break;
322  case TRACKER_ZNCC_INVERSE_COMPOSITIONAL: tracker = new vpTemplateTrackerZNCCInverseCompositional(warp); break;
323  }
324 
325  tracker->setSampling(2,2);
326  tracker->setLambda(0.001);
327  tracker->setThresholdGradient(60.);
328  tracker->setIterationMax(800);
329  if (opt_pyramidal) {
330  tracker->setPyramidal(2, 1);
331  }
332  bool delaunay = false;
333  if (opt_display && opt_click_allowed)
334  tracker->initClick(I, delaunay);
335  else {
336  std::vector<vpImagePoint> v_ip;
337  vpImagePoint ip;
338  ip.set_ij(166, 54); v_ip.push_back(ip);
339  ip.set_ij(284, 55); v_ip.push_back(ip);
340  ip.set_ij(259, 284); v_ip.push_back(ip); // ends the first triangle
341  ip.set_ij(259, 284); v_ip.push_back(ip); // start the second triangle
342  ip.set_ij(149, 240); v_ip.push_back(ip);
343  ip.set_ij(167, 58); v_ip.push_back(ip);
344 
345  tracker->initFromPoints(I, v_ip, false);
346  }
347 
348  while (! reader.end())
349  {
350  std::cout << "Process image number " << reader.getFrameIndex() << std::endl;
351  // Acquire a new image
352  reader.acquire(I);
353  // Display the image
355  // Track the template
356  tracker->track(I);
357 
358  // Simulate a re-init
359  if (reader.getFrameIndex() == 10){
360  std::cout << "re-init simulation" << std::endl;
361  if (opt_click_allowed)
363 
364  tracker->resetTracker();
365 
366  if (opt_display && opt_click_allowed) {
367  vpDisplay::displayText(I, 10, 10, "Re-init simulation", vpColor::red);
368  vpDisplay::flush(I);
369  tracker->initClick(I, delaunay);
370  }
371  else {
372  std::vector<vpImagePoint> v_ip;
373  vpImagePoint ip;
374  ip.set_ij(146, 60); v_ip.push_back(ip);
375  ip.set_ij(254, 74); v_ip.push_back(ip);
376  ip.set_ij(228, 288); v_ip.push_back(ip); // ends the first triangle
377  ip.set_ij(228, 288); v_ip.push_back(ip); // start the second triangle
378  ip.set_ij(126, 242); v_ip.push_back(ip);
379  ip.set_ij(146, 60); v_ip.push_back(ip);
380 
381  tracker->initFromPoints(I, v_ip, false);
382  }
383  }
384 
385  // Display the template
386 #if 1
387  tracker->display(I, vpColor::red, 3);
388 #else
389  vpTemplateTrackerZone zoneWarped_, zoneRef_ = tracker->getZoneRef();
390  vpTemplateTrackerWarp *warp_ = tracker->getWarp();
391  vpColVector p_= tracker->getp();
392  warp_->warpZone(zoneRef_, p_, zoneWarped_);
393  zoneWarped_.display(I, vpColor::red, 3);
394  zoneRef_.display(I, vpColor::green, 3);
395 #endif
396 
397  vpDisplay::flush(I) ;
398  }
399  if (opt_click_allowed) {
400  vpDisplay::displayText(I, 10,10, "A click to exit...", vpColor::red);
401  vpDisplay::flush(I) ;
403  }
404  reader.close();
405  if (display)
406  delete display;
407 
408  delete warp;
409  delete tracker;
410 
411  return 0;
412  }
413  catch(vpException e)
414  {
415  std::cout << "Catch an exception: " << e << std::endl;
416  return -1;
417  }
418 }
419 
420 #else
421 
422 int main()
423 {
424  std::cout << "No display is available." << std::endl;
425  return 0;
426 }
427 
428 #endif
long getFrameIndex() const
void setSampling(int sample_i, int sample_j)
virtual void init(vpImage< unsigned char > &I, int x=-1, int y=-1, const char *title=NULL)=0
Class that defines generic functionnalities for display.
Definition: vpDisplay.h:174
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1071
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:132
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
Definition: vpDisplay.cpp:887
Define the X11 console to display images.
Definition: vpDisplayX.h:152
Class that enables to manipulate easily a video file or a sequence of images. As it inherits from the...
error that can be emited by ViSP classes.
Definition: vpException.h:76
void display(const vpImage< unsigned char > &I, const vpColor &col=vpColor::green, const unsigned int thickness=3)
void setIterationMax(const unsigned int &n)
static const vpColor green
Definition: vpColor.h:170
static void flush(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:2232
vpColVector getp() const
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:80
static const vpColor red
Definition: vpColor.h:167
void open(vpImage< vpRGBa > &I)
Display for windows using Direct3D.
Definition: vpDisplayD3D.h:109
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.
void initClick(const vpImage< unsigned char > &I, bool delaunay=false)
The vpDisplayGTK allows to display image using the GTK+ library version 1.2.
Definition: vpDisplayGTK.h:145
void acquire(vpImage< vpRGBa > &I)
void setFileName(const char *filename)
void initFromPoints(const vpImage< unsigned char > &I, const std::vector< vpImagePoint > &v_ip, bool delaunay=false)
void warpZone(const vpTemplateTrackerZone &in, const vpColVector &p, vpTemplateTrackerZone &out)
void setLastFrameIndex(const long last_frame)
Class that provides a data structure for the column vectors as well as a set of operations on these v...
Definition: vpColVector.h:72
void setLambda(double l)
void track(const vpImage< unsigned char > &I)
vpTemplateTrackerZone getZoneRef() const
void setFirstFrameIndex(const long first_frame)
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
void set_ij(const double ii, const double jj)
Definition: vpImagePoint.h:181
void setPyramidal(unsigned int nlevels=2, unsigned int level_to_stop=1)
vpTemplateTrackerWarp * getWarp() const
void setThresholdGradient(double threshold)
void display(const vpImage< unsigned char > &I, const vpColor &col=vpColor::green, const unsigned int thickness=3)