Visual Servoing Platform  version 3.5.0 under development (2022-02-15)
trackMeLine.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  * Tracking of a line.
33  *
34  * Authors:
35  * Eric Marchand
36  * Fabien Spindler
37  *
38  *****************************************************************************/
51 #include <visp3/core/vpConfig.h>
52 #include <visp3/core/vpDebug.h>
53 
54 #include <iomanip>
55 #include <sstream>
56 #include <stdio.h>
57 #include <stdlib.h>
58 
59 #if defined(VISP_HAVE_MODULE_ME) && \
60  (defined(VISP_HAVE_X11) || defined(VISP_HAVE_GTK) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV))
61 
62 #include <visp3/core/vpColor.h>
63 #include <visp3/core/vpImage.h>
64 #include <visp3/core/vpImagePoint.h>
65 #include <visp3/gui/vpDisplayGDI.h>
66 #include <visp3/gui/vpDisplayGTK.h>
67 #include <visp3/gui/vpDisplayOpenCV.h>
68 #include <visp3/gui/vpDisplayX.h>
69 #include <visp3/io/vpImageIo.h>
70 
71 #include <visp3/me/vpMeLine.h>
72 
73 #include <visp3/visual_features/vpFeatureBuilder.h>
74 #include <visp3/visual_features/vpFeatureLine.h>
75 
76 #include <visp3/core/vpIoTools.h>
77 #include <visp3/io/vpParseArgv.h>
78 
79 // List of allowed command line options
80 #define GETOPTARGS "cdi:h"
81 
82 void usage(const char *name, const char *badparam, std::string ipath);
83 bool getOptions(int argc, const char **argv, std::string &ipath, bool &click_allowed, bool &display);
84 
94 void usage(const char *name, const char *badparam, std::string ipath)
95 {
96  fprintf(stdout, "\n\
97 Tracking of a line.\n\
98 \n\
99 SYNOPSIS\n\
100  %s [-i <input image path>] [-c] [-d] [-h]\n", name);
101 
102  fprintf(stdout, "\n\
103 OPTIONS: Default\n\
104  -i <input image path> %s\n\
105  Set image input path.\n\
106  From this path read \"line/image.%%04d.pgm\"\n\
107  images. \n\
108  Setting the VISP_INPUT_IMAGE_PATH environment\n\
109  variable produces the same behaviour than using\n\
110  this option.\n\
111 \n\
112  -c\n\
113  Disable the mouse click. Useful to automaze the \n\
114  execution of this program without humain intervention.\n\
115 \n\
116  -d \n\
117  Turn off the display.\n\
118 \n\
119  -h\n\
120  Print the help.\n", ipath.c_str());
121 
122  if (badparam)
123  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
124 }
138 bool getOptions(int argc, const char **argv, std::string &ipath, bool &click_allowed, bool &display)
139 {
140  const char *optarg_;
141  int c;
142  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
143 
144  switch (c) {
145  case 'c':
146  click_allowed = false;
147  break;
148  case 'd':
149  display = false;
150  break;
151  case 'i':
152  ipath = optarg_;
153  break;
154  case 'h':
155  usage(argv[0], NULL, ipath);
156  return false;
157  break;
158 
159  default:
160  usage(argv[0], optarg_, ipath);
161  return false;
162  break;
163  }
164  }
165 
166  if ((c == 1) || (c == -1)) {
167  // standalone param or error
168  usage(argv[0], NULL, ipath);
169  std::cerr << "ERROR: " << std::endl;
170  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
171  return false;
172  }
173 
174  return true;
175 }
176 
177 int main(int argc, const char **argv)
178 {
179 #if defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_OPENCV)
180  try {
181  std::string env_ipath;
182  std::string opt_ipath;
183  std::string ipath;
184  std::string dirname;
185  std::string filename;
186  bool opt_click_allowed = true;
187  bool opt_display = true;
188 
189  // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
190  // environment variable value
191  env_ipath = vpIoTools::getViSPImagesDataPath();
192 
193  // Set the default input path
194  if (!env_ipath.empty())
195  ipath = env_ipath;
196 
197  // Read the command line options
198  if (getOptions(argc, argv, opt_ipath, opt_click_allowed, opt_display) == false) {
199  exit(-1);
200  }
201 
202  // Get the option values
203  if (!opt_ipath.empty())
204  ipath = opt_ipath;
205 
206  // Compare ipath and env_ipath. If they differ, we take into account
207  // the input path comming from the command line option
208  if (!opt_ipath.empty() && !env_ipath.empty()) {
209  if (ipath != env_ipath) {
210  std::cout << std::endl << "WARNING: " << std::endl;
211  std::cout << " Since -i <visp image path=" << ipath << "> "
212  << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
213  << " we skip the environment variable." << std::endl;
214  }
215  }
216 
217  // Test if an input path is set
218  if (opt_ipath.empty() && env_ipath.empty()) {
219  usage(argv[0], NULL, ipath);
220  std::cerr << std::endl << "ERROR:" << std::endl;
221  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
222  << " environment variable to specify the location of the " << std::endl
223  << " image path where test images are located." << std::endl
224  << std::endl;
225  exit(-1);
226  }
227 
228  // Declare an image, this is a gray level image (unsigned char)
229  // it size is not defined yet, it will be defined when the image will
230  // read on the disk
232 
233  // Set the path location of the image sequence
234  dirname = vpIoTools::createFilePath(ipath, "line");
235 
236  // Build the name of the image file
237  unsigned int iter = 1; // Image number
238  std::ostringstream s;
239  s.setf(std::ios::right, std::ios::adjustfield);
240  s << "image." << std::setw(4) << std::setfill('0') << iter << ".pgm";
241  filename = vpIoTools::createFilePath(dirname, s.str());
242 
243  // Read the PGM image named "filename" on the disk, and put the
244  // bitmap into the image structure I. I is initialized to the
245  // correct size
246  //
247  // exception readPGM may throw various exception if, for example,
248  // the file does not exist, or if the memory cannot be allocated
249  try {
250  vpCTRACE << "Load: " << filename << std::endl;
251 
252  vpImageIo::read(I, filename);
253  } catch (...) {
254  // an exception is throwned if an exception from readPGM has been
255  // catched here this will result in the end of the program Note that
256  // another error message has been printed from readPGM to give more
257  // information about the error
258  std::cerr << std::endl << "ERROR:" << std::endl;
259  std::cerr << " Cannot read " << filename << std::endl;
260  std::cerr << " Check your -i " << ipath << " option " << std::endl
261  << " or VISP_INPUT_IMAGE_PATH environment variable." << std::endl;
262  exit(-1);
263  }
264 
265 // We open a window using either X11, GTK or GDI.
266 #if defined VISP_HAVE_X11
267  vpDisplayX display;
268 #elif defined VISP_HAVE_GTK
269  vpDisplayGTK display;
270 #elif defined VISP_HAVE_GDI
271  vpDisplayGDI display;
272 #elif defined VISP_HAVE_OPENCV
273  vpDisplayOpenCV display;
274 #endif
275 
276  if (opt_display) {
277  // Display size is automatically defined by the image (I) size
278  display.init(I, 100, 100, "Display...");
279  // Display the image
280  // The image class has a member that specify a pointer toward
281  // the display that has been initialized in the display declaration
282  // therefore is is no longuer necessary to make a reference to the
283  // display variable.
285  vpDisplay::flush(I);
286  }
287 
288  vpMeLine L1;
289 
290  vpMe me;
291  me.setRange(15);
292  me.setPointsToTrack(160);
293  me.setThreshold(15000);
294 
295  L1.setMe(&me);
297 
298  if (opt_display && opt_click_allowed)
299  L1.initTracking(I);
300  else {
301  vpImagePoint ip1, ip2;
302  ip1.set_i(96);
303  ip1.set_j(191);
304  ip2.set_i(122);
305  ip2.set_j(211);
306  L1.initTracking(I, ip1, ip2);
307  }
308 
309  if (opt_display)
310  L1.display(I, vpColor::green);
311 
312  L1.track(I);
313  if (opt_display && opt_click_allowed) {
314  std::cout << "A click to continue..." << std::endl;
316  }
317  std::cout << "----------------------------------------------------------" << std::endl;
318 
319  vpFeatureLine l;
320 
321  vpCameraParameters cam;
322  vpImage<vpRGBa> Ic;
323  for (iter = 1; iter < 30; iter++) {
324  std::cout << "----------------------------------------------------------" << std::endl;
325  // set the new image name
326  s.str("");
327  s << "image." << std::setw(4) << std::setfill('0') << iter << ".pgm";
328  filename = vpIoTools::createFilePath(dirname, s.str());
329  // read the image
330  vpImageIo::read(I, filename);
331  if (opt_display) {
332  // Display the image
334  }
335 
336  std::cout << "Tracking on image: " << filename << std::endl;
337  L1.track(I);
338 
339  vpTRACE("L1 : %f %f", L1.getRho(), vpMath::deg(L1.getTheta()));
340  vpFeatureBuilder::create(l, cam, L1);
341  vpTRACE("L1 : %f %f", l.getRho(), vpMath::deg(l.getTheta()));
342 
343  if (opt_display) {
344  L1.display(I, vpColor::green);
345  vpDisplay::flush(I);
346  if (opt_click_allowed) {
347  std::cout << "A click to continue..." << std::endl;
349  }
350  }
351  }
352  if (opt_display && opt_click_allowed) {
353  std::cout << "A click to exit..." << std::endl;
355  }
356  return EXIT_SUCCESS;
357  } catch (const vpException &e) {
358  std::cout << "Catch an exception: " << e << std::endl;
359  return EXIT_FAILURE;
360  }
361 #else
362  (void)argc;
363  (void)argv;
364  std::cout << "Cannot run this example: install Lapack, Eigen3 or OpenCV" << std::endl;
365 #endif
366 }
367 
368 #else
369 #include <iostream>
370 
371 int main()
372 {
373  std::cout << "visp_me module or X11, GTK, GDI or OpenCV display "
374  "functionalities are required..."
375  << std::endl;
376  return EXIT_SUCCESS;
377 }
378 
379 #endif
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:149
double getTheta() const
Definition: vpMeLine.cpp:960
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1365
void setPointsToTrack(const int &n)
Definition: vpMe.h:264
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:128
double getRho() const
Definition: vpMeLine.cpp:955
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition: vpDisplayX.h:134
double getRho() const
error that can be emited by ViSP classes.
Definition: vpException.h:71
void track(const vpImage< unsigned char > &Im)
Definition: vpMeLine.cpp:746
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="")
Definition: vpMe.h:60
static const vpColor green
Definition: vpColor.h:220
static void flush(const vpImage< unsigned char > &I)
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:69
void display(const vpImage< unsigned char > &I, vpColor col)
Definition: vpMeLine.cpp:224
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1670
void set_i(double ii)
Definition: vpImagePoint.h:166
#define vpTRACE
Definition: vpDebug.h:416
void setDisplay(vpMeSite::vpMeSiteDisplayType select)
Definition: vpMeTracker.h:152
static void display(const vpImage< unsigned char > &I)
Class that tracks in an image a line moving edges.
Definition: vpMeLine.h:151
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
Generic class defining intrinsic camera parameters.
Class that defines a 2D line visual feature which is composed by two parameters that are and ...
double getTheta() const
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
Definition: vpDisplayGTK.h:134
void initTracking(const vpImage< unsigned char > &I)
Definition: vpMeLine.cpp:236
void set_j(double jj)
Definition: vpImagePoint.h:177
static double deg(double rad)
Definition: vpMath.h:103
#define vpCTRACE
Definition: vpDebug.h:338
void setThreshold(const double &t)
Definition: vpMe.h:300
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:87
static void create(vpFeaturePoint &s, const vpCameraParameters &cam, const vpDot &d)
void setRange(const unsigned int &r)
Definition: vpMe.h:271
void setMe(vpMe *p_me)
Definition: vpMeTracker.h:173