Visual Servoing Platform  version 3.6.1 under development (2025-02-18)
trackMeCircle.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Tracking of an ellipse.
32  */
33 
46 #include <visp3/core/vpConfig.h>
47 
48 #if defined(VISP_HAVE_MODULE_ME) && defined(VISP_HAVE_DISPLAY)
49 
50 #include <visp3/core/vpColor.h>
51 #include <visp3/core/vpImage.h>
52 #include <visp3/core/vpIoTools.h>
53 #include <visp3/gui/vpDisplayFactory.h>
54 #include <visp3/io/vpImageIo.h>
55 #include <visp3/io/vpParseArgv.h>
56 #include <visp3/me/vpMeEllipse.h>
57 
58 // List of allowed command line options
59 #define GETOPTARGS "cdi:h"
60 
61 #ifdef ENABLE_VISP_NAMESPACE
62 using namespace VISP_NAMESPACE_NAME;
63 #endif
64 
65 void usage(const char *name, const char *badparam, std::string ipath);
66 bool getOptions(int argc, const char **argv, std::string &ipath, bool &click_allowed, bool &display);
67 
77 void usage(const char *name, const char *badparam, std::string ipath)
78 {
79 #if VISP_HAVE_DATASET_VERSION >= 0x030600
80  std::string ext("png");
81 #else
82  std::string ext("pgm");
83 #endif
84  fprintf(stdout, "\n\
85 Test auto detection of dots using vpDot2.\n\
86 \n\
87 SYNOPSIS\n\
88  %s [-i <input image path>] [-c] [-d] [-h]\n",
89  name);
90 
91  fprintf(stdout, "\n\
92 OPTIONS: Default\n\
93  -i <input image path> %s\n\
94  Set image input path.\n\
95  From this path read \"circle/circle.%s\"\n\
96  image. \n\
97  Setting the VISP_INPUT_IMAGE_PATH environment\n\
98  variable produces the same behaviour than using\n\
99  this option.\n\
100 \n\
101  -c\n\
102  Disable the mouse click. Useful to automate the \n\
103  execution of this program without human intervention.\n\
104 \n\
105  -d \n\
106  Turn off the display.\n\
107 \n\
108  -h\n\
109  Print the help.\n",
110  ipath.c_str(), ext.c_str());
111 
112  if (badparam)
113  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
114 }
128 bool getOptions(int argc, const char **argv, std::string &ipath, bool &click_allowed, bool &display)
129 {
130  const char *optarg_;
131  int c;
132  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
133 
134  switch (c) {
135  case 'c':
136  click_allowed = false;
137  break;
138  case 'd':
139  display = false;
140  break;
141  case 'i':
142  ipath = optarg_;
143  break;
144  case 'h':
145  usage(argv[0], nullptr, ipath);
146  return false;
147  break;
148 
149  default:
150  usage(argv[0], optarg_, ipath);
151  return false;
152  break;
153  }
154  }
155 
156  if ((c == 1) || (c == -1)) {
157  // standalone param or error
158  usage(argv[0], nullptr, ipath);
159  std::cerr << "ERROR: " << std::endl;
160  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
161  return false;
162  }
163 
164  return true;
165 }
166 
167 int main(int argc, const char **argv)
168 {
169 #if defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_OPENCV)
170  try {
171  std::string env_ipath;
172  std::string opt_ipath;
173  std::string ipath;
174  std::string dirname;
175  std::string filename;
176  bool opt_click_allowed = true;
177  bool opt_display = true;
178 
179 #if VISP_HAVE_DATASET_VERSION >= 0x030600
180  std::string ext("png");
181 #else
182  std::string ext("pgm");
183 #endif
184 
185  // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
186  // environment variable value
187  env_ipath = vpIoTools::getViSPImagesDataPath();
188 
189  // Set the default input path
190  if (!env_ipath.empty())
191  ipath = env_ipath;
192 
193  // Read the command line options
194  if (getOptions(argc, argv, opt_ipath, opt_click_allowed, opt_display) == false) {
195  return EXIT_FAILURE;
196  }
197 
198  // Get the option values
199  if (!opt_ipath.empty())
200  ipath = opt_ipath;
201 
202  // Compare ipath and env_ipath. If they differ, we take into account
203  // the input path coming from the command line option
204  if (!opt_ipath.empty() && !env_ipath.empty()) {
205  if (ipath != env_ipath) {
206  std::cout << std::endl << "WARNING: " << std::endl;
207  std::cout << " Since -i <visp image path=" << ipath << "> "
208  << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
209  << " we skip the environment variable." << std::endl;
210  }
211  }
212 
213  // Test if an input path is set
214  if (opt_ipath.empty() && env_ipath.empty()) {
215  usage(argv[0], nullptr, ipath);
216  std::cerr << std::endl << "ERROR:" << std::endl;
217  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
218  << " environment variable to specify the location of the " << std::endl
219  << " image path where test images are located." << std::endl
220  << std::endl;
221  return EXIT_FAILURE;
222  }
223 
224  // Declare an image, this is a gray level image (unsigned char)
225  // it size is not defined yet, it will be defined when the image will
226  // read on the disk
228  vpDisplay *display = nullptr;
229 
230  // Set the path location of the image sequence
231  dirname = vpIoTools::createFilePath(ipath, "circle");
232 
233  // Build the name of the image file
234  filename = vpIoTools::createFilePath(dirname, "circle." + ext);
235 
236  // Read the image into the image structure I. I is initialized to the correct size
237  // vpImageIo::read() may throw various exception if, for example,
238  // the file does not exist, or if the memory cannot be allocated
239  try {
240  std::cout << "Load: " << filename << std::endl;
241 
242  vpImageIo::read(I, filename);
243  }
244  catch (...) {
245  // If an exception is throwned it is catched here and will result in the end of the program.
246  // Note that another error message can be printed from vpImageIo::read() to give more
247  // information about the error
248  std::cerr << std::endl << "ERROR:" << std::endl;
249  std::cerr << " Cannot read " << filename << std::endl;
250  std::cerr << " Check your -i " << ipath << " option " << std::endl
251  << " or VISP_INPUT_IMAGE_PATH environment variable." << std::endl;
252  return EXIT_FAILURE;
253  }
254 
255  // We open a window using either X11, GTK or GDI
256  if (opt_display) {
258  // Display size is automatically defined by the image (I) size
259  display->init(I, 100, 100, "Display...");
260  // Display the image
261  // The image class has a member that specify a pointer toward
262  // the display that has been initialized in the display declaration
263  // therefore is is no longer necessary to make a reference to the
264  // display variable.
266  vpDisplay::flush(I);
267  }
268 
269  vpMeEllipse E1;
270 
271  vpMe me;
272  me.setRange(20);
273  me.setSampleStep(10);
275  me.setThreshold(20);
276 
277  E1.setMe(&me);
279  // If click is allowed, wait for a mouse click to select the points
280  // on the ellipse
281  if (opt_display && opt_click_allowed) {
282  E1.initTracking(I);
283  }
284  else {
285  // Create a list of points to automate the test
286  std::vector<vpImagePoint> ip;
287  ip.push_back(vpImagePoint(78, 203));
288  ip.push_back(vpImagePoint(62, 125));
289  ip.push_back(vpImagePoint(128, 101));
290  ip.push_back(vpImagePoint(167, 147));
291  ip.push_back(vpImagePoint(147, 200));
292 
293  E1.initTracking(I, ip);
294  }
295 
296  if (opt_display) {
297  E1.display(I, vpColor::green);
298  vpDisplay::flush(I);
299  }
300 
301  std::cout << "Sample step: " << E1.getMe()->getSampleStep() << std::endl;
302  std::cout << "Tracking on image: " << filename << std::endl;
303  E1.track(I);
304  if (opt_display) {
305  vpDisplay::flush(I);
306  }
307 
308  if (opt_display && opt_click_allowed) {
309  std::cout << "A click to exit..." << std::endl;
311  }
312 
313  if (display) {
314  delete display;
315  }
316  return EXIT_SUCCESS;
317  }
318  catch (const vpException &e) {
319  std::cout << "Catch an exception: " << e << std::endl;
320  return EXIT_FAILURE;
321  }
322 #else
323  (void)argc;
324  (void)argv;
325  std::cout << "Cannot run this example: install Lapack, Eigen3 or OpenCV" << std::endl;
326 #endif
327 }
328 #else
329 #include <iostream>
330 
331 int main()
332 {
333  std::cout << "visp_me module or X11, GTK, GDI or OpenCV display "
334  "functionalities are required..."
335  << std::endl;
336  return EXIT_SUCCESS;
337 }
338 
339 #endif
static const vpColor green
Definition: vpColor.h:201
Class that defines generic functionalities for display.
Definition: vpDisplay.h:178
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void display(const vpImage< unsigned char > &I)
static void flush(const vpImage< unsigned char > &I)
error that can be emitted by ViSP classes.
Definition: vpException.h:60
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:147
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:82
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1053
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1427
Class that tracks an ellipse using moving edges.
Definition: vpMeEllipse.h:96
void display(const vpImage< unsigned char > &I, const vpColor &col, unsigned int thickness=1)
void initTracking(const vpImage< unsigned char > &I, bool trackCircle=false, bool trackArc=false)
void track(const vpImage< unsigned char > &I)
@ RANGE_RESULT
Definition: vpMeSite.h:78
vpMe * getMe()
Definition: vpMeTracker.h:153
void setDisplay(vpMeSite::vpMeSiteDisplayType select)
Definition: vpMeTracker.h:232
void setMe(vpMe *me)
Definition: vpMeTracker.h:260
Definition: vpMe.h:134
void setRange(const unsigned int &range)
Definition: vpMe.h:415
void setLikelihoodThresholdType(const vpLikelihoodThresholdType likelihood_threshold_type)
Definition: vpMe.h:505
void setThreshold(const double &threshold)
Definition: vpMe.h:466
void setSampleStep(const double &sample_step)
Definition: vpMe.h:422
double getSampleStep() const
Definition: vpMe.h:275
@ NORMALIZED_THRESHOLD
Definition: vpMe.h:145
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:70
vpDisplay * allocateDisplay()
Return a newly allocated vpDisplay specialization if a GUI library is available or nullptr otherwise.