Example of model based tracking on an image sequence containing a cube.
Example of model based tracking on an image sequence containing a cube.
#include <iostream>
#include <visp3/core/vpConfig.h>
#if (defined(VISP_HAVE_MODULE_MBT) && defined(VISP_HAVE_DISPLAY)) && \
(defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_OPENCV))
#include <visp3/core/vpDebug.h>
#include <visp3/core/vpHomogeneousMatrix.h>
#include <visp3/core/vpIoTools.h>
#include <visp3/core/vpMath.h>
#include <visp3/gui/vpDisplayFactory.h>
#include <visp3/io/vpImageIo.h>
#include <visp3/io/vpParseArgv.h>
#include <visp3/io/vpVideoReader.h>
#include <visp3/mbt/vpMbEdgeTracker.h>
#define GETOPTARGS "cCde:fhi:lm:n:opstvwx:"
#ifdef ENABLE_VISP_NAMESPACE
#endif
void usage(const char *name, const char *badparam)
{
#if defined(VISP_HAVE_DATASET)
#if VISP_HAVE_DATASET_VERSION >= 0x030600
std::string ext("png");
#else
std::string ext("pgm");
#endif
#else
std::string ext("png");
#endif
fprintf(stdout, "\n\
Example of tracking based on the 3D model.\n\
\n\
SYNOPSIS\n\
%s [-i <test image path>] [-x <config file>]\n\
[-m <model name>] [-n <initialisation file base name>] [-e <last frame index>]\n\
[-t] [-c] [-d] [-h] [-f] [-C] [-o] [-w] [-l] [-v] [-p] [-s]\n",
name);
fprintf(stdout, "\n\
OPTIONS: \n\
-i <input image path> \n\
Set image input path.\n\
From this path read images \n\
\"mbt/cube/image%%04d.%s\". These \n\
images come from visp-images-x.y.z.tar.gz available \n\
on the ViSP website.\n\
Setting the VISP_INPUT_IMAGE_PATH environment\n\
variable produces the same behaviour than using\n\
this option.\n\
\n\
-x <config file> \n\
Set the config file (the xml file) to use.\n\
The config file is used to specify the parameters of the tracker.\n\
\n\
-m <model name> \n\
Specify the name of the file of the model\n\
The model can either be a vrml model (.wrl) or a .cao file.\n\
\n\
-e <last frame index> \n\
Specify the index of the last frame. Once reached, the tracking is stopped\n\
\n\
-s \n\
Enable step-by-step mode when click is allowed.\n\
\n\
-f \n\
Do not use the vrml model, use the .cao one. These two models are \n\
equivalent and comes from ViSP-images-x.y.z.tar.gz available on the ViSP\n\
website. However, the .cao model allows to use the 3d model based tracker \n\
without Coin.\n\
\n\
-C \n\
Track only the cube (not the cylinder). In this case the models files are\n\
cube.cao or cube.wrl instead of cube_and_cylinder.cao and \n\
cube_and_cylinder.wrl.\n\
\n\
-n <initialisation file base name> \n\
Base name of the initialisation file. The file will be 'base_name'.init .\n\
This base name is also used for the Optional picture specifying where to \n\
click (a .ppm picture).\n\
\n\
-t \n\
Turn off the display of the the moving edges. \n\
\n\
-d \n\
Turn off the display.\n\
\n\
-c\n\
Disable the mouse click. Useful to automate the \n\
execution of this program without human intervention.\n\
\n\
-o\n\
Use Ogre3D for visibility tests.\n\
\n\
-w\n\
When Ogre3D is enable [-o] show Ogre3D configuration dialog thatallows to set the renderer.\n\
\n\
-l\n\
Use the scanline for visibility tests.\n\
\n\
-v\n\
Compute covariance matrix.\n\
\n\
-p\n\
Compute gradient projection error.\n\
\n\
-h \n\
Print the help.\n\n",
ext.c_str());
if (badparam)
fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
}
bool getOptions(int argc, const char **argv, std::string &ipath, std::string &configFile, std::string &modelFile,
std::string &initFile, long &lastFrame, bool &displayFeatures, bool &click_allowed, bool &display,
bool &cao3DModel, bool &trackCylinder, bool &useOgre, bool &showOgreConfigDialog, bool &useScanline,
bool &computeCovariance, bool &projectionError, bool &step_by_step)
{
const char *optarg_;
int c;
switch (c) {
case 's':
step_by_step = true;
break;
case 'e':
lastFrame = atol(optarg_);
break;
case 'i':
ipath = optarg_;
break;
case 'x':
configFile = optarg_;
break;
case 'm':
modelFile = optarg_;
break;
case 'n':
initFile = optarg_;
break;
case 't':
displayFeatures = false;
break;
case 'f':
cao3DModel = true;
break;
case 'c':
click_allowed = false;
break;
case 'd':
display = false;
break;
case 'C':
trackCylinder = false;
break;
case 'o':
useOgre = true;
break;
case 'l':
useScanline = true;
break;
case 'w':
showOgreConfigDialog = true;
break;
case 'v':
computeCovariance = true;
break;
case 'p':
projectionError = true;
break;
case 'h':
usage(argv[0], nullptr);
return false;
default:
usage(argv[0], optarg_);
return false;
}
}
if ((c == 1) || (c == -1)) {
usage(argv[0], nullptr);
std::cerr << "ERROR: " << std::endl;
std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
return false;
}
return true;
}
int main(int argc, const char **argv)
{
#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
std::shared_ptr<vpDisplay> display;
#else
#endif
int return_status;
try {
std::string env_ipath;
std::string opt_ipath;
std::string ipath;
std::string opt_configFile;
std::string configFile;
std::string opt_modelFile;
std::string modelFile;
std::string opt_initFile;
std::string initFile;
long opt_lastFrame = -1;
bool displayFeatures = true;
bool opt_click_allowed = true;
bool opt_display = true;
bool cao3DModel = false;
bool trackCylinder = true;
bool useOgre = false;
bool showOgreConfigDialog = false;
bool useScanline = false;
bool computeCovariance = false;
bool projectionError = false;
bool opt_step_by_step = false;
bool quit = false;
#if defined(VISP_HAVE_DATASET)
#if VISP_HAVE_DATASET_VERSION >= 0x030600
std::string ext("png");
#else
std::string ext("pgm");
#endif
#else
std::string ext("png");
#endif
if (!env_ipath.empty())
ipath = env_ipath;
if (!getOptions(argc, argv, opt_ipath, opt_configFile, opt_modelFile, opt_initFile, opt_lastFrame, displayFeatures,
opt_click_allowed, opt_display, cao3DModel, trackCylinder, useOgre, showOgreConfigDialog,
useScanline, computeCovariance, projectionError, opt_step_by_step)) {
return EXIT_FAILURE;
}
if (opt_ipath.empty() && env_ipath.empty()) {
usage(argv[0], nullptr);
std::cerr << std::endl << "ERROR:" << std::endl;
std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
<< " environment variable to specify the location of the " << std::endl
<< " image path where test images are located." << std::endl
<< std::endl;
return EXIT_FAILURE;
}
if (!opt_ipath.empty())
else
if (!opt_configFile.empty())
configFile = opt_configFile;
else if (!opt_ipath.empty())
else
if (!opt_modelFile.empty()) {
modelFile = opt_modelFile;
}
else {
std::string modelFileCao;
std::string modelFileWrl;
if (trackCylinder) {
modelFileCao = "mbt/cube_and_cylinder.cao";
modelFileWrl = "mbt/cube_and_cylinder.wrl";
}
else {
modelFileCao = "mbt/cube.cao";
modelFileWrl = "mbt/cube.wrl";
}
if (!opt_ipath.empty()) {
if (cao3DModel) {
}
else {
#ifdef VISP_HAVE_COIN3D
#else
std::cerr << "Coin is not detected in ViSP. Use the .cao model instead." << std::endl;
#endif
}
}
else {
if (cao3DModel) {
}
else {
#ifdef VISP_HAVE_COIN3D
#else
std::cerr << "Coin is not detected in ViSP. Use the .cao model instead." << std::endl;
#endif
}
}
}
if (!opt_initFile.empty())
initFile = opt_initFile;
else if (!opt_ipath.empty())
else
try {
}
catch (...) {
std::cout << "Cannot open sequence: " << ipath << std::endl;
return EXIT_FAILURE;
}
#ifndef VISP_HAVE_DISPLAY
opt_display = false;
#endif
if (opt_display) {
#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
#else
#endif
}
#if defined(VISP_HAVE_PUGIXML)
tracker.loadConfigFile(configFile);
#else
cam.initPersProjWithoutDistortion(547, 542, 338, 234);
tracker.setNearClippingDistance(0.01);
tracker.setFarClippingDistance(0.90);
#endif
tracker.setDisplayFeatures(displayFeatures);
tracker.setOgreVisibilityTest(useOgre);
if (useOgre)
tracker.setOgreShowConfigDialog(showOgreConfigDialog);
tracker.setScanLineVisibilityTest(useScanline);
tracker.setCovarianceComputation(computeCovariance);
tracker.setProjectionErrorComputation(projectionError);
if (opt_display && opt_click_allowed) {
}
}
if (opt_display && opt_click_allowed) {
tracker.initClick(I, initFile,
true);
}
else {
vpHomogeneousMatrix cMoi(0.02044769891, 0.1101505452, 0.5078963719, 2.063603907, 1.110231561, -0.4392789872);
}
if (opt_display)
if (opt_display)
if (opt_display)
#if defined(VISP_HAVE_PUGIXML)
tracker.loadConfigFile(configFile);
#else
cam.initPersProjWithoutDistortion(547, 542, 338, 234);
tracker.setNearClippingDistance(0.01);
tracker.setFarClippingDistance(0.90);
#endif
tracker.setOgreVisibilityTest(useOgre);
tracker.setScanLineVisibilityTest(useScanline);
tracker.setCovarianceComputation(computeCovariance);
tracker.setProjectionErrorComputation(projectionError);
}
cMo.buildFrom(0.0439540832, 0.0845870108, 0.5477322481, 2.179498458, 0.8611798108, -0.3491961946);
}
if (opt_display) {
}
}
if (opt_click_allowed && opt_display) {
if (opt_step_by_step) {
}
quit = true;
}
opt_step_by_step = !opt_step_by_step;
}
}
}
if (computeCovariance) {
std::cout <<
"Covariance matrix: \n" <<
tracker.getCovarianceMatrix() << std::endl << std::endl;
}
if (projectionError) {
std::cout <<
"Projection error: " <<
tracker.getProjectionError() << std::endl << std::endl;
}
if (opt_display)
}
std::cout <<
"Reached last frame: " << reader.
getFrameIndex() << std::endl;
if (opt_click_allowed && !quit) {
}
return_status = EXIT_SUCCESS;
}
std::cout <<
"Catch an exception: " <<
e << std::endl;
return_status = EXIT_FAILURE;
}
#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
if (display) {
delete display;
display = nullptr;
}
#endif
return return_status;
}
#elif !(defined(VISP_HAVE_MODULE_MBT) && defined(VISP_HAVE_DISPLAY))
int main()
{
std::cout << "Cannot run this example: visp_mbt, visp_gui modules are required." << std::endl;
return EXIT_SUCCESS;
}
#else
int main()
{
std::cout << "Cannot run this example: install Lapack, Eigen3 or OpenCV" << std::endl;
return EXIT_SUCCESS;
}
#endif
Generic class defining intrinsic camera parameters.
static const vpColor darkRed
Class that defines generic functionalities for display.
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.
Implementation of an homogeneous matrix and operations on such kind of matrices.
Definition of the vpImage class member functions.
Make the complete tracking of an object by using its CAD model.
void setMu1(const double &mu_1)
void setRange(const unsigned int &range)
void setLikelihoodThresholdType(const vpLikelihoodThresholdType likelihood_threshold_type)
void setMaskNumber(const unsigned int &mask_number)
void setThreshold(const double &threshold)
void setSampleStep(const double &sample_step)
void setMaskSize(const unsigned int &mask_size)
void setMu2(const double &mu_2)
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)
void open(vpImage< vpRGBa > &I) VP_OVERRIDE
void setFileName(const std::string &filename)
long getFirstFrameIndex()
long getFrameIndex() const
void acquire(vpImage< vpRGBa > &I) VP_OVERRIDE
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.