Visual Servoing Platform version 3.5.0
trackDot2.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 * Example of dot tracking.
33 *
34 * Authors:
35 * Eric Marchand
36 * Fabien Spindler
37 *
38 *****************************************************************************/
45#include <visp3/core/vpConfig.h>
46#include <visp3/core/vpDebug.h>
47
48#include <iomanip>
49#include <sstream>
50#include <stdio.h>
51#include <stdlib.h>
52
53#if defined(VISP_HAVE_MODULE_BLOB) && \
54 (defined(VISP_HAVE_X11) || defined(VISP_HAVE_GTK) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV))
55
56#include <visp3/blob/vpDot2.h>
57#include <visp3/core/vpImage.h>
58#include <visp3/core/vpImagePoint.h>
59#include <visp3/core/vpIoTools.h>
60#include <visp3/gui/vpDisplayGDI.h>
61#include <visp3/gui/vpDisplayGTK.h>
62#include <visp3/gui/vpDisplayOpenCV.h>
63#include <visp3/gui/vpDisplayX.h>
64#include <visp3/io/vpImageIo.h>
65#include <visp3/io/vpParseArgv.h>
66
67// List of allowed command line options
68#define GETOPTARGS "cdf:i:n:p:s:h"
69
70// int gsl_warnings_off;
71
72void usage(const char *name, const char *badparam, std::string ipath, std::string ppath, unsigned first,
73 unsigned nimages, unsigned step);
74bool getOptions(int argc, const char **argv, std::string &ipath, std::string &ppath, unsigned &first, unsigned &nimages,
75 unsigned &step, bool &click_allowed, bool &display);
95void usage(const char *name, const char *badparam, std::string ipath, std::string ppath, unsigned first,
96 unsigned nimages, unsigned step)
97{
98 fprintf(stdout, "\n\
99Test dot tracking using vpDot2 class.\n\
100\n\
101SYNOPSIS\n\
102 %s [-i <test image path>] [-p <personal image path>]\n\
103 [-f <first image>] [-n <number of images>] [-s <step>]\n\
104 [-c] [-d] [-h]\n", name);
105
106 fprintf(stdout, "\n\
107OPTIONS: Default\n\
108 -i <input image path> %s\n\
109 Set image input path.\n\
110 From this path read images \n\
111 \"mire-2/image.%%04d.pgm\". These \n\
112 images come from ViSP-images-x.y.z.tar.gz available \n\
113 on the ViSP website.\n\
114 Setting the VISP_INPUT_IMAGE_PATH environment\n\
115 variable produces the same behaviour than using\n\
116 this option.\n\
117 \n\
118 -p <personal image path> %s\n\
119 Specify a personal sequence containing images \n\
120 to process.\n\
121 By image sequence, we mean one file per image.\n\
122 The following image file formats PNM (PGM P5, PPM P6)\n\
123 are supported. The format is selected by analysing \n\
124 the filename extension.\n\
125 Example : \"C:/Temp/ViSP-images/cube/image.%%04d.pgm\"\n\
126 %%04d is for the image numbering.\n\
127 \n\
128 -f <first image> %u\n\
129 First image number of the sequence.\n\
130 \n\
131 -n <number of images> %u\n\
132 Number of images to load from the sequence.\n\
133 \n\
134 -s <step> %u\n\
135 Step between two images.\n\
136\n\
137 -c\n\
138 Disable the mouse click. Useful to automaze the \n\
139 execution of this program without humain intervention.\n\
140\n\
141 -d \n\
142 Turn off the display.\n\
143\n\
144 -h\n\
145 Print the help.\n", ipath.c_str(), ppath.c_str(), first, nimages, step);
146
147 if (badparam)
148 fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
149}
167bool getOptions(int argc, const char **argv, std::string &ipath, std::string &ppath, unsigned &first, unsigned &nimages,
168 unsigned &step, bool &click_allowed, bool &display)
169{
170 const char *optarg_;
171 int c;
172 while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
173
174 switch (c) {
175 case 'c':
176 click_allowed = false;
177 break;
178 case 'd':
179 display = false;
180 break;
181 case 'i':
182 ipath = optarg_;
183 break;
184 case 'p':
185 ppath = optarg_;
186 break;
187 case 'f':
188 first = (unsigned)atoi(optarg_);
189 break;
190 case 'n':
191 nimages = (unsigned)atoi(optarg_);
192 break;
193 case 's':
194 step = (unsigned)atoi(optarg_);
195 break;
196 case 'h':
197 usage(argv[0], NULL, ipath, ppath, first, nimages, step);
198 return false;
199 break;
200
201 default:
202 usage(argv[0], optarg_, ipath, ppath, first, nimages, step);
203 return false;
204 break;
205 }
206 }
207
208 if ((c == 1) || (c == -1)) {
209 // standalone param or error
210 usage(argv[0], NULL, ipath, ppath, first, nimages, step);
211 std::cerr << "ERROR: " << std::endl;
212 std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
213 return false;
214 }
215
216 return true;
217}
218
219int main(int argc, const char **argv)
220{
221 try {
222 std::string env_ipath;
223 std::string opt_ipath;
224 std::string ipath;
225 std::string opt_ppath;
226 std::string dirname;
227 std::string filename;
228 unsigned opt_first = 1;
229 unsigned opt_nimages = 500;
230 unsigned opt_step = 1;
231 bool opt_click_allowed = true;
232 bool opt_display = true;
233
234 // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
235 // environment variable value
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_ppath, opt_first, opt_nimages, opt_step, opt_click_allowed,
244 opt_display) == false) {
245 exit(-1);
246 }
247
248 // Get the option values
249 if (!opt_ipath.empty())
250 ipath = opt_ipath;
251
252 // Compare ipath and env_ipath. If they differ, we take into account
253 // the input path comming from the command line option
254 if (!opt_ipath.empty() && !env_ipath.empty() && opt_ppath.empty()) {
255 if (ipath != env_ipath) {
256 std::cout << std::endl << "WARNING: " << std::endl;
257 std::cout << " Since -i <visp image path=" << ipath << "> "
258 << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
259 << " we skip the environment variable." << std::endl;
260 }
261 }
262
263 // Test if an input path is set
264 if (opt_ipath.empty() && env_ipath.empty() && opt_ppath.empty()) {
265 usage(argv[0], NULL, ipath, opt_ppath, opt_first, opt_nimages, opt_step);
266 std::cerr << std::endl << "ERROR:" << std::endl;
267 std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
268 << " environment variable to specify the location of the " << std::endl
269 << " image path where test images are located." << std::endl
270 << " Use -p <personal image path> option if you want to " << std::endl
271 << " use personal images." << std::endl
272 << std::endl;
273
274 exit(-1);
275 }
276
277 // Declare an image, this is a gray level image (unsigned char)
278 // it size is not defined yet, it will be defined when the image will
279 // read on the disk
281
282 unsigned iter = opt_first;
283 std::ostringstream s;
284 char cfilename[FILENAME_MAX];
285
286 if (opt_ppath.empty()) {
287
288 // Warning :
289 // the image sequence is not provided with the ViSP package
290 // therefore the program will return you an error :
291 // !! vpImageIoPnm.cpp: readPGM(#210) :couldn't read file
292 // ViSP-images/mire-2/image.0001.pgm
293 // !! vpDotExample.cpp: main(#95) :Error while reading the image
294 // terminate called after throwing an instance of 'vpImageException'
295 //
296 // The sequence is available on the visp www site
297 // https://visp.inria.fr/download/
298 // in the download section. It is named "ViSP-images.tar.gz"
299
300 // Set the path location of the image sequence
301 dirname = vpIoTools::createFilePath(ipath, "mire-2");
302
303 // Build the name of the image file
304
305 s.setf(std::ios::right, std::ios::adjustfield);
306 s << "image." << std::setw(4) << std::setfill('0') << iter << ".pgm";
307 filename = vpIoTools::createFilePath(dirname, s.str());
308 } else {
309
310 sprintf(cfilename, opt_ppath.c_str(), iter);
311 filename = cfilename;
312 }
313
314 // Read the PGM image named "filename" on the disk, and put the
315 // bitmap into the image structure I. I is initialized to the
316 // correct size
317 //
318 // exception readPGM may throw various exception if, for example,
319 // the file does not exist, or if the memory cannot be allocated
320 try {
321 vpCTRACE << "Load: " << filename << std::endl;
322
323 vpImageIo::read(I, filename);
324 } catch (...) {
325 // an exception is throwned if an exception from readPGM has been
326 // catched here this will result in the end of the program Note that
327 // another error message has been printed from readPGM to give more
328 // information about the error
329 std::cerr << std::endl << "ERROR:" << std::endl;
330 std::cerr << " Cannot read " << filename << std::endl;
331 std::cerr << " Check your -i " << ipath << " option " << std::endl
332 << " or VISP_INPUT_IMAGE_PATH environment variable." << std::endl;
333 exit(-1);
334 }
335
336// We open a window using either X11, GTK or GDI.
337#if defined VISP_HAVE_X11
338 vpDisplayX display;
339#elif defined VISP_HAVE_GTK
340 vpDisplayGTK display;
341#elif defined VISP_HAVE_GDI
342 vpDisplayGDI display;
343#elif defined VISP_HAVE_OPENCV
344 vpDisplayOpenCV display;
345#endif
346
347 if (opt_display) {
348 // Display size is automatically defined by the image (I) size
349 display.init(I, 100, 100, "Display...");
350 // Display the image
351 // The image class has a member that specify a pointer toward
352 // the display that has been initialized in the display declaration
353 // therefore is is no longuer necessary to make a reference to the
354 // display variable.
357 }
358 // define the vpDot structure.
359
360 // vpDot and vpDot2 correspond to two different algorithms designed to
361 // track a dot. vpDot is based on recurse connex componants (all the
362 // pixels of the dot are parsed), while vpDot2 is based on freeman chain
363 // code (only the contour of the dot is parsed)
364
365 vpDot2 d;
366 vpImagePoint cog;
367
368 if (opt_display) {
369 // by using setGraphics, we request to see the all the pixel of the dot
370 // in green on the screen.
371 // It uses the overlay image plane.
372 // The default of this setting is that it is time consumming
373
374 d.setGraphics(true);
375 } else {
376
377 d.setGraphics(false);
378 }
379 // We want to track an ellipsoid shape. If you want to track a non
380 // ellipsoid object, use d.setEllipsoidShape(0); we also request to
381 // compute the dot moment m00, m10, m01, m11, m20, m02
382 d.setComputeMoments(true);
383 d.setGrayLevelPrecision(0.90);
384
385 // tracking is initalized if no other parameters are given to the
386 // iniTracking(..) method a right mouse click on the dot is expected
387 // dot location can also be specified explicitely in the
388 // initTracking method : d.initTracking(I,ip) where ip is the image
389 // point from which the dot is searched
390
391 if (opt_display && opt_click_allowed) {
392 std::cout << "Click on a dot to track it." << std::endl;
393 d.initTracking(I);
394 } else {
395 vpImagePoint ip;
396 ip.set_u(160);
397 ip.set_v(212);
398 d.initTracking(I, ip);
399 }
400 if (1) {
401 std::cout << "COG: " << std::endl;
402 cog = d.getCog();
403 std::cout << " u: " << cog.get_u() << " v: " << cog.get_v() << std::endl;
404 std::cout << "Size:" << std::endl;
405 std::cout << " w: " << d.getWidth() << " h: " << d.getHeight() << std::endl;
406 std::cout << "Area: " << d.getArea() << std::endl;
407 std::cout << "Centered normalized moments nij:" << std::endl;
408 std::cout << " n20: " << d.get_nij()[0] << std::endl;
409 std::cout << " n11: " << d.get_nij()[1] << std::endl;
410 std::cout << " n02: " << d.get_nij()[2] << std::endl;
411 std::cout << "Settings:" << std::endl;
412 std::cout << " gray level min: " << d.getGrayLevelMin() << std::endl;
413 std::cout << " gray level max: " << d.getGrayLevelMax() << std::endl;
414 std::cout << " size precision: " << d.getSizePrecision() << std::endl;
415 std::cout << " gray level precision: " << d.getGrayLevelPrecision() << std::endl;
416 }
417
418 while (iter < opt_first + opt_nimages * opt_step) {
419 // set the new image name
420 if (opt_ppath.empty()) {
421 s.str("");
422 s << "image." << std::setw(4) << std::setfill('0') << iter << ".pgm";
423 filename = vpIoTools::createFilePath(dirname, s.str());
424 } else {
425 sprintf(cfilename, opt_ppath.c_str(), iter);
426 filename = cfilename;
427 }
428 // read the image
429 std::cout << "read : " << filename << std::endl;
430 vpImageIo::read(I, filename);
431
432 // track the dot and returns its coordinates in the image
433 // results are given in float since many many are usually considered
434 //
435 // an expcetion is thrown by the track method if
436 // - dot is lost
437
438 if (opt_display) {
439 // Display the image
441 }
442
443 std::cout << "Tracking on image: " << filename << std::endl;
444 double time = vpTime::measureTimeMs();
445 d.track(I);
446
447 std::cout << "COG (" << vpTime::measureTimeMs() - time << " ms): " << std::endl;
448 cog = d.getCog();
449 std::cout << " u: " << cog.get_u() << " v: " << cog.get_v() << std::endl;
450 std::cout << "Size:" << std::endl;
451 std::cout << " w: " << d.getWidth() << " h: " << d.getHeight() << std::endl;
452 std::cout << "Area: " << d.getArea() << std::endl;
453 std::cout << "Centered normalized moments nij:" << std::endl;
454 std::cout << " n20: " << d.get_nij()[0] << std::endl;
455 std::cout << " n11: " << d.get_nij()[1] << std::endl;
456 std::cout << " n02: " << d.get_nij()[2] << std::endl;
457 std::cout << "Settings:" << std::endl;
458 std::cout << " gray level min: " << d.getGrayLevelMin() << std::endl;
459 std::cout << " gray level max: " << d.getGrayLevelMax() << std::endl;
460 std::cout << " size precision: " << d.getSizePrecision() << std::endl;
461 std::cout << " gray level precision: " << d.getGrayLevelPrecision() << std::endl;
462
463 if (opt_display) {
464 if (0) {
465 std::list<vpImagePoint> edges;
466 d.getEdges(edges);
467 std::list<vpImagePoint>::const_iterator it;
468 for (it = edges.begin(); it != edges.end(); ++it) {
470 }
471 }
472
473 // display a green cross (size 10) in the image at the dot center
474 // of gravity location
476 // flush the X11 buffer
477
479 }
480 iter++;
481 }
482
483 if (opt_display && opt_click_allowed) {
484 std::cout << "\nA click to exit..." << std::endl;
485 // Wait for a blocking mouse click
487 }
488 return EXIT_SUCCESS;
489 } catch (const vpException &e) {
490 std::cout << "Catch an exception: " << e << std::endl;
491 return EXIT_FAILURE;
492 }
493}
494#else
495#include <iostream>
496
497int main()
498{
499 std::cout << "visp_me module or X11, GTK, GDI or OpenCV display "
500 "functionalities are required..."
501 << std::endl;
502 return EXIT_SUCCESS;
503}
504
505#endif
static const vpColor blue
Definition: vpColor.h:223
static const vpColor green
Definition: vpColor.h:220
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:129
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
Definition: vpDisplayGTK.h:135
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition: vpDisplayX.h:135
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void display(const vpImage< unsigned char > &I)
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
unsigned int getHeight() const
Definition: vpDisplay.h:240
static void flush(const vpImage< unsigned char > &I)
static void displayPoint(const vpImage< unsigned char > &I, const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1)
unsigned int getWidth() const
Definition: vpDisplay.h:245
This tracker is meant to track a blob (connex pixels with same gray level) on a vpImage.
Definition: vpDot2.h:127
error that can be emited by ViSP classes.
Definition: vpException.h:72
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:149
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
double get_u() const
Definition: vpImagePoint.h:262
void set_u(double u)
Definition: vpImagePoint.h:225
void set_v(double v)
Definition: vpImagePoint.h:236
double get_v() const
Definition: vpImagePoint.h:273
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1365
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1670
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:69
#define vpCTRACE
Definition: vpDebug.h:338
VISP_EXPORT double measureTimeMs()