Visual Servoing Platform version 3.6.0
Loading...
Searching...
No Matches
trackDot.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*****************************************************************************/
35
48#include <visp3/core/vpConfig.h>
49#include <visp3/core/vpDebug.h>
50
51#include <iomanip>
52#include <sstream>
53#include <stdio.h>
54#include <stdlib.h>
55
56#if defined(VISP_HAVE_MODULE_BLOB) && \
57 (defined(VISP_HAVE_X11) || defined(VISP_HAVE_GTK) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV))
58
59#include <visp3/blob/vpDot.h>
60#include <visp3/core/vpImage.h>
61#include <visp3/core/vpImagePoint.h>
62#include <visp3/core/vpIoTools.h>
63#include <visp3/gui/vpDisplayGDI.h>
64#include <visp3/gui/vpDisplayGTK.h>
65#include <visp3/gui/vpDisplayOpenCV.h>
66#include <visp3/gui/vpDisplayX.h>
67#include <visp3/io/vpImageIo.h>
68#include <visp3/io/vpParseArgv.h>
69
70// List of allowed command line options
71#define GETOPTARGS "cdf:hi:l:p:s:"
72
86void usage(const char *name, const char *badparam, std::string ipath, std::string ppath, unsigned first,
87 unsigned last, unsigned step)
88{
89#if VISP_HAVE_DATASET_VERSION >= 0x030600
90 std::string ext("png");
91#else
92 std::string ext("pgm");
93#endif
94 fprintf(stdout, "\n\
95Test dot tracking.\n\
96\n\
97SYNOPSIS\n\
98 %s [-i <test image path>] [-p <personal image path>]\n\
99 [-f <first image>] [-l <last image>] [-s <step>]\n\
100 [-c] [-d] [-h]\n", name);
101
102 fprintf(stdout, "\n\
103OPTIONS: Default\n\
104 -i <input image path> %s\n\
105 Set image input path.\n\
106 From this path read images \n\
107 \"mire-2/image.%%04d.%s\". These \n\
108 images come from visp-images-x.y.z.tar.gz available \n\
109 on the ViSP website.\n\
110 Setting the VISP_INPUT_IMAGE_PATH environment\n\
111 variable produces the same behaviour than using\n\
112 this option.\n\
113\n\
114 -p <personal image path> %s\n\
115 Specify a personal sequence containing images \n\
116 to process.\n\
117 By image sequence, we mean one file per image.\n\
118 Example : \"C:/Temp/visp-images/cube/image.%%04d.%s\"\n\
119 %%04d is for the image numbering.\n\
120\n\
121 -f <first image> %u\n\
122 First image number of the sequence.\n\
123\n\
124 -l <last image> %u\n\
125 Last image number of the sequence.\n\
126\n\
127 -s <step> %u\n\
128 Step between two images.\n\
129\n\
130 -c\n\
131 Disable the mouse click. Useful to automate the \n\
132 execution of this program without human intervention.\n\
133\n\
134 -d \n\
135 Turn off the display.\n\
136\n\
137 -h\n\
138 Print the help.\n",
139 ipath.c_str(), ext.c_str(), ppath.c_str(), ext.c_str(), first, last, step);
140
141 if (badparam)
142 fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
143}
161bool getOptions(int argc, const char **argv, std::string &ipath, std::string &ppath, unsigned &first, unsigned &last,
162 unsigned &step, bool &click_allowed, bool &display)
163{
164 const char *optarg_;
165 int c;
166 while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
167
168 switch (c) {
169 case 'c':
170 click_allowed = false;
171 break;
172 case 'd':
173 display = false;
174 break;
175 case 'i':
176 ipath = optarg_;
177 break;
178 case 'p':
179 ppath = optarg_;
180 break;
181 case 'f':
182 first = (unsigned)atoi(optarg_);
183 break;
184 case 'l':
185 last = (unsigned)atoi(optarg_);
186 break;
187 case 's':
188 step = (unsigned)atoi(optarg_);
189 break;
190 case 'h':
191 usage(argv[0], NULL, ipath, ppath, first, last, step);
192 return false;
193 break;
194
195 default:
196 usage(argv[0], optarg_, ipath, ppath, first, last, step);
197 return false;
198 break;
199 }
200 }
201
202 if ((c == 1) || (c == -1)) {
203 // standalone param or error
204 usage(argv[0], NULL, ipath, ppath, first, last, step);
205 std::cerr << "ERROR: " << std::endl;
206 std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
207 return false;
208 }
209
210 return true;
211}
212
213int main(int argc, const char **argv)
214{
215 try {
216 std::string env_ipath;
217 std::string opt_ipath;
218 std::string ipath;
219 std::string opt_ppath;
220 std::string dirname;
221 std::string filename;
222 unsigned int opt_first = 1;
223 unsigned int opt_last = 500;
224 unsigned int opt_step = 1;
225 bool opt_click_allowed = true;
226 bool opt_display = true;
227
228#if VISP_HAVE_DATASET_VERSION >= 0x030600
229 std::string ext("png");
230#else
231 std::string ext("pgm");
232#endif
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_last, opt_step, opt_click_allowed,
244 opt_display) == false) {
245 return EXIT_FAILURE;
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_last, 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 return EXIT_FAILURE;
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 an error :
291 // !! couldn't read file visp-images/mire-2/image.0001.png
292 //
293 // ViSP dataset is available on the visp www site
294 // https://visp.inria.fr/download/.
295
296 // Set the path location of the image sequence
297 dirname = vpIoTools::createFilePath(ipath, "mire-2");
298
299 // Build the name of the image file
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 }
304 else {
305 snprintf(cfilename, FILENAME_MAX, opt_ppath.c_str(), iter);
306 filename = cfilename;
307 }
308
309 // Read the image named "filename", and put the bitmap into the image structure I.
310 // I is initialized to the correct size
311 //
312 // vpImageIo::read() may throw various exception if, for example,
313 // the file does not exist, or if the memory cannot be allocated
314 try {
315 vpCTRACE << "Load: " << filename << std::endl;
316
317 vpImageIo::read(I, filename);
318 } catch (...) {
319 // If an exception is thrown by vpImageIo::read() it will result in the end of the program.
320 std::cerr << std::endl << "ERROR:" << std::endl;
321 std::cerr << " Cannot read " << filename << std::endl;
322 if (opt_ppath.empty()) {
323 std::cerr << " Check your -i " << ipath << " option " << std::endl
324 << " or VISP_INPUT_IMAGE_PATH environment variable." << std::endl;
325 }
326 else {
327 std::cerr << " Check your -p " << opt_ppath << " option " << std::endl;
328 }
329 return EXIT_FAILURE;
330 }
331
332// We open a window using either X11, GTK or GDI.
333#if defined(VISP_HAVE_X11)
334 vpDisplayX display;
335#elif defined(VISP_HAVE_GTK)
336 vpDisplayGTK display;
337#elif defined(VISP_HAVE_GDI)
338 vpDisplayGDI display;
339#elif defined(HAVE_OPENCV_HIGHGUI)
340 vpDisplayOpenCV display;
341#endif
342
343 if (opt_display) {
344 // Display size is automatically defined by the image (I) size
345 display.init(I, 100, 100, "Display...");
346 // Display the image
347 // The image class has a member that specify a pointer toward
348 // the display that has been initialized in the display declaration
349 // therefore is is no longer necessary to make a reference to the
350 // display variable.
353 }
354
355 // by using setGraphics, we request to see the all the pixel of the dot
356 vpDot d;
357 if (opt_display) {
358 // by using setGraphics, we request to see the all the pixel of the dot
359 // in green on the screen.
360 // It uses the overlay image plane.
361 // The default of this setting is that it is time consuming
362 d.setGraphics(true);
363 } else {
364 d.setGraphics(false);
365 }
366 // we also request to compute the dot moment m00, m10, m01, m11, m20, m02
367 d.setComputeMoments(true);
368 d.setConnexity(vpDot::CONNEXITY_8);
369
370 if (opt_display && opt_click_allowed) {
371 // tracking is initalized
372 // if no other parameters are given to the iniTracking(..) method
373 // a right mouse click on the dot is expected
374 std::cout << "Click on a white dot you want to track..." << std::endl;
375 d.initTracking(I);
376 } else {
377 // dot location can also be specified explicitly in the
378 // initTracking method : d.initTracking(I,ip) where ip is the
379 // image point from which the dot is searched
380 vpImagePoint ip;
381 ip.set_u(160);
382 ip.set_v(212);
383 d.initTracking(I, ip);
384 }
385
386 vpImagePoint cog;
387 while (iter < opt_last) {
388 // set the new image name
389 if (opt_ppath.empty()) {
390 s.str("");
391 s << "image." << std::setw(4) << std::setfill('0') << iter << "." << ext;
392 filename = vpIoTools::createFilePath(dirname, s.str());
393 } else {
394 snprintf(cfilename, FILENAME_MAX, opt_ppath.c_str(), iter);
395 filename = cfilename;
396 }
397 // read the image
398 std::cout << "read: " << filename << std::endl;
399 vpImageIo::read(I, filename);
400
401 if (opt_display) {
402 // Display the image
404 }
405 std::cout << "Tracking on image: " << filename << std::endl;
406
407 // track the dot
408 double time = vpTime::measureTimeMs();
409 d.track(I);
410
411 std::cout << "COG (" << vpTime::measureTimeMs() - time << " ms): " << std::endl;
412 cog = d.getCog();
413 std::cout << cog.get_u() << " " << cog.get_v() << std::endl;
414 std::cout << "Size:" << std::endl;
415 std::cout << " w: " << d.getWidth() << " h: " << d.getHeight() << std::endl;
416 std::cout << "Area: " << d.getArea() << std::endl;
417 std::cout << "Centered normalized moments nij:" << std::endl;
418 std::cout << " n20: " << d.get_nij()[0] << std::endl;
419 std::cout << " n11: " << d.get_nij()[1] << std::endl;
420 std::cout << " n02: " << d.get_nij()[2] << std::endl;
421
422 if (0) {
423 std::list<vpImagePoint> edges = d.getEdges();
424 std::list<vpImagePoint>::const_iterator it;
425 for (it = edges.begin(); it != edges.end(); ++it) {
427 }
428 }
429
430 if (opt_display) {
431 // display a red cross (size 10) in the image at the dot center
432 // of gravity location
434 // flush the X11 buffer
436 }
437 iter += opt_step;
438 }
439
440 if (opt_display && opt_click_allowed) {
441 std::cout << "\nA click to exit..." << std::endl;
442 // Wait for a blocking mouse click
444 }
445 return EXIT_SUCCESS;
446 } catch (const vpException &e) {
447 std::cout << "Catch an exception: " << e << std::endl;
448 return EXIT_FAILURE;
449 }
450}
451#else
452#include <iostream>
453
454int main()
455{
456 std::cout << "visp_blob module or X11, GTK, GDI or OpenCV display "
457 "functionalities are required..."
458 << std::endl;
459 return EXIT_SUCCESS;
460}
461
462#endif
static const vpColor red
Definition vpColor.h:211
static const vpColor blue
Definition vpColor.h:217
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 dot (connected pixels with same gray level) on a vpImage.
Definition vpDot.h:112
@ CONNEXITY_8
Definition vpDot.h:120
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()