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