ViSP  2.9.0
templateTracker.cpp
1 /****************************************************************************
2  *
3  * $Id: templateTracker.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  * 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_IMAGE_PATH environment variable value
236  char *ptenv = getenv("VISP_INPUT_IMAGE_PATH");
237  if (ptenv != NULL)
238  env_ipath = ptenv;
239 
240  // Set the default input path
241  if (! env_ipath.empty())
242  ipath = env_ipath;
243 
244  // Read the command line options
245  if (!getOptions(argc, argv, opt_ipath, opt_click_allowed, opt_display, opt_pyramidal,
246  opt_warp_type, opt_tracker_type, opt_last_frame)) {
247  return (-1);
248  }
249 
250  // Test if an input path is set
251  if (opt_ipath.empty() && env_ipath.empty() ){
252  usage(argv[0], NULL, opt_warp_type, opt_tracker_type, opt_last_frame);
253  std::cerr << std::endl
254  << "ERROR:" << std::endl;
255  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH "
256  << std::endl
257  << " environment variable to specify the location of the " << std::endl
258  << " image path where test images are located." << std::endl
259  << std::endl;
260 
261  return (-1);
262  }
263 
264  // Get the option values
265  if (!opt_ipath.empty())
266  ipath = opt_ipath + vpIoTools::path("/ViSP-images/mire-2/image.%04d.pgm");
267  else
268  ipath = env_ipath + vpIoTools::path("/ViSP-images/mire-2/image.%04d.pgm");
269 
271  vpVideoReader reader;
272 
273  reader.setFileName(ipath.c_str());
274  reader.setFirstFrameIndex(1);
275  reader.setLastFrameIndex(opt_last_frame);
276  try{
277  reader.open(I);
278  }catch(...){
279  std::cout << "Cannot open sequence: " << ipath << std::endl;
280  return -1;
281  }
282  reader.acquire(I);
283 
284  vpDisplay *display = NULL;
285  if (opt_display)
286  {
287  // initialise a display
288 #if defined VISP_HAVE_X11
289  display = new vpDisplayX;
290 #elif defined VISP_HAVE_GDI
291  display = new vpDisplayGDI;
292 #elif defined VISP_HAVE_OPENCV
293  display = new vpDisplayOpenCV;
294 #elif defined VISP_HAVE_D3D9
295  display = new vpDisplayD3D;
296 #elif defined VISP_HAVE_GTK
297  display = new vpDisplayGTK;
298 #else
299  opt_display = false;
300 #endif
301 #if (defined VISP_HAVE_DISPLAY)
302  display->init(I, 100, 100, "Test tracking") ;
303 #endif
304  vpDisplay::display(I) ;
305  vpDisplay::flush(I);
306  }
307 
308  vpTemplateTrackerWarp *warp = NULL;
309  switch(opt_warp_type) {
310  case WARP_AFFINE: warp = new vpTemplateTrackerWarpAffine; break;
311  case WARP_HOMOGRAPHY: warp = new vpTemplateTrackerWarpHomography; break;
312  case WARP_HOMOGRAPHY_SL3: warp = new vpTemplateTrackerWarpHomographySL3; break;
313  case WARP_SRT: warp = new vpTemplateTrackerWarpSRT; break;
314  case WARP_TRANSLATION: warp = new vpTemplateTrackerWarpTranslation; break;
315  }
316 
317  vpTemplateTracker *tracker = NULL;
318  switch(opt_tracker_type) {
319  case TRACKER_SSD_ESM: tracker = new vpTemplateTrackerSSDESM(warp); break;
320  case TRACKER_SSD_FORWARD_ADDITIONAL: tracker = new vpTemplateTrackerSSDForwardAdditional(warp); break;
321  case TRACKER_SSD_FORWARD_COMPOSITIONAL: tracker = new vpTemplateTrackerSSDForwardCompositional(warp); break;
322  case TRACKER_SSD_INVERSE_COMPOSITIONAL: tracker = new vpTemplateTrackerSSDInverseCompositional(warp); break;
323  case TRACKER_ZNCC_FORWARD_ADDITIONEL: tracker = new vpTemplateTrackerZNCCForwardAdditional(warp); break;
324  case TRACKER_ZNCC_INVERSE_COMPOSITIONAL: tracker = new vpTemplateTrackerZNCCInverseCompositional(warp); break;
325  }
326 
327  tracker->setSampling(2,2);
328  tracker->setLambda(0.001);
329  tracker->setThresholdGradient(60.);
330  tracker->setIterationMax(800);
331  if (opt_pyramidal) {
332  tracker->setPyramidal(2, 1);
333  }
334  bool delaunay = false;
335  if (opt_display && opt_click_allowed)
336  tracker->initClick(I, delaunay);
337  else {
338  std::vector<vpImagePoint> v_ip;
339  vpImagePoint ip;
340  ip.set_ij(166, 54); v_ip.push_back(ip);
341  ip.set_ij(284, 55); v_ip.push_back(ip);
342  ip.set_ij(259, 284); v_ip.push_back(ip); // ends the first triangle
343  ip.set_ij(259, 284); v_ip.push_back(ip); // start the second triangle
344  ip.set_ij(149, 240); v_ip.push_back(ip);
345  ip.set_ij(167, 58); v_ip.push_back(ip);
346 
347  tracker->initFromPoints(I, v_ip, false);
348  }
349 
350  while (! reader.end())
351  {
352  std::cout << "Process image number " << reader.getFrameIndex() << std::endl;
353  // Acquire a new image
354  reader.acquire(I);
355  // Display the image
357  // Track the template
358  tracker->track(I);
359 
360  // Simulate a re-init
361  if (reader.getFrameIndex() == 10){
362  std::cout << "re-init simulation" << std::endl;
363  if (opt_click_allowed)
365 
366  tracker->resetTracker();
367 
368  if (opt_display && opt_click_allowed) {
369  vpDisplay::displayCharString(I, 10, 10, "Re-init simulation", vpColor::red);
370  vpDisplay::flush(I);
371  tracker->initClick(I, delaunay);
372  }
373  else {
374  std::vector<vpImagePoint> v_ip;
375  vpImagePoint ip;
376  ip.set_ij(146, 60); v_ip.push_back(ip);
377  ip.set_ij(254, 74); v_ip.push_back(ip);
378  ip.set_ij(228, 288); v_ip.push_back(ip); // ends the first triangle
379  ip.set_ij(228, 288); v_ip.push_back(ip); // start the second triangle
380  ip.set_ij(126, 242); v_ip.push_back(ip);
381  ip.set_ij(146, 60); v_ip.push_back(ip);
382 
383  tracker->initFromPoints(I, v_ip, false);
384  }
385  }
386 
387  // Display the template
388 #if 1
389  tracker->display(I, vpColor::red, 3);
390 #else
391  vpTemplateTrackerZone zoneWarped_, zoneRef_ = tracker->getZoneRef();
392  vpTemplateTrackerWarp *warp_ = tracker->getWarp();
393  vpColVector p_= tracker->getp();
394  warp_->warpZone(zoneRef_, p_, zoneWarped_);
395  zoneWarped_.display(I, vpColor::red, 3);
396  zoneRef_.display(I, vpColor::green, 3);
397 #endif
398 
399  vpDisplay::flush(I) ;
400  }
401  if (opt_click_allowed) {
402  vpDisplay::displayCharString(I, 10,10, "A click to exit...", vpColor::red);
403  vpDisplay::flush(I) ;
405  }
406  reader.close();
407  if (display)
408  delete display;
409 
410  delete warp;
411  delete tracker;
412 
413  return 0;
414  }
415  catch(vpException e)
416  {
417  std::cout << "Catch an exception: " << e << std::endl;
418  return -1;
419  }
420 }
421 
422 #else
423 
424 int main()
425 {
426  std::cout << "No display is available." << std::endl;
427  return 0;
428 }
429 
430 #endif
long getFrameIndex() const
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:176
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:132
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
static std::string path(const char *pathname)
Definition: vpIoTools.cpp:715
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:1994
vpColVector getp() const
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:79
static const vpColor red
Definition: vpColor.h:167
void open(vpImage< vpRGBa > &I)
Display for windows using Direct3D.
Definition: vpDisplayD3D.h:109
static void display(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:206
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)
virtual void displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color=vpColor::green)=0
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:92
void set_ij(const double ii, const double jj)
Definition: vpImagePoint.h:180
void setPyramidal(unsigned int nlevels=2, unsigned int level_to_stop=1)
vpTemplateTrackerWarp * getWarp() const
void setThresholdGradient(double threshold)
void setSampling(int _mod_i, int _mod_j)
void display(const vpImage< unsigned char > &I, const vpColor &col=vpColor::green, const unsigned int thickness=3)