Visual Servoing Platform version 3.6.0
Loading...
Searching...
No Matches
trackKltOpencv.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 <vector>
48
49#if defined(VISP_HAVE_MODULE_KLT) && (defined(VISP_HAVE_X11) || defined(VISP_HAVE_GTK) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV))
50
51#if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
52
53#include <visp3/core/vpImage.h>
54#include <visp3/core/vpIoTools.h>
55#include <visp3/gui/vpDisplayGDI.h>
56#include <visp3/gui/vpDisplayGTK.h>
57#include <visp3/gui/vpDisplayOpenCV.h>
58#include <visp3/gui/vpDisplayX.h>
59#include <visp3/io/vpImageIo.h>
60#include <visp3/io/vpParseArgv.h>
61#include <visp3/klt/vpKltOpencv.h>
62
63// List of allowed command line options
64#define GETOPTARGS "cdf:i:l:p:s:h"
65
66void usage(const char *name, const char *badparam, std::string ipath, std::string ppath, unsigned first,
67 unsigned last, unsigned step);
68bool getOptions(int argc, const char **argv, std::string &ipath, std::string &ppath, unsigned &first, unsigned &last,
69 unsigned &step, bool &click_allowed, bool &display);
91void usage(const char *name, const char *badparam, std::string ipath, std::string ppath, unsigned first,
92 unsigned last, unsigned step)
93{
94#if VISP_HAVE_DATASET_VERSION >= 0x030600
95 std::string ext("png");
96#else
97 std::string ext("pgm");
98#endif
99 fprintf(stdout, "\n\
100Example of KLT tracking using OpenCV library.\n\
101\n\
102SYNOPSIS\n\
103 %s [-i <test image path>] [-p <personal image path>]\n\
104 [-f <first image>] [-l <last image>] [-s <step>]\n\
105 [-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\". These \n\
114 images come from visp-images-x.y.z.tar.gz available \n\
115 on the ViSP website.\n\
116 Setting the VISP_INPUT_IMAGE_PATH environment\n\
117 variable produces the same behaviour than using\n\
118 this option.\n\
119 \n\
120 -p <personal image path> %s\n\
121 Specify a personal sequence containing images \n\
122 to process.\n\
123 By image sequence, we mean one file per image.\n\
124 Example : \"/Temp/visp-images/mire-2/image.%%04d.%s\"\n\
125 %%04d is for the image numbering.\n\
126 \n\
127 -f <first image> %u\n\
128 First image number of the sequence.\n\
129 \n\
130 -l <last image> %u\n\
131 Last image number of the sequence.\n\
132 \n\
133 -s <step> %u\n\
134 Step between two images.\n\
135\n\
136 -c\n\
137 Disable the mouse click. Useful to automate the \n\
138 execution of this program without human intervention.\n\
139\n\
140 -d \n\
141 Turn off the display.\n\
142\n\
143 -h\n\
144 Print the help.\n",
145 ipath.c_str(), ext.c_str(), ppath.c_str(), ext.c_str(), first, last, step);
146
147 if (badparam)
148 fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
149}
150
168bool getOptions(int argc, const char **argv, std::string &ipath, std::string &ppath, unsigned &first, unsigned &last,
169 unsigned &step, bool &click_allowed, bool &display)
170{
171 const char *optarg_;
172 int c;
173 while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
174
175 switch (c) {
176 case 'c':
177 click_allowed = false;
178 break;
179 case 'd':
180 display = false;
181 break;
182 case 'i':
183 ipath = optarg_;
184 break;
185 case 'p':
186 ppath = optarg_;
187 break;
188 case 'f':
189 first = (unsigned)atoi(optarg_);
190 break;
191 case 'l':
192 last = (unsigned)atoi(optarg_);
193 break;
194 case 's':
195 step = (unsigned)atoi(optarg_);
196 break;
197 case 'h':
198 usage(argv[0], NULL, ipath, ppath, first, last, step);
199 return false;
200 break;
201
202 default:
203 usage(argv[0], optarg_, ipath, ppath, first, last, step);
204 return false;
205 break;
206 }
207 }
208
209 if ((c == 1) || (c == -1)) {
210 // standalone param or error
211 usage(argv[0], NULL, ipath, ppath, first, last, step);
212 std::cerr << "ERROR: " << std::endl;
213 std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
214 return false;
215 }
216
217 return true;
218}
219
220int main(int argc, const char **argv)
221{
222 try {
223 std::string env_ipath;
224 std::string opt_ipath;
225 std::string ipath;
226 std::string opt_ppath;
227 std::string dirname;
228 std::string filename;
229 unsigned opt_first = 1;
230 unsigned opt_last = 500;
231 unsigned opt_step = 1;
232 bool opt_click_allowed = true;
233 bool opt_display = true;
234
235#if VISP_HAVE_DATASET_VERSION >= 0x030600
236 std::string ext("png");
237#else
238 std::string ext("pgm");
239#endif
240
241 // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
242 // environment variable value
244
245 // Set the default input path
246 if (!env_ipath.empty())
247 ipath = env_ipath;
248
249 // Read the command line options
250 if (getOptions(argc, argv, opt_ipath, opt_ppath, opt_first, opt_last, opt_step, opt_click_allowed,
251 opt_display) == false) {
252 return EXIT_FAILURE;
253 }
254
255 // Get the option values
256 if (!opt_ipath.empty())
257 ipath = opt_ipath;
258
259 // Compare ipath and env_ipath. If they differ, we take into account
260 // the input path comming from the command line option
261 if (!opt_ipath.empty() && !env_ipath.empty() && opt_ppath.empty()) {
262 if (ipath != env_ipath) {
263 std::cout << std::endl << "WARNING: " << std::endl;
264 std::cout << " Since -i <visp image path=" << ipath << "> "
265 << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
266 << " we skip the environment variable." << std::endl;
267 }
268 }
269
270 // Test if an input path is set
271 if (opt_ipath.empty() && env_ipath.empty() && opt_ppath.empty()) {
272 usage(argv[0], NULL, ipath, opt_ppath, opt_first, opt_last, opt_step);
273 std::cerr << std::endl << "ERROR:" << std::endl;
274 std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
275 << " environment variable to specify the location of the " << std::endl
276 << " image path where test images are located." << std::endl
277 << " Use -p <personal image path> option if you want to " << std::endl
278 << " use personal images." << std::endl
279 << std::endl;
280
281 return EXIT_FAILURE;
282 }
283
284 // Declare an image, this is a gray level image (unsigned char)
285 // it size is not defined yet, it will be defined when the image will
286 // read on the disk
287 vpImage<unsigned char> vpI; // This is a ViSP image used for display only
288 cv::Mat cvI;
289
290 unsigned iter = opt_first;
291 std::ostringstream s;
292 char cfilename[FILENAME_MAX];
293
294 if (opt_ppath.empty()) {
295
296 // Warning :
297 // The image sequence is not provided with the ViSP package
298 // therefore the program will return an error :
299 // !! couldn't read file visp-images/mire-2/image.0001.png
300 //
301 // ViSP dataset is available on the visp www site
302 // https://visp.inria.fr/download/.
303
304 // Set the path location of the image sequence
305 dirname = vpIoTools::createFilePath(ipath, "mire-2");
306
307 // Build the name of the image file
308
309 s.setf(std::ios::right, std::ios::adjustfield);
310 s << "image." << std::setw(4) << std::setfill('0') << iter << "." << ext;
311 filename = vpIoTools::createFilePath(dirname, s.str());
312 }
313 else {
314 snprintf(cfilename, FILENAME_MAX, opt_ppath.c_str(), iter);
315 filename = cfilename;
316 }
317
318 // Read the image named "filename", and put the bitmap into the image structure I.
319 // I is initialized to the correct size
320 //
321 // vpImageIo::read() may throw various exception if, for example,
322 // the file does not exist, or if the memory cannot be allocated
323 try {
324 std::cout << "Load: " << filename << std::endl;
325
326 // Load a ViSP image used for the display
327 vpImageIo::read(vpI, filename);
328 vpImageConvert::convert(vpI, cvI);
329 } catch (...) {
330 // If an exception is thrown by vpImageIo::read() it will result in the end of the program.
331 std::cerr << std::endl << "ERROR:" << std::endl;
332 std::cerr << " Cannot read " << filename << std::endl;
333 if (opt_ppath.empty()) {
334 std::cerr << " Check your -i " << ipath << " option " << std::endl
335 << " or VISP_INPUT_IMAGE_PATH environment variable." << std::endl;
336 }
337 else {
338 std::cerr << " Check your -p " << opt_ppath << " option " << std::endl;
339 }
340 return EXIT_FAILURE;
341 }
342
343// We open a window using either X11, GTK or GDI.
344#if defined(VISP_HAVE_X11)
345 vpDisplayX display;
346#elif defined(VISP_HAVE_GTK)
347 vpDisplayGTK display;
348#elif defined(VISP_HAVE_GDI)
349 vpDisplayGDI display;
350#elif defined(HAVE_OPENCV_HIGHGUI)
351 vpDisplayOpenCV display;
352#endif
353
354 if (opt_display) {
355 // Display size is automatically defined by the image (I) size
356 display.init(vpI, 100, 100, "Display...");
357 // Display the image
358 // The image class has a member that specify a pointer toward
359 // the display that has been initialized in the display declaration
360 // therefore is is no longer necessary to make a reference to the
361 // display variable.
363 vpDisplay::flush(vpI);
364 }
365
366 // KLT tracker
367 vpKltOpencv tracker;
368
369 // Event manager
370 // tracker.setOnNewFeature(&newFeature);
371 // tracker.setOnFeatureLost(&lostFeature);
372 // tracker.setIsFeatureValid(&isValid);
373
374 // Tracker parameters
375 tracker.setTrackerId(1);
376 // tracker.setOnMeasureFeature(&modifyFeature);
377 tracker.setMaxFeatures(200);
378 tracker.setWindowSize(10);
379 tracker.setQuality(0.01);
380 tracker.setMinDistance(15);
381 tracker.setHarrisFreeParameter(0.04);
382 tracker.setBlockSize(9);
383 tracker.setUseHarris(1);
384 tracker.setPyramidLevels(3);
385
386 // Point detection using Harris. In input we have an OpenCV IPL image
387 tracker.initTracking(cvI);
388
389 if (opt_display) {
390 // Plot the Harris points on ViSP image
391 tracker.display(vpI, vpColor::red);
392 }
393
394 // tracking is now initialized. We can start the tracker.
395 while (iter < opt_last) {
396 // set the new image name
397 if (opt_ppath.empty()) {
398 s.str("");
399 s << "image." << std::setw(4) << std::setfill('0') << iter << "." << ext;
400 filename = vpIoTools::createFilePath(dirname, s.str());
401 } else {
402 snprintf(cfilename, FILENAME_MAX, opt_ppath.c_str(), iter);
403 filename = cfilename;
404 }
405 // read the image
406 vpImageIo::read(vpI, filename);
407 vpImageConvert::convert(vpI, cvI);
408
409 // track the dot and returns its coordinates in the image
410 // results are given in float since many many are usually considered
411 //
412 // an exception is thrown by the track method if
413 // - dot is lost
414
415 if (opt_display) {
416 // Display the image
418 }
419
420 std::cout << "Tracking on image: " << filename << std::endl;
421 double time = vpTime::measureTimeMs();
422 // Tracking of the detected points
423 tracker.track(cvI);
424 std::cout << "Tracking performed in " << vpTime::measureTimeMs() - time << " ms" << std::endl;
425
426 if (opt_display) {
427 // Display the tracked points
428 tracker.display(vpI, vpColor::red);
429
430 vpDisplay::flush(vpI);
431 }
432 iter += opt_step;
433 }
434 if (opt_display && opt_click_allowed) {
435 std::cout << "\nA click to exit..." << std::endl;
436 // Wait for a blocking mouse click
438 }
439 return EXIT_SUCCESS;
440 } catch (const vpException &e) {
441 std::cout << "Catch an exception: " << e << std::endl;
442 return EXIT_FAILURE;
443 }
444}
445#else
446int main()
447{
448 std::cout << "You do not have OpenCV functionalities to display images..." << std::endl;
449 std::cout << "Tip:" << std::endl;
450 std::cout << "- Install OpenCV, configure again ViSP using cmake and build again this example" << std::endl;
451 return EXIT_SUCCESS;
452}
453#endif
454#else
455#include <iostream>
456
457int main()
458{
459 std::cout << "visp_klt module or X11, GTK, GDI or OpenCV display "
460 "functionalities are required..."
461 << std::endl;
462}
463
464#endif
static const vpColor red
Definition vpColor.h:211
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 flush(const vpImage< unsigned char > &I)
error that can be emitted by ViSP classes.
Definition vpException.h:59
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
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)
Wrapper for the KLT (Kanade-Lucas-Tomasi) feature tracker implemented in OpenCV. Thus to enable this ...
Definition vpKltOpencv.h:73
void setBlockSize(int blockSize)
void setQuality(double qualityLevel)
void track(const cv::Mat &I)
void setTrackerId(int tid)
void setHarrisFreeParameter(double harris_k)
void setMaxFeatures(int maxCount)
void initTracking(const cv::Mat &I, const cv::Mat &mask=cv::Mat())
void setMinDistance(double minDistance)
void display(const vpImage< unsigned char > &I, const vpColor &color=vpColor::red, unsigned int thickness=1)
void setUseHarris(int useHarrisDetector)
void setWindowSize(int winSize)
void setPyramidLevels(int pyrMaxLevel)
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
VISP_EXPORT double measureTimeMs()