Visual Servoing Platform version 3.6.0
Loading...
Searching...
No Matches
trackDot2WithAutoDetection.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 * Test auto detection of dots.
33 *
34*****************************************************************************/
47#include <visp3/core/vpConfig.h>
48#include <visp3/core/vpDebug.h>
49
50#include <iomanip>
51#include <sstream>
52#include <stdio.h>
53#include <stdlib.h>
54
55#if defined(VISP_HAVE_MODULE_BLOB) && \
56 (defined(VISP_HAVE_X11) || defined(VISP_HAVE_GTK) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV))
57
58#include <visp3/blob/vpDot2.h>
59#include <visp3/core/vpImage.h>
60#include <visp3/core/vpImagePoint.h>
61#include <visp3/core/vpIoTools.h>
62#include <visp3/gui/vpDisplayGDI.h>
63#include <visp3/gui/vpDisplayGTK.h>
64#include <visp3/gui/vpDisplayOpenCV.h>
65#include <visp3/gui/vpDisplayX.h>
66#include <visp3/io/vpImageIo.h>
67#include <visp3/io/vpParseArgv.h>
68
69// List of allowed command line options
70#define GETOPTARGS "cdi:p:f:l:s:S:G:E:h"
71
89void usage(const char *name, const char *badparam, std::string ipath, std::string ppath, unsigned first,
90 unsigned last, unsigned step, double sizePrecision, double grayLevelPrecision,
91 double ellipsoidShapePrecision)
92{
93#if VISP_HAVE_DATASET_VERSION >= 0x030600
94 std::string ext("png");
95#else
96 std::string ext("pgm");
97#endif
98 fprintf(stdout, "\n\
99Test auto detection of dots using vpDot2.\n\
100 \n\
101SYNOPSIS\n\
102 %s [-i <input image path>] [-p <personal image path>]\n\
103 [-f <first image>] [-l <last image>] [-s <step>] \n\
104 [-S <size precision>] [-G <gray level precision>]\n\
105 [-E <ellipsoid shape precision>] [-c] [-d] [-h]\n",
106 name);
107
108 fprintf(stdout, "\n\
109OPTIONS: Default\n\
110 -i <input image path> %s\n\
111 Set image input path.\n\
112 From this path read images \n\
113 \"mire-2/image.%%04d.%s\"\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 The format is selected by analysing the filename extension.\n\
122 Example : \"/Temp/visp-images/mire-2/image.%%04d.%s\"\n\
123 %%04d is for the image numbering.\n\
124 \n\
125 -f <first image> %u\n\
126 First image number of the sequence.\n\
127 \n\
128 -l <last image> %u\n\
129 Last image number of the sequence.\n\
130 \n\
131 -s <step> %u\n\
132 Step between two images.\n\
133 \n\
134 -S <size precision> %f\n\
135 Precision of the size of the dot. \n\
136 It is a double precision float witch value is in ]0,1].\n\
137 1 means full precision, the sizes (width, heigth, surface) \n\
138 of the dots must the same, whereas values close to 0 \n\
139 show a very bad precision.\n\
140\n\
141 -G <gray level precision> %f\n\
142 Precision of the gray level of the dot. \n\
143 It is a double precision float witch value is in ]0,1].\n\
144 1 means full precision, the gray level must the same in \n\
145 the wall dot, whereas values close to 0 \n\
146 show a very bad precision.\n\
147\n\
148 -E <ellipsoid shape precision> %f\n\
149 Precision of the ellipsoid shape of the dot. \n\
150 It is a double precision float witch value is in [0,1].\n\
151 1 means full precision, the shape should be a perfect ellipsoid,\n\
152 whereas values close to 0 show a very bad precision.\n\
153 0 means the shape of dots is not tested \n\
154\n",
155 ipath.c_str(), ext.c_str(), ppath.c_str(), ext.c_str(), first, last, step, sizePrecision, grayLevelPrecision,
156 ellipsoidShapePrecision);
157
158 fprintf(stdout, "\
159 -c\n\
160 Disable the mouse click. Useful to automate the \n\
161 execution of this program without human intervention.\n\
162 \n\
163 -d \n\
164 Turn off the display.\n\
165 \n\
166 -h\n\
167 Print the help.\n");
168
169 if (badparam)
170 fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
171}
192bool getOptions(int argc, const char **argv, std::string &ipath, std::string &ppath, unsigned &first, unsigned &last,
193 unsigned &step, double &sizePrecision, double &grayLevelPrecision, double &ellipsoidShapePrecision,
194 bool &click_allowed, bool &display)
195{
196 const char *optarg_;
197 int c;
198 while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
199
200 switch (c) {
201 case 'c':
202 click_allowed = false;
203 break;
204 case 'd':
205 display = false;
206 break;
207 case 'i':
208 ipath = optarg_;
209 break;
210 case 'p':
211 ppath = optarg_;
212 break;
213 case 'f':
214 first = (unsigned)atoi(optarg_);
215 break;
216 case 'l':
217 last = (unsigned)atoi(optarg_);
218 break;
219 case 's':
220 step = (unsigned)atoi(optarg_);
221 break;
222 case 'S':
223 sizePrecision = atof(optarg_);
224 break;
225 case 'G':
226 grayLevelPrecision = atof(optarg_);
227 break;
228 case 'E':
229 ellipsoidShapePrecision = atof(optarg_);
230 break;
231 case 'h':
232 usage(argv[0], NULL, ipath, ppath, first, last, step, sizePrecision, grayLevelPrecision,
233 ellipsoidShapePrecision);
234 return false;
235 break;
236
237 default:
238 usage(argv[0], optarg_, ipath, ppath, first, last, step, sizePrecision, grayLevelPrecision,
239 ellipsoidShapePrecision);
240 return false;
241 break;
242 }
243 }
244
245 if ((c == 1) || (c == -1)) {
246 // standalone param or error
247 usage(argv[0], NULL, ipath, ppath, first, last, step, sizePrecision, grayLevelPrecision,
248 ellipsoidShapePrecision);
249 std::cerr << "ERROR: " << std::endl;
250 std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
251 return false;
252 }
253
254 return true;
255}
256
257int main(int argc, const char **argv)
258{
259 try {
260 std::string env_ipath;
261 std::string opt_ipath;
262 std::string ipath;
263 std::string opt_ppath;
264 std::string dirname;
265 std::string filename;
266 unsigned opt_first = 1;
267 unsigned opt_last = 10;
268 unsigned opt_step = 1;
269 double opt_sizePrecision = 0.65;
270 double opt_grayLevelPrecision = 0.85;
271 double opt_ellipsoidShapePrecision = 0.8;
272 bool opt_click_allowed = true;
273 bool opt_display = true;
274
275#if VISP_HAVE_DATASET_VERSION >= 0x030600
276 std::string ext("png");
277#else
278 std::string ext("pgm");
279#endif
280
281 // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
282 // environment variable value
284
285 // Set the default input path
286 if (!env_ipath.empty())
287 ipath = env_ipath;
288
289 // Read the command line options
290 if (getOptions(argc, argv, opt_ipath, opt_ppath, opt_first, opt_last, opt_step, opt_sizePrecision,
291 opt_grayLevelPrecision, opt_ellipsoidShapePrecision, opt_click_allowed, opt_display) == false) {
292 return EXIT_FAILURE;
293 }
294
295 // Get the option values
296 if (!opt_ipath.empty())
297 ipath = opt_ipath;
298
299 // Compare ipath and env_ipath. If they differ, we take into account
300 // the input path comming from the command line option
301 if (!opt_ipath.empty() && !env_ipath.empty() && opt_ppath.empty()) {
302 if (ipath != env_ipath) {
303 std::cout << std::endl << "WARNING: " << std::endl;
304 std::cout << " Since -i <visp image path=" << ipath << "> "
305 << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
306 << " we skip the environment variable." << std::endl;
307 }
308 }
309
310 // Test if an input path is set
311 if (opt_ipath.empty() && env_ipath.empty()) {
312 usage(argv[0], NULL, ipath, opt_ppath, opt_first, opt_last, opt_step, opt_sizePrecision,
313 opt_grayLevelPrecision, opt_ellipsoidShapePrecision);
314 std::cerr << std::endl << "ERROR:" << std::endl;
315 std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
316 << " environment variable to specify the location of the " << std::endl
317 << " image path where test images are located." << std::endl
318 << std::endl
319 << " Use -p <personal image path> option if you want to " << std::endl
320 << " use personal images." << std::endl;
321 return EXIT_FAILURE;
322 }
323
324 // Declare an image, this is a gray level image (unsigned char)
325 // it size is not defined yet, it will be defined when the image will
326 // read on the disk
328 std::ostringstream s;
329 char cfilename[FILENAME_MAX];
330 unsigned iter = opt_first; // Image number
331
332 if (opt_ppath.empty()) {
333
334 // Warning :
335 // The image sequence is not provided with the ViSP package
336 // therefore the program will return an error :
337 // !! couldn't read file visp-images/mire-2/image.0001.png
338 //
339 // ViSP dataset is available on the visp www site
340 // https://visp.inria.fr/download/.
341
342 // Set the path location of the image sequence
343 dirname = vpIoTools::createFilePath(ipath, "mire-2");
344
345 // Build the name of the image file
346
347 s.setf(std::ios::right, std::ios::adjustfield);
348 s << "image." << std::setw(4) << std::setfill('0') << iter << "." << ext;
349 filename = vpIoTools::createFilePath(dirname, s.str());
350 } else {
351 snprintf(cfilename, FILENAME_MAX, opt_ppath.c_str(), iter);
352 filename = cfilename;
353 }
354 // Read the image named "filename", and put the bitmap into the image structure I.
355 // I is initialized to the correct size
356 //
357 // vpImageIo::read() may throw various exception if, for example,
358 // the file does not exist, or if the memory cannot be allocated
359 try {
360 vpCTRACE << "Load: " << filename << std::endl;
361
362 vpImageIo::read(I, filename);
363 } catch (...) {
364 // If an exception is thrown by vpImageIo::read() it will result in the end of the program.
365 std::cerr << std::endl << "ERROR:" << std::endl;
366 std::cerr << " Cannot read " << filename << std::endl;
367 if (opt_ppath.empty()) {
368 std::cerr << " Check your -i " << ipath << " option " << std::endl
369 << " or VISP_INPUT_IMAGE_PATH environment variable." << std::endl;
370 }
371 else {
372 std::cerr << " Check your -p " << opt_ppath << " option " << std::endl;
373 }
374 return EXIT_FAILURE;
375 }
376
377// We open a window using either GTK, X11 or GDI.
378#if defined(VISP_HAVE_GTK)
379 vpDisplayGTK display;
380#elif defined(VISP_HAVE_X11)
381 vpDisplayX display;
382#elif defined(VISP_HAVE_GDI)
383 vpDisplayGDI display;
384#elif defined(HAVE_OPENCV_HIGHGUI)
385 vpDisplayOpenCV display;
386#endif
387
388 if (opt_display) {
389 // Display size is automatically defined by the image (I) size
390 display.init(I, 100, 100, "Display...");
391 // Display the image
392 // The image class has a member that specify a pointer toward
393 // the display that has been initialized in the display declaration
394 // therefore is is no longer necessary to make a reference to the
395 // display variable.
398 }
399
400 // Dot declaration
401 vpDot2 d;
402
403 d.setGraphics(true);
404 if (opt_click_allowed & opt_display) {
405 d.setGrayLevelPrecision(opt_grayLevelPrecision);
406
407 std::cout << "Please click on a dot to initialize detection" << std::endl;
408
409 d.initTracking(I);
410 if (opt_display) {
411 vpImagePoint cog;
412 cog = d.getCog();
415 }
416 d.setSizePrecision(opt_sizePrecision);
417 d.setEllipsoidShapePrecision(opt_ellipsoidShapePrecision);
418 printf("Dot characteristics: \n");
419 printf(" width : %lf\n", d.getWidth());
420 printf(" height: %lf\n", d.getHeight());
421 printf(" area: %lf\n", d.getArea());
422 printf(" gray level min: %u\n", d.getGrayLevelMin());
423 printf(" gray level max: %u\n", d.getGrayLevelMax());
424 printf(" grayLevelPrecision: %lf\n", d.getGrayLevelPrecision());
425 printf(" sizePrecision: %lf\n", d.getSizePrecision());
426 printf(" ellipsoidShapePrecision: %lf\n", d.getEllipsoidShapePrecision());
427 } else {
428 // Set dot characteristics for the auto detection
429 d.setGraphics(true);
430 d.setWidth(15.0);
431 d.setHeight(12.0);
432 d.setArea(124);
433 d.setGrayLevelMin(164);
434 d.setGrayLevelMax(255);
435 d.setGrayLevelPrecision(opt_grayLevelPrecision);
436 d.setSizePrecision(opt_sizePrecision);
437 d.setEllipsoidShapePrecision(opt_ellipsoidShapePrecision);
438 }
439
440 while (iter < opt_last) {
441 // set the new image name
442
443 if (opt_ppath.empty()) {
444
445 s.str("");
446 s << "image." << std::setw(4) << std::setfill('0') << iter << "." << ext;
447 filename = vpIoTools::createFilePath(dirname, s.str());
448 } else {
449 snprintf(cfilename, FILENAME_MAX, opt_ppath.c_str(), iter);
450 filename = cfilename;
451 }
452 // read the image
453 vpImageIo::read(I, filename);
454
455 if (opt_display) {
456 // Display the image
458 }
459
460 std::cout << "Search dots in image" << filename << std::endl;
461 std::list<vpDot2> list_d;
462 d.searchDotsInArea(I, 0, 0, I.getWidth(), I.getHeight(), list_d);
463
464 if (list_d.empty()) {
465 std::cout << "Dot auto detection did not work." << std::endl;
466 return EXIT_FAILURE;
467 }
468 else {
469 std::cout << std::endl << list_d.size() << " dots are detected" << std::endl;
470
471 if (opt_display) {
472 int i = 0;
473 // Parse all founded dots for display
474 for (std::list<vpDot2>::const_iterator it = list_d.begin(); it != list_d.end(); ++it) {
475 vpImagePoint cog = (*it).getCog();
476
477 std::cout << "Dot " << i++ << " : " << cog.get_u() << " " << cog.get_v() << std::endl;
478
480 }
482 }
483 }
484
485 // If click is allowed, wait for a mouse click to launch the next
486 // iteration
487 if (opt_display && opt_click_allowed) {
488 std::cout << "\nA click to continue..." << std::endl;
489 // Wait for a blocking mouse click
491 }
492
493 iter += opt_step;
494 }
495 if (opt_display && opt_click_allowed) {
496 std::cout << "\nA click to exit..." << std::endl;
497 // Wait for a blocking mouse click
499 }
500
501 return EXIT_SUCCESS;
502 } catch (const vpException &e) {
503 std::cout << "Catch an exception: " << e << std::endl;
504 return EXIT_FAILURE;
505 }
506}
507#else
508#include <iostream>
509
510int main()
511{
512 std::cout << "visp_me module or X11, GTK, GDI or OpenCV display "
513 "functionalities are required..."
514 << std::endl;
515 return EXIT_SUCCESS;
516}
517
518#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)
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
double get_v() const
Definition of the vpImage class member functions.
Definition vpImage.h:135
unsigned int getWidth() const
Definition vpImage.h:242
unsigned int getHeight() const
Definition vpImage.h:184
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