Visual Servoing Platform  version 3.6.1 under development (2025-02-18)
trackMeLine.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 a line.
32  */
33 
41 #include <visp3/core/vpConfig.h>
42 
43 #if defined(VISP_HAVE_MODULE_ME) && defined(VISP_HAVE_DISPLAY)
44 
45 #include <visp3/core/vpColor.h>
46 #include <visp3/core/vpImage.h>
47 #include <visp3/core/vpImagePoint.h>
48 #include <visp3/core/vpIoTools.h>
49 #include <visp3/gui/vpDisplayFactory.h>
50 #include <visp3/io/vpVideoReader.h>
51 #include <visp3/io/vpParseArgv.h>
52 #include <visp3/me/vpMeLine.h>
53 #include <visp3/visual_features/vpFeatureBuilder.h>
54 #include <visp3/visual_features/vpFeatureLine.h>
55 
56 // List of allowed command line options
57 #define GETOPTARGS "cdf:hi:l:p:s:"
58 
59 #ifdef ENABLE_VISP_NAMESPACE
60 using namespace VISP_NAMESPACE_NAME;
61 #endif
62 
74 void usage(const char *name, const char *badparam, std::string ipath, std::string ppath, unsigned first,
75  unsigned last, unsigned step)
76 {
77 #if VISP_HAVE_DATASET_VERSION >= 0x030600
78  std::string ext("png");
79 #else
80  std::string ext("pgm");
81 #endif
82  fprintf(stdout, "\n\
83 Tracking of a line.\n\
84 \n\
85 SYNOPSIS\n\
86  %s [-i <input image path>] [-p <personal image path>]\n\
87  [-f <first image>] [-l <last image>] [-s <step>]\n\
88  [-c] [-d] [-h]\n", name);
89 
90  fprintf(stdout, "\n\
91 OPTIONS: Default\n\
92  -i <input image path> %s\n\
93  Set image input path.\n\
94  From this path read \"line/image.%%04d.%s\"\n\
95  images. \n\
96  Setting the VISP_INPUT_IMAGE_PATH environment\n\
97  variable produces the same behaviour than using\n\
98  this option.\n\
99 \n\
100  -p <personal image path> %s\n\
101  Specify a personal sequence containing images \n\
102  to process.\n\
103  By image sequence, we mean one file per image.\n\
104  Example : \"C:/Temp/visp-images/line/image.%%04d.%s\"\n\
105  %%04d is for the image numbering.\n\
106 \n\
107  -f <first image> %u\n\
108  First image number of the sequence.\n\
109 \n\
110  -l <last image> %u\n\
111  Last image number of the sequence.\n\
112 \n\
113  -s <step> %u\n\
114  Step between two images.\n\
115 \n\
116  -c\n\
117  Disable the mouse click. Useful to automate the \n\
118  execution of this program without human intervention.\n\
119 \n\
120  -d \n\
121  Turn off the display.\n\
122 \n\
123  -h\n\
124  Print the help.\n",
125  ipath.c_str(), ext.c_str(), ppath.c_str(), ext.c_str(), first, last, step);
126 
127  if (badparam)
128  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
129 }
130 
148 bool getOptions(int argc, const char **argv, std::string &ipath, std::string &ppath, unsigned &first, unsigned &last,
149  unsigned &step, bool &click_allowed, bool &display)
150 {
151  const char *optarg_;
152  int c;
153  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
154 
155  switch (c) {
156  case 'c':
157  click_allowed = false;
158  break;
159  case 'd':
160  display = false;
161  break;
162  case 'i':
163  ipath = optarg_;
164  break;
165  case 'p':
166  ppath = optarg_;
167  break;
168  case 'f':
169  first = (unsigned)atoi(optarg_);
170  break;
171  case 'l':
172  last = (unsigned)atoi(optarg_);
173  break;
174  case 's':
175  step = (unsigned)atoi(optarg_);
176  break;
177  case 'h':
178  usage(argv[0], nullptr, ipath, ppath, first, last, step);
179  return false;
180  break;
181 
182  default:
183  usage(argv[0], optarg_, ipath, ppath, first, last, step);
184  return false;
185  break;
186  }
187  }
188 
189  if ((c == 1) || (c == -1)) {
190  // standalone param or error
191  usage(argv[0], nullptr, ipath, ppath, first, last, step);
192  std::cerr << "ERROR: " << std::endl;
193  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
194  return false;
195  }
196 
197  return true;
198 }
199 
200 int main(int argc, const char **argv)
201 {
202 #if defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_OPENCV)
203  std::string env_ipath;
204  std::string opt_ipath;
205  std::string ipath;
206  std::string opt_ppath;
207  std::string videoname;
208  unsigned int opt_first = 1;
209  unsigned int opt_last = 30;
210  unsigned int opt_step = 1;
211  bool opt_click_allowed = true;
212  bool opt_display = true;
213  unsigned int thickness = 1;
214 
216  vpDisplay *display = nullptr;
217  vpVideoReader g;
218 
219  try {
220  // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
221  // environment variable value
222  env_ipath = vpIoTools::getViSPImagesDataPath();
223 
224  // Set the default input path
225  if (!env_ipath.empty())
226  ipath = env_ipath;
227 
228  // Read the command line options
229  if (getOptions(argc, argv, opt_ipath, opt_ppath, opt_first, opt_last, opt_step, opt_click_allowed,
230  opt_display) == false) {
231  return EXIT_FAILURE;
232  }
233 
234  // Get the option values
235  if (!opt_ipath.empty()) {
236  ipath = opt_ipath;
237  }
238 
239  // Compare ipath and env_ipath. If they differ, we take into account
240  // the input path coming from the command line option
241  if (!opt_ipath.empty() && !env_ipath.empty() && opt_ppath.empty()) {
242  if (ipath != env_ipath) {
243  std::cout << std::endl << "WARNING: " << std::endl;
244  std::cout << " Since -i <visp image path=" << ipath << "> "
245  << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
246  << " we skip the environment variable." << std::endl;
247  }
248  }
249 
250  // Test if an input path is set
251  if (opt_ipath.empty() && env_ipath.empty() && opt_ppath.empty()) {
252  usage(argv[0], nullptr, ipath, opt_ppath, opt_first, opt_last, opt_step);
253  std::cerr << std::endl << "ERROR:" << std::endl;
254  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
255  << " environment variable to specify the location of the " << std::endl
256  << " image path where test images are located." << std::endl
257  << " Use -p <personal image path> option if you want to " << std::endl
258  << " use personal images." << std::endl
259  << std::endl;
260 
261  return EXIT_FAILURE;
262  }
263 
264  vpVideoReader g;
265  if (opt_ppath.empty()) {
266  // Set the path location of the image sequence
267 #if VISP_HAVE_DATASET_VERSION >= 0x030600
268  videoname = vpIoTools::createFilePath(ipath, "line/image.%04d.png");
269 #else
270  videoname = vpIoTools::createFilePath(ipath, "line/image.%04d.pgm");
271 #endif
272  g.setFileName(videoname);
273  }
274  else {
275  g.setFileName(opt_ppath);
276  }
277 
278  if (opt_first > 0) {
279  g.setFirstFrameIndex(opt_first);
280  }
281  if (opt_last > 0) {
282  g.setLastFrameIndex(opt_last);
283  }
284  g.setFrameStep(opt_step);
285  g.open(I);
286 
287  if (opt_display) {
288  // We open a window using either X11, GTK, GDI or OpenCV
290 
291  // Display size is automatically defined by the image (I) size
292  display->init(I, 10, 10, "Current image");
293  // Display the image
294  // The image class has a member that specify a pointer toward
295  // the display that has been initialized in the display declaration
296  // therefore is is no longer necessary to make a reference to the
297  // display variable.
299  vpDisplay::flush(I);
300  }
301 
302  vpMeLine me_line;
303 
304  vpMe me;
305  me.setRange(20);
306  me.setPointsToTrack(160);
308  me.setThreshold(20);
309 
310  me_line.setMe(&me);
312  // ajout FC
313  const bool useIntensity = true;
314  me_line.setRhoSignFromIntensity(useIntensity);
315  // fin ajout FC
316 
317  std::cout << "Video settings" << std::endl;
318  std::cout << " Name : " << g.getFrameName() << std::endl;
319  std::cout << " First image: " << g.getFirstFrameIndex() << std::endl;
320  std::cout << " Last image : " << g.getLastFrameIndex() << std::endl;
321  std::cout << " Step : " << g.getFrameStep() << std::endl;
322  std::cout << " Image size : " << I.getWidth() << " x " << I.getHeight() << std::endl;
323 
324  std::cout << "Moving-edges settings" << std::endl;
325  std::cout << " Sample step : " << me_line.getMe()->getSampleStep() << std::endl;
326  std::cout << " Range : " << me_line.getMe()->getRange() << std::endl;
327  std::cout << " Threshold type: " << (me_line.getMe()->getLikelihoodThresholdType() == vpMe::NORMALIZED_THRESHOLD ? "normalized" : "old threshold (to be avoided)") << std::endl;
328  std::cout << " Threshold : " << me_line.getMe()->getThreshold() << std::endl;
329 
330  if (opt_display && opt_click_allowed)
331  me_line.initTracking(I);
332  else {
333  vpImagePoint ip1, ip2;
334  ip1.set_i(96);
335  ip1.set_j(191);
336  ip2.set_i(122);
337  ip2.set_j(211);
338  me_line.initTracking(I, ip1, ip2);
339  }
340  me_line.track(I);
341 
342  if (opt_display) {
343  me_line.display(I, vpColor::green);
344  vpDisplay::flush(I);
345  }
346  if (opt_display && opt_click_allowed) {
347  std::cout << "A click to continue..." << std::endl;
349  }
350  std::cout << "----------------------------------------------------------" << std::endl;
351 
352  vpFeatureLine l;
353 
354  vpCameraParameters cam;
355 
356  bool quit = false;
357  while (!g.end() && !quit) {
358  g.acquire(I);
359  std::cout << "Process image " << g.getFrameIndex() << std::endl;
360  if (opt_display) {
361  // Display the image
363  if (opt_click_allowed) {
364  vpDisplay::displayText(I, 40, 10, "Click to exit...", vpColor::red);
365  }
366  }
367 
368  me_line.track(I);
369 
370  vpTRACE("me_line: rho %lf theta (dg) %lf", me_line.getRho(), vpMath::deg(me_line.getTheta()));
371  vpFeatureBuilder::create(l, cam, me_line);
372  vpTRACE("fe_line: rho %lf theta (dg) %lf", l.getRho(), vpMath::deg(l.getTheta()));
373 
374  // FC print
375  // printf("me_line: rho %lf theta (dg) %lf\n", me_line.getRho(), vpMath::deg(me_line.getTheta()));
376  // printf("fe_line: rho %lf theta (dg) %lf\n", l.getRho(), vpMath::deg(l.getTheta()));
377  // FC fin print
378 
379  if (opt_display) {
380  me_line.display(I, vpColor::green, thickness);
381  vpDisplay::flush(I);
382  if (opt_click_allowed) {
383  if (vpDisplay::getClick(I, false)) {
384  quit = true;
385  }
386  }
387  // ajout FC
388  // std::cout << "A click to continue..." << std::endl;
389  // vpDisplay::getClick(I);
390  // fin ajout FC
391  }
392  }
393  if (opt_display && opt_click_allowed && !quit) {
395  }
396  if (display) {
397  delete display;
398  }
399  return EXIT_SUCCESS;
400  }
401  catch (const vpException &e) {
402  std::cout << "Catch an exception: " << e << std::endl;
403  return EXIT_FAILURE;
404  }
405 #else
406  (void)argc;
407  (void)argv;
408  std::cout << "Cannot run this example: install Lapack, Eigen3 or OpenCV" << std::endl;
409 #endif
410 }
411 
412 #else
413 #include <iostream>
414 
415 int main()
416 {
417  std::cout << "visp_me module or X11, GTK, GDI or OpenCV display functionalities are required..." << std::endl;
418  return EXIT_SUCCESS;
419 }
420 
421 #endif
Generic class defining intrinsic camera parameters.
static const vpColor red
Definition: vpColor.h:198
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)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
error that can be emitted by ViSP classes.
Definition: vpException.h:60
static void create(vpFeaturePoint &s, const vpCameraParameters &cam, const vpImagePoint &t)
Class that defines a 2D line visual feature which is composed by two parameters that are and ,...
double getTheta() const
double getRho() const
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:82
void set_j(double jj)
Definition: vpImagePoint.h:309
void set_i(double ii)
Definition: vpImagePoint.h:298
unsigned int getWidth() const
Definition: vpImage.h:242
unsigned int getHeight() const
Definition: vpImage.h:181
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1053
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1427
static double deg(double rad)
Definition: vpMath.h:119
Class that tracks in an image a line moving edges.
Definition: vpMeLine.h:153
double getRho() const
Definition: vpMeLine.h:227
void display(const vpImage< unsigned char > &I, const vpColor &color, unsigned int thickness=1)
Definition: vpMeLine.cpp:197
double getTheta() const
Definition: vpMeLine.h:257
void track(const vpImage< unsigned char > &I)
Definition: vpMeLine.cpp:683
void initTracking(const vpImage< unsigned char > &I)
Definition: vpMeLine.cpp:207
void setRhoSignFromIntensity(bool useIntensityForRho)
Definition: vpMeLine.h:288
@ 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 setPointsToTrack(const int &points_to_track)
Definition: vpMe.h:408
vpLikelihoodThresholdType getLikelihoodThresholdType() const
Definition: vpMe.h:327
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
double getThreshold() const
Definition: vpMe.h:291
double getSampleStep() const
Definition: vpMe.h:275
unsigned int getRange() const
Definition: vpMe.h:268
@ NORMALIZED_THRESHOLD
Definition: vpMe.h:145
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:70
Class that enables to manipulate easily a video file or a sequence of images. As it inherits from the...
void acquire(vpImage< vpRGBa > &I)
void setLastFrameIndex(const long last_frame)
long getLastFrameIndex()
void open(vpImage< vpRGBa > &I)
void setFileName(const std::string &filename)
void setFirstFrameIndex(const long first_frame)
long getFirstFrameIndex()
void setFrameStep(const long frame_step)
long getFrameStep() const
std::string getFrameName() const
long getFrameIndex() const
vpDisplay * allocateDisplay()
Return a newly allocated vpDisplay specialization if a GUI library is available or nullptr otherwise.