#include <visp3/core/vpConfig.h>
#if defined(VISP_HAVE_CATCH2)
#include <catch_amalgamated.hpp>
#include <visp3/core/vpIoTools.h>
#include <visp3/io/vpImageIo.h>
#include <visp3/mbt/vpMbGenericTracker.h>
#ifdef DEBUG_DISPLAY
#include <visp3/gui/vpDisplayX.h>
#endif
#ifdef ENABLE_VISP_NAMESPACE
#endif
namespace
{
bool runBenchmark = false;
template <typename Type>
{
static_assert(std::is_same<Type, unsigned char>::value || std::is_same<Type, vpRGBa>::value,
"Template function supports only unsigned char and vpRGBa images!");
#if VISP_HAVE_DATASET_VERSION >= 0x030600
std::string ext("png");
#else
std::string ext("pgm");
#endif
char buffer[FILENAME_MAX];
snprintf(buffer, FILENAME_MAX, std::string(input_directory + "/Images/Image_%04d." + ext).c_str(), cpt);
std::string image_filename = buffer;
snprintf(buffer, FILENAME_MAX, std::string(input_directory + "/Depth/Depth_%04d.bin").c_str(), cpt);
std::string depth_filename = buffer;
snprintf(buffer, FILENAME_MAX, std::string(input_directory + "/CameraPose/Camera_%03d.txt").c_str(), cpt);
std::string pose_filename = buffer;
return false;
unsigned int depth_width = 0, depth_height = 0;
std::ifstream file_depth(depth_filename.c_str(), std::ios::in | std::ios::binary);
if (!file_depth.is_open())
return false;
I_depth.
resize(depth_height, depth_width);
pointcloud.resize(depth_height * depth_width);
const float depth_scale = 0.000030518f;
for (
unsigned int i = 0; i < I_depth.
getHeight(); i++) {
for (
unsigned int j = 0; j < I_depth.
getWidth(); j++) {
double x = 0.0, y = 0.0, Z = I_depth[i][j] * depth_scale;
pt3d[0] = x * Z;
pt3d[1] = y * Z;
pt3d[2] = Z;
pointcloud[i * I_depth.
getWidth() + j] = pt3d;
}
}
std::ifstream file_pose(pose_filename.c_str());
if (!file_pose.is_open()) {
return false;
}
for (unsigned int i = 0; i < 4; i++) {
for (unsigned int j = 0; j < 4; j++) {
file_pose >> cMo[i][j];
}
}
return true;
}
}
TEST_CASE("Benchmark generic tracker", "[benchmark]")
{
if (runBenchmark) {
std::vector<int> tracker_type(2);
const std::string input_directory =
const bool verbose = false;
#if defined(VISP_HAVE_PUGIXML)
const std::string configFileCam1 = input_directory + std::string("/Config/chateau.xml");
const std::string configFileCam2 = input_directory + std::string("/Config/chateau_depth.xml");
tracker.loadConfigFile(configFileCam1, configFileCam2, verbose);
#else
{
tracker.setCameraParameters(cam_color, cam_depth);
}
tracker.setMovingEdge(me);
#if defined(VISP_HAVE_MODULE_KLT) && defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
tracker.setKltMaskBorder(5);
tracker.setKltOpencv(klt);
#endif
tracker.setDepthNormalPclPlaneEstimationMethod(2);
tracker.setDepthNormalPclPlaneEstimationRansacMaxIter(200);
tracker.setDepthNormalPclPlaneEstimationRansacThreshold(0.001);
tracker.setDepthNormalSamplingStep(2, 2);
tracker.setDepthDenseSamplingStep(4, 4);
tracker.setNearClippingDistance(0.01);
tracker.setFarClippingDistance(2.0);
#endif
tracker.loadModel(input_directory + "/Models/chateau.cao", input_directory + "/Models/chateau.cao", verbose);
T[0][0] = -1;
T[0][3] = -0.2;
T[1][1] = 0;
T[1][2] = 1;
T[1][3] = 0.12;
T[2][1] = 1;
T[2][2] = 0;
T[2][3] = -0.15;
tracker.loadModel(input_directory + "/Models/cube.cao", verbose, T);
std::vector<vpColVector> pointcloud;
tracker.getCameraParameters(cam_color, cam_depth);
depth_M_color[0][3] = -0.05;
tracker.setCameraTransformationMatrix("Camera2", depth_M_color);
std::vector<vpImage<unsigned char> > images;
std::vector<vpImage<uint16_t> > depth_raws;
std::vector<std::vector<vpColVector> > pointclouds;
std::vector<vpHomogeneousMatrix> cMo_truth_all;
for (int i = 1; i <= 40; i++) {
if (read_data(input_directory, i, cam_depth, I, I_depth_raw, pointcloud, cMo_truth)) {
images.push_back(I);
depth_raws.push_back(I_depth_raw);
pointclouds.push_back(pointcloud);
cMo_truth_all.push_back(cMo_truth);
}
}
for (int i = 40; i >= 1; i--) {
if (read_data(input_directory, i, cam_depth, I, I_depth_raw, pointcloud, cMo_truth)) {
images.push_back(I);
depth_raws.push_back(I_depth_raw);
pointclouds.push_back(pointcloud);
cMo_truth_all.push_back(cMo_truth);
}
}
{
std::vector<std::map<std::string, int> > mapOfTrackerTypes;
mapOfTrackerTypes.push_back(
mapOfTrackerTypes.push_back(
#if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
mapOfTrackerTypes.push_back(
#endif
std::vector<std::string> benchmarkNames = {
"Edge MBT",
"Edge + Depth dense MBT",
#if defined(VISP_HAVE_OPENCV)
"KLT MBT",
"KLT + depth dense MBT",
"Edge + KLT + depth dense MBT"
#endif
};
std::vector<bool> monoculars = {
true,
false,
#if defined(VISP_HAVE_OPENCV)
true,
false,
false
#endif
};
for (size_t idx = 0; idx < mapOfTrackerTypes.size(); idx++) {
tracker.resetTracker();
tracker.setTrackerType(mapOfTrackerTypes[idx]);
const bool verbose = false;
#if defined(VISP_HAVE_PUGIXML)
tracker.loadConfigFile(configFileCam1, configFileCam2, verbose);
#else
{
tracker.setCameraParameters(cam_color, cam_depth);
}
tracker.setMovingEdge(me);
#if defined(VISP_HAVE_MODULE_KLT) && defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
tracker.setKltMaskBorder(5);
tracker.setKltOpencv(klt);
#endif
tracker.setDepthNormalPclPlaneEstimationMethod(2);
tracker.setDepthNormalPclPlaneEstimationRansacMaxIter(200);
tracker.setDepthNormalPclPlaneEstimationRansacThreshold(0.001);
tracker.setDepthNormalSamplingStep(2, 2);
tracker.setDepthDenseSamplingStep(4, 4);
tracker.setNearClippingDistance(0.01);
tracker.setFarClippingDistance(2.0);
#endif
tracker.loadModel(input_directory + "/Models/chateau.cao", input_directory + "/Models/chateau.cao", verbose);
tracker.loadModel(input_directory + "/Models/cube.cao", verbose, T);
tracker.initFromPose(images.front(), cMo_truth_all.front());
std::map<std::string, unsigned int> mapOfWidths, mapOfHeights;
mapOfWidths[
"Camera2"] = monoculars[idx] ? 0 : I_depth_raw.
getWidth();
mapOfHeights[
"Camera2"] = monoculars[idx] ? 0 : I_depth_raw.
getHeight();
#ifndef DEBUG_DISPLAY
BENCHMARK(benchmarkNames[idx].c_str())
#else
vpDisplayX d_color(I, 0, 0, "Color image");
vpDisplayX d_depth(I_depth, I.
getWidth(), 0,
"Depth image");
tracker.setDisplayFeatures(true);
#endif
{
tracker.initFromPose(images.front(), cMo_truth_all.front());
for (size_t i = 0; i < images.size(); i++) {
const std::vector<vpColVector> &pointcloud_current = pointclouds[i];
#ifdef DEBUG_DISPLAY
I = I_current;
#endif
std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
mapOfImages["Camera1"] = &I_current;
std::map<std::string, const std::vector<vpColVector> *> mapOfPointclouds;
mapOfPointclouds["Camera2"] = &pointcloud_current;
tracker.track(mapOfImages, mapOfPointclouds, mapOfWidths, mapOfHeights);
cMo = tracker.getPose();
#ifdef DEBUG_DISPLAY
tracker.display(I, I_depth, cMo, depth_M_color * cMo, cam_color, cam_depth,
vpColor::red, 3);
I, 40, 20, std::string(
"Nb features: " + std::to_string(tracker.getError().getRows())),
vpColor::red);
#endif
}
#ifndef DEBUG_DISPLAY
return cMo;
};
#else
}
#endif
for (unsigned int i = 0; i < 3; i++) {
t_err[i] = pose_est[i] - pose_truth[i];
tu_err[i] = pose_est[i + 3] - pose_truth[i + 3];
}
const double max_translation_error = 0.006;
const double max_rotation_error = 0.03;
CHECK(sqrt(t_err.sumSquare()) < max_translation_error);
CHECK(sqrt(tu_err.sumSquare()) < max_rotation_error);
}
}
}
}
int main(int argc, char *argv[])
{
Catch::Session session;
auto cli = session.cli()
| Catch::Clara::Opt(runBenchmark)
["--benchmark"]
("run benchmark comparing naive code with ViSP implementation");
session.cli(cli);
session.applyCommandLine(argc, argv);
int numFailed = session.run();
return numFailed;
}
#else
#include <iostream>
int main() { return EXIT_SUCCESS; }
#endif
Generic class defining intrinsic camera parameters.
void initPersProjWithoutDistortion(double px, double py, double u0, double v0)
Implementation of column vector and the associated operations.
static const vpColor none
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)
Implementation of an homogeneous matrix and operations on such kind of matrices.
static void createDepthHistogram(const vpImage< uint16_t > &src_depth, vpImage< vpRGBa > &dest_rgba)
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition of the vpImage class member functions.
unsigned int getWidth() const
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
unsigned int getHeight() const
Wrapper for the KLT (Kanade-Lucas-Tomasi) feature tracker implemented in OpenCV. Thus to enable this ...
void setBlockSize(int blockSize)
void setQuality(double qualityLevel)
void setHarrisFreeParameter(double harris_k)
void setMaxFeatures(int maxCount)
void setMinDistance(double minDistance)
void setWindowSize(int winSize)
void setPyramidLevels(int pyrMaxLevel)
static double rad(double deg)
Real-time 6D object pose tracking using its CAD model.
@ ROBUST_FEATURE_ESTIMATION
Robust scheme to estimate the normal of the plane.
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 void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
Implementation of a pose vector and operations on poses.
VISP_EXPORT int wait(double t0, double t)