Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
mbtEdgeTracking.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Example of model based tracking.
32 */
33
40
41#include <iostream>
42#include <visp3/core/vpConfig.h>
43
44#if (defined(VISP_HAVE_MODULE_MBT) && defined(VISP_HAVE_DISPLAY)) && \
45 (defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_OPENCV))
46
47#include <visp3/core/vpDebug.h>
48#include <visp3/core/vpHomogeneousMatrix.h>
49#include <visp3/core/vpIoTools.h>
50#include <visp3/core/vpMath.h>
51#include <visp3/gui/vpDisplayFactory.h>
52#include <visp3/io/vpImageIo.h>
53#include <visp3/io/vpParseArgv.h>
54#include <visp3/io/vpVideoReader.h>
55#include <visp3/mbt/vpMbEdgeTracker.h>
56
57#define GETOPTARGS "cCde:fhi:lm:n:opstvwx:"
58
59#ifdef ENABLE_VISP_NAMESPACE
60using namespace VISP_NAMESPACE_NAME;
61#endif
62
63void usage(const char *name, const char *badparam)
64{
65#if defined(VISP_HAVE_DATASET)
66#if VISP_HAVE_DATASET_VERSION >= 0x030600
67 std::string ext("png");
68#else
69 std::string ext("pgm");
70#endif
71#else
72 // We suppose that the user will download a recent dataset
73 std::string ext("png");
74#endif
75
76 fprintf(stdout, "\n\
77Example of tracking based on the 3D model.\n\
78\n\
79SYNOPSIS\n\
80 %s [-i <test image path>] [-x <config file>]\n\
81 [-m <model name>] [-n <initialisation file base name>] [-e <last frame index>]\n\
82 [-t] [-c] [-d] [-h] [-f] [-C] [-o] [-w] [-l] [-v] [-p] [-s]\n",
83 name);
84
85 fprintf(stdout, "\n\
86OPTIONS: \n\
87 -i <input image path> \n\
88 Set image input path.\n\
89 From this path read images \n\
90 \"mbt/cube/image%%04d.%s\". These \n\
91 images come from visp-images-x.y.z.tar.gz available \n\
92 on the ViSP website.\n\
93 Setting the VISP_INPUT_IMAGE_PATH environment\n\
94 variable produces the same behaviour than using\n\
95 this option.\n\
96\n\
97 -x <config file> \n\
98 Set the config file (the xml file) to use.\n\
99 The config file is used to specify the parameters of the tracker.\n\
100\n\
101 -m <model name> \n\
102 Specify the name of the file of the model\n\
103 The model can either be a vrml model (.wrl) or a .cao file.\n\
104\n\
105 -e <last frame index> \n\
106 Specify the index of the last frame. Once reached, the tracking is stopped\n\
107\n\
108 -s \n\
109 Enable step-by-step mode when click is allowed.\n\
110\n\
111 -f \n\
112 Do not use the vrml model, use the .cao one. These two models are \n\
113 equivalent and comes from ViSP-images-x.y.z.tar.gz available on the ViSP\n\
114 website. However, the .cao model allows to use the 3d model based tracker \n\
115 without Coin.\n\
116\n\
117 -C \n\
118 Track only the cube (not the cylinder). In this case the models files are\n\
119 cube.cao or cube.wrl instead of cube_and_cylinder.cao and \n\
120 cube_and_cylinder.wrl.\n\
121\n\
122 -n <initialisation file base name> \n\
123 Base name of the initialisation file. The file will be 'base_name'.init .\n\
124 This base name is also used for the Optional picture specifying where to \n\
125 click (a .ppm picture).\n\
126\n\
127 -t \n\
128 Turn off the display of the the moving edges. \n\
129\n\
130 -d \n\
131 Turn off the display.\n\
132\n\
133 -c\n\
134 Disable the mouse click. Useful to automate the \n\
135 execution of this program without human intervention.\n\
136\n\
137 -o\n\
138 Use Ogre3D for visibility tests.\n\
139\n\
140 -w\n\
141 When Ogre3D is enable [-o] show Ogre3D configuration dialog thatallows to set the renderer.\n\
142\n\
143 -l\n\
144 Use the scanline for visibility tests.\n\
145\n\
146 -v\n\
147 Compute covariance matrix.\n\
148\n\
149 -p\n\
150 Compute gradient projection error.\n\
151\n\
152 -h \n\
153 Print the help.\n\n",
154 ext.c_str());
155
156 if (badparam)
157 fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
158}
159
160bool getOptions(int argc, const char **argv, std::string &ipath, std::string &configFile, std::string &modelFile,
161 std::string &initFile, long &lastFrame, bool &displayFeatures, bool &click_allowed, bool &display,
162 bool &cao3DModel, bool &trackCylinder, bool &useOgre, bool &showOgreConfigDialog, bool &useScanline,
163 bool &computeCovariance, bool &projectionError, bool &step_by_step)
164{
165 const char *optarg_;
166 int c;
167 while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
168
169 switch (c) {
170 case 's':
171 step_by_step = true;
172 break;
173 case 'e':
174 lastFrame = atol(optarg_);
175 break;
176 case 'i':
177 ipath = optarg_;
178 break;
179 case 'x':
180 configFile = optarg_;
181 break;
182 case 'm':
183 modelFile = optarg_;
184 break;
185 case 'n':
186 initFile = optarg_;
187 break;
188 case 't':
189 displayFeatures = false;
190 break;
191 case 'f':
192 cao3DModel = true;
193 break;
194 case 'c':
195 click_allowed = false;
196 break;
197 case 'd':
198 display = false;
199 break;
200 case 'C':
201 trackCylinder = false;
202 break;
203 case 'o':
204 useOgre = true;
205 break;
206 case 'l':
207 useScanline = true;
208 break;
209 case 'w':
210 showOgreConfigDialog = true;
211 break;
212 case 'v':
213 computeCovariance = true;
214 break;
215 case 'p':
216 projectionError = true;
217 break;
218 case 'h':
219 usage(argv[0], nullptr);
220 return false;
221
222 default:
223 usage(argv[0], optarg_);
224 return false;
225 }
226 }
227
228 if ((c == 1) || (c == -1)) {
229 // standalone param or error
230 usage(argv[0], nullptr);
231 std::cerr << "ERROR: " << std::endl;
232 std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
233 return false;
234 }
235
236 return true;
237}
238
239int main(int argc, const char **argv)
240{
241#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
242 std::shared_ptr<vpDisplay> display;
243#else
244 vpDisplay *display = nullptr;
245#endif
246
247 int return_status;
248 try {
249 std::string env_ipath;
250 std::string opt_ipath;
251 std::string ipath;
252 std::string opt_configFile;
253 std::string configFile;
254 std::string opt_modelFile;
255 std::string modelFile;
256 std::string opt_initFile;
257 std::string initFile;
258 long opt_lastFrame = -1;
259 bool displayFeatures = true;
260 bool opt_click_allowed = true;
261 bool opt_display = true;
262 bool cao3DModel = false;
263 bool trackCylinder = true;
264 bool useOgre = false;
265 bool showOgreConfigDialog = false;
266 bool useScanline = false;
267 bool computeCovariance = false;
268 bool projectionError = false;
269 bool opt_step_by_step = false;
270 bool quit = false;
271
272#if defined(VISP_HAVE_DATASET)
273#if VISP_HAVE_DATASET_VERSION >= 0x030600
274 std::string ext("png");
275#else
276 std::string ext("pgm");
277#endif
278#else
279 // We suppose that the user will download a recent dataset
280 std::string ext("png");
281#endif
282
283 // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
284 // environment variable value
286
287 // Set the default input path
288 if (!env_ipath.empty())
289 ipath = env_ipath;
290
291 // Read the command line options
292 if (!getOptions(argc, argv, opt_ipath, opt_configFile, opt_modelFile, opt_initFile, opt_lastFrame, displayFeatures,
293 opt_click_allowed, opt_display, cao3DModel, trackCylinder, useOgre, showOgreConfigDialog,
294 useScanline, computeCovariance, projectionError, opt_step_by_step)) {
295 return EXIT_FAILURE;
296 }
297
298 // Test if an input path is set
299 if (opt_ipath.empty() && env_ipath.empty()) {
300 usage(argv[0], nullptr);
301 std::cerr << std::endl << "ERROR:" << std::endl;
302 std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
303 << " environment variable to specify the location of the " << std::endl
304 << " image path where test images are located." << std::endl
305 << std::endl;
306
307 return EXIT_FAILURE;
308 }
309
310 // Get the option values
311 if (!opt_ipath.empty())
312 ipath = vpIoTools::createFilePath(opt_ipath, "mbt/cube/image%04d." + ext);
313 else
314 ipath = vpIoTools::createFilePath(env_ipath, "mbt/cube/image%04d." + ext);
315
316 if (!opt_configFile.empty())
317 configFile = opt_configFile;
318 else if (!opt_ipath.empty())
319 configFile = vpIoTools::createFilePath(opt_ipath, "mbt/cube.xml");
320 else
321 configFile = vpIoTools::createFilePath(env_ipath, "mbt/cube.xml");
322
323 if (!opt_modelFile.empty()) {
324 modelFile = opt_modelFile;
325 }
326 else {
327 std::string modelFileCao;
328 std::string modelFileWrl;
329 if (trackCylinder) {
330 modelFileCao = "mbt/cube_and_cylinder.cao";
331 modelFileWrl = "mbt/cube_and_cylinder.wrl";
332 }
333 else {
334 modelFileCao = "mbt/cube.cao";
335 modelFileWrl = "mbt/cube.wrl";
336 }
337
338 if (!opt_ipath.empty()) {
339 if (cao3DModel) {
340 modelFile = vpIoTools::createFilePath(opt_ipath, modelFileCao);
341 }
342 else {
343#ifdef VISP_HAVE_COIN3D
344 modelFile = vpIoTools::createFilePath(opt_ipath, modelFileWrl);
345#else
346 std::cerr << "Coin is not detected in ViSP. Use the .cao model instead." << std::endl;
347 modelFile = vpIoTools::createFilePath(opt_ipath, modelFileCao);
348#endif
349 }
350 }
351 else {
352 if (cao3DModel) {
353 modelFile = vpIoTools::createFilePath(env_ipath, modelFileCao);
354 }
355 else {
356#ifdef VISP_HAVE_COIN3D
357 modelFile = vpIoTools::createFilePath(env_ipath, modelFileWrl);
358#else
359 std::cerr << "Coin is not detected in ViSP. Use the .cao model instead." << std::endl;
360 modelFile = vpIoTools::createFilePath(env_ipath, modelFileCao);
361#endif
362 }
363 }
364 }
365
366 if (!opt_initFile.empty())
367 initFile = opt_initFile;
368 else if (!opt_ipath.empty())
369 initFile = vpIoTools::createFilePath(opt_ipath, "mbt/cube");
370 else
371 initFile = vpIoTools::createFilePath(env_ipath, "mbt/cube");
372
374 vpVideoReader reader;
375
376 reader.setFileName(ipath);
377 try {
378 reader.open(I);
379 }
380 catch (...) {
381 std::cout << "Cannot open sequence: " << ipath << std::endl;
382 return EXIT_FAILURE;
383 }
384
385 if (opt_lastFrame > 1 && opt_lastFrame < reader.getLastFrameIndex())
386 reader.setLastFrameIndex(opt_lastFrame);
387
388 reader.acquire(I);
389
390 // initialise a display
391#ifndef VISP_HAVE_DISPLAY
392 opt_display = false;
393#endif
394 if (opt_display) {
395#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
396 display = vpDisplayFactory::createDisplay(I, 100, 100, "Test tracking");
397#else
398 display = vpDisplayFactory::allocateDisplay(I, 100, 100, "Test tracking");
399#endif
402 }
403
406
407 // Initialise the tracker: camera parameters, moving edge and KLT settings
409#if defined(VISP_HAVE_PUGIXML)
410 // From the xml file
411 tracker.loadConfigFile(configFile);
412#else
413 // Corresponding parameters manually set to have an example code
414 // By setting the parameters:
415 cam.initPersProjWithoutDistortion(547, 542, 338, 234);
416
417 vpMe me;
418 me.setMaskSize(5);
419 me.setMaskNumber(180);
420 me.setRange(7);
422 me.setThreshold(10);
423 me.setMu1(0.5);
424 me.setMu2(0.5);
425 me.setSampleStep(4);
426
427 tracker.setCameraParameters(cam);
428 tracker.setMovingEdge(me);
429
430 // Specify the clipping to use
431 tracker.setNearClippingDistance(0.01);
432 tracker.setFarClippingDistance(0.90);
433 tracker.setClipping(tracker.getClipping() | vpMbtPolygon::FOV_CLIPPING);
434 // tracker.setClipping(tracker.getClipping() | vpMbtPolygon::LEFT_CLIPPING |
435 // vpMbtPolygon::RIGHT_CLIPPING | vpMbtPolygon::UP_CLIPPING |
436 // vpMbtPolygon::DOWN_CLIPPING); // Equivalent to FOV_CLIPPING
437#endif
438
439 // Display the moving edges, see documentation for the signification of
440 // the colours
441 tracker.setDisplayFeatures(displayFeatures);
442
443 // Tells if the tracker has to use Ogre3D for visibility tests
444 tracker.setOgreVisibilityTest(useOgre);
445 if (useOgre)
446 tracker.setOgreShowConfigDialog(showOgreConfigDialog);
447
448 // Tells if the tracker has to use the scanline visibility tests
449 tracker.setScanLineVisibilityTest(useScanline);
450
451 // Tells if the tracker has to compute the covariance matrix
452 tracker.setCovarianceComputation(computeCovariance);
453
454 // Tells if the tracker has to compute the projection error
455 tracker.setProjectionErrorComputation(projectionError);
456
457 // Retrieve the camera parameters from the tracker
458 tracker.getCameraParameters(cam);
459
460 // Loop to position the cube
461 if (opt_display && opt_click_allowed) {
462 while (!vpDisplay::getClick(I, false)) {
464 vpDisplay::displayText(I, 15, 10, "click after positioning the object", vpColor::red);
466 }
467 }
468
469 // Load the 3D model (either a vrml file or a .cao file)
470 tracker.loadModel(modelFile);
471
472 // Initialise the tracker by clicking on the image
473 // This function looks for
474 // - a ./cube/cube.init file that defines the 3d coordinates (in meter,
475 // in the object basis) of the points used for the initialisation
476 // - a ./cube/cube.ppm file to display where the user have to click
477 // (Optional, set by the third parameter)
478 if (opt_display && opt_click_allowed) {
479 tracker.initClick(I, initFile, true);
480 tracker.getPose(cMo);
481 // display the 3D model at the given pose
482 tracker.display(I, cMo, cam, vpColor::red);
483 }
484 else {
485 vpHomogeneousMatrix cMoi(0.02044769891, 0.1101505452, 0.5078963719, 2.063603907, 1.110231561, -0.4392789872);
486 tracker.initFromPose(I, cMoi);
487 }
488
489 // track the model
490 tracker.track(I);
491 tracker.getPose(cMo);
492
493 if (opt_display)
495
496 while (!reader.end()) {
497 // acquire a new image
498 reader.acquire(I);
499 // display the image
500 if (opt_display)
502
503 // Test to reset the tracker
504 if (reader.getFrameIndex() == reader.getFirstFrameIndex() + 10) {
505 vpTRACE("Test reset tracker");
506 if (opt_display)
508 tracker.resetTracker();
509
510#if defined(VISP_HAVE_PUGIXML)
511 tracker.loadConfigFile(configFile);
512#else
513 // Corresponding parameters manually set to have an example code
514 // By setting the parameters:
515 cam.initPersProjWithoutDistortion(547, 542, 338, 234);
516
517 vpMe me;
518 me.setMaskSize(5);
519 me.setMaskNumber(180);
520 me.setRange(7);
522 me.setThreshold(10);
523 me.setMu1(0.5);
524 me.setMu2(0.5);
525 me.setSampleStep(4);
526
527 tracker.setCameraParameters(cam);
528 tracker.setMovingEdge(me);
529
530 // Specify the clipping to use
531 tracker.setNearClippingDistance(0.01);
532 tracker.setFarClippingDistance(0.90);
533 tracker.setClipping(tracker.getClipping() | vpMbtPolygon::FOV_CLIPPING);
534 // tracker.setClipping(tracker.getClipping() | vpMbtPolygon::LEFT_CLIPPING |
535 // vpMbtPolygon::RIGHT_CLIPPING | vpMbtPolygon::UP_CLIPPING |
536 // vpMbtPolygon::DOWN_CLIPPING); // Equivalent to FOV_CLIPPING
537#endif
538 tracker.loadModel(modelFile);
539 tracker.setCameraParameters(cam);
540 tracker.setOgreVisibilityTest(useOgre);
541 tracker.setScanLineVisibilityTest(useScanline);
542 tracker.setCovarianceComputation(computeCovariance);
543 tracker.setProjectionErrorComputation(projectionError);
544 tracker.initFromPose(I, cMo);
545 }
546
547 // Test to set an initial pose
548 if (reader.getFrameIndex() == reader.getFirstFrameIndex() + 50) {
549 cMo.buildFrom(0.0439540832, 0.0845870108, 0.5477322481, 2.179498458, 0.8611798108, -0.3491961946);
550 vpTRACE("Test set pose");
551 tracker.setPose(I, cMo);
552 // if (opt_display) {
553 // // display the 3D model
554 // tracker.display(I, cMo, cam, vpColor::darkRed);
555 // // display the frame
556 // vpDisplay::displayFrame (I, cMo, cam, 0.05);
561 // }
562 }
563
564 // track the object: stop tracking from frame 40 to 50
565 if (reader.getFrameIndex() - reader.getFirstFrameIndex() < 40 ||
566 reader.getFrameIndex() - reader.getFirstFrameIndex() >= 50) {
567 tracker.track(I);
568 tracker.getPose(cMo);
569 if (opt_display) {
570 // display the 3D model
571 tracker.display(I, cMo, cam, vpColor::darkRed);
572 // display the frame
573 vpDisplay::displayFrame(I, cMo, cam, 0.05);
574 }
575 }
576
577 if (opt_click_allowed && opt_display) {
578 vpDisplay::displayText(I, 20, I.getWidth() - 150, std::string("Mode: ") + (opt_step_by_step ? std::string("step-by-step") : std::string("continuous")), vpColor::red);
579 vpDisplay::displayText(I, 20, 10, "Right click to exit", vpColor::red);
580 vpDisplay::displayText(I, 40, 10, "Middle click to change mode", vpColor::red);
581 if (opt_step_by_step) {
582 vpDisplay::displayText(I, 60, 10, "Left click to process next image", vpColor::red);
583 }
585 if (vpDisplay::getClick(I, button, opt_step_by_step)) {
586 if (button == vpMouseButton::button3) {
587 quit = true;
588 }
589 else if (button == vpMouseButton::button2) {
590 opt_step_by_step = !opt_step_by_step;
591 }
592 }
593 }
594
595 if (computeCovariance) {
596 std::cout << "Covariance matrix: \n" << tracker.getCovarianceMatrix() << std::endl << std::endl;
597 }
598
599 if (projectionError) {
600 std::cout << "Projection error: " << tracker.getProjectionError() << std::endl << std::endl;
601 }
602
603 if (opt_display)
605 }
606
607 std::cout << "Reached last frame: " << reader.getFrameIndex() << std::endl;
608
609 if (opt_click_allowed && !quit) {
611 }
612 reader.close();
613 return_status = EXIT_SUCCESS;
614 }
615 catch (const vpException &e) {
616 std::cout << "Catch an exception: " << e << std::endl;
617 return_status = EXIT_FAILURE;
618 }
619#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
620 if (display) {
621 delete display;
622 display = nullptr;
623 }
624#endif
625 return return_status;
626}
627
628#elif !(defined(VISP_HAVE_MODULE_MBT) && defined(VISP_HAVE_DISPLAY))
629int main()
630{
631 std::cout << "Cannot run this example: visp_mbt, visp_gui modules are required." << std::endl;
632 return EXIT_SUCCESS;
633}
634#else
635int main()
636{
637 std::cout << "Cannot run this example: install Lapack, Eigen3 or OpenCV" << std::endl;
638 return EXIT_SUCCESS;
639}
640#endif
Generic class defining intrinsic camera parameters.
static const vpColor red
Definition vpColor.h:198
static const vpColor darkRed
Definition vpColor.h:199
Class that defines generic functionalities for display.
Definition vpDisplay.h:171
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void display(const vpImage< unsigned char > &I)
static void displayFrame(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, double size, const vpColor &color=vpColor::none, unsigned int thickness=1, const vpImagePoint &offset=vpImagePoint(0, 0), const std::string &frameName="", const vpColor &textColor=vpColor::black, const vpImagePoint &textOffset=vpImagePoint(15, 15))
static void flush(const vpImage< unsigned char > &I)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
error that can be emitted by ViSP classes.
Definition vpException.h:60
Implementation of an homogeneous matrix and operations on such kind of matrices.
Definition of the vpImage class member functions.
Definition vpImage.h:131
static std::string getViSPImagesDataPath()
static std::string createFilePath(const std::string &parent, const std::string &child)
Make the complete tracking of an object by using its CAD model.
Definition vpMe.h:143
void setMu1(const double &mu_1)
Definition vpMe.h:408
void setRange(const unsigned int &range)
Definition vpMe.h:438
void setLikelihoodThresholdType(const vpLikelihoodThresholdType likelihood_threshold_type)
Definition vpMe.h:531
void setMaskNumber(const unsigned int &mask_number)
Definition vpMe.cpp:555
void setThreshold(const double &threshold)
Definition vpMe.h:489
void setSampleStep(const double &sample_step)
Definition vpMe.h:445
void setMaskSize(const unsigned int &mask_size)
Definition vpMe.cpp:563
void setMu2(const double &mu_2)
Definition vpMe.h:415
@ NORMALIZED_THRESHOLD
Definition vpMe.h:154
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Class that enables to manipulate easily a video file or a sequence of images. As it inherits from the...
void setLastFrameIndex(const long last_frame)
long getLastFrameIndex()
void open(vpImage< vpRGBa > &I) VP_OVERRIDE
void setFileName(const std::string &filename)
long getFirstFrameIndex()
void close() VP_OVERRIDE
long getFrameIndex() const
void acquire(vpImage< vpRGBa > &I) VP_OVERRIDE
#define vpTRACE
Definition vpDebug.h:450
std::shared_ptr< vpDisplay > createDisplay()
Return a smart pointer vpDisplay specialization if a GUI library is available or nullptr otherwise.
vpDisplay * allocateDisplay()
Return a newly allocated vpDisplay specialization if a GUI library is available or nullptr otherwise.