37 #include <visp3/core/vpConfig.h>
39 #if defined(VISP_HAVE_CATCH2)
41 #include <catch_amalgamated.hpp>
43 #include <visp3/core/vpIoTools.h>
44 #include <visp3/io/vpImageIo.h>
45 #include <visp3/mbt/vpMbGenericTracker.h>
49 #include <visp3/gui/vpDisplayX.h>
52 #ifdef ENABLE_VISP_NAMESPACE
58 bool runBenchmark =
false;
60 template <
typename Type>
64 static_assert(std::is_same<Type, unsigned char>::value || std::is_same<Type, vpRGBa>::value,
65 "Template function supports only unsigned char and vpRGBa images!");
66 #if VISP_HAVE_DATASET_VERSION >= 0x030600
67 std::string ext(
"png");
69 std::string ext(
"pgm");
71 char buffer[FILENAME_MAX];
72 snprintf(buffer, FILENAME_MAX, std::string(input_directory +
"/Images/Image_%04d." + ext).c_str(), cpt);
73 std::string image_filename = buffer;
75 snprintf(buffer, FILENAME_MAX, std::string(input_directory +
"/Depth/Depth_%04d.bin").c_str(), cpt);
76 std::string depth_filename = buffer;
78 snprintf(buffer, FILENAME_MAX, std::string(input_directory +
"/CameraPose/Camera_%03d.txt").c_str(), cpt);
79 std::string pose_filename = buffer;
87 unsigned int depth_width = 0, depth_height = 0;
88 std::ifstream file_depth(depth_filename.c_str(), std::ios::in | std::ios::binary);
89 if (!file_depth.is_open())
94 I_depth.
resize(depth_height, depth_width);
95 pointcloud.resize(depth_height * depth_width);
97 const float depth_scale = 0.000030518f;
98 for (
unsigned int i = 0; i < I_depth.
getHeight(); i++) {
99 for (
unsigned int j = 0; j < I_depth.
getWidth(); j++) {
101 double x = 0.0, y = 0.0, Z = I_depth[i][j] * depth_scale;
107 pointcloud[i * I_depth.
getWidth() + j] = pt3d;
111 std::ifstream file_pose(pose_filename.c_str());
112 if (!file_pose.is_open()) {
116 for (
unsigned int i = 0; i < 4; i++) {
117 for (
unsigned int j = 0; j < 4; j++) {
118 file_pose >> cMo[i][j];
126 TEST_CASE(
"Benchmark generic tracker",
"[benchmark]")
129 std::vector<int> tracker_type(2);
134 const std::string input_directory =
137 const bool verbose =
false;
138 #if defined(VISP_HAVE_PUGIXML)
139 const std::string configFileCam1 = input_directory + std::string(
"/Config/chateau.xml");
140 const std::string configFileCam2 = input_directory + std::string(
"/Config/chateau_depth.xml");
143 tracker.loadConfigFile(configFileCam1, configFileCam2, verbose);
149 tracker.setCameraParameters(cam_color, cam_depth);
162 tracker.setMovingEdge(me);
165 #if defined(VISP_HAVE_MODULE_KLT) && defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
167 tracker.setKltMaskBorder(5);
176 tracker.setKltOpencv(klt);
181 tracker.setDepthNormalPclPlaneEstimationMethod(2);
182 tracker.setDepthNormalPclPlaneEstimationRansacMaxIter(200);
183 tracker.setDepthNormalPclPlaneEstimationRansacThreshold(0.001);
184 tracker.setDepthNormalSamplingStep(2, 2);
186 tracker.setDepthDenseSamplingStep(4, 4);
190 tracker.setNearClippingDistance(0.01);
191 tracker.setFarClippingDistance(2.0);
196 tracker.loadModel(input_directory +
"/Models/chateau.cao", input_directory +
"/Models/chateau.cao", verbose);
207 tracker.loadModel(input_directory +
"/Models/cube.cao", verbose, T);
212 std::vector<vpColVector> pointcloud;
215 tracker.getCameraParameters(cam_color, cam_depth);
218 depth_M_color[0][3] = -0.05;
219 tracker.setCameraTransformationMatrix(
"Camera2", depth_M_color);
222 std::vector<vpImage<unsigned char> > images;
223 std::vector<vpImage<uint16_t> > depth_raws;
224 std::vector<std::vector<vpColVector> > pointclouds;
225 std::vector<vpHomogeneousMatrix> cMo_truth_all;
227 for (
int i = 1; i <= 40; i++) {
228 if (read_data(input_directory, i, cam_depth, I, I_depth_raw, pointcloud, cMo_truth)) {
230 depth_raws.push_back(I_depth_raw);
231 pointclouds.push_back(pointcloud);
232 cMo_truth_all.push_back(cMo_truth);
236 for (
int i = 40; i >= 1; i--) {
237 if (read_data(input_directory, i, cam_depth, I, I_depth_raw, pointcloud, cMo_truth)) {
239 depth_raws.push_back(I_depth_raw);
240 pointclouds.push_back(pointcloud);
241 cMo_truth_all.push_back(cMo_truth);
247 std::vector<std::map<std::string, int> > mapOfTrackerTypes;
248 mapOfTrackerTypes.push_back(
250 mapOfTrackerTypes.push_back(
252 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
253 mapOfTrackerTypes.push_back(
261 std::vector<std::string> benchmarkNames = {
263 "Edge + Depth dense MBT",
264 #if defined(VISP_HAVE_OPENCV)
266 "KLT + depth dense MBT",
267 "Edge + KLT + depth dense MBT"
271 std::vector<bool> monoculars = {
274 #if defined(VISP_HAVE_OPENCV)
281 for (
size_t idx = 0; idx < mapOfTrackerTypes.size(); idx++) {
282 tracker.resetTracker();
283 tracker.setTrackerType(mapOfTrackerTypes[idx]);
285 const bool verbose =
false;
286 #if defined(VISP_HAVE_PUGIXML)
287 tracker.loadConfigFile(configFileCam1, configFileCam2, verbose);
293 tracker.setCameraParameters(cam_color, cam_depth);
306 tracker.setMovingEdge(me);
309 #if defined(VISP_HAVE_MODULE_KLT) && defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
311 tracker.setKltMaskBorder(5);
320 tracker.setKltOpencv(klt);
325 tracker.setDepthNormalPclPlaneEstimationMethod(2);
326 tracker.setDepthNormalPclPlaneEstimationRansacMaxIter(200);
327 tracker.setDepthNormalPclPlaneEstimationRansacThreshold(0.001);
328 tracker.setDepthNormalSamplingStep(2, 2);
330 tracker.setDepthDenseSamplingStep(4, 4);
334 tracker.setNearClippingDistance(0.01);
335 tracker.setFarClippingDistance(2.0);
338 tracker.loadModel(input_directory +
"/Models/chateau.cao", input_directory +
"/Models/chateau.cao", verbose);
339 tracker.loadModel(input_directory +
"/Models/cube.cao", verbose, T);
340 tracker.initFromPose(images.front(), cMo_truth_all.front());
342 std::map<std::string, unsigned int> mapOfWidths, mapOfHeights;
343 mapOfWidths[
"Camera2"] = monoculars[idx] ? 0 : I_depth_raw.
getWidth();
344 mapOfHeights[
"Camera2"] = monoculars[idx] ? 0 : I_depth_raw.
getHeight();
347 #ifndef DEBUG_DISPLAY
348 BENCHMARK(benchmarkNames[idx].c_str())
353 vpDisplayX d_color(I, 0, 0,
"Color image");
354 vpDisplayX d_depth(I_depth, I.
getWidth(), 0,
"Depth image");
355 tracker.setDisplayFeatures(
true);
358 tracker.initFromPose(images.front(), cMo_truth_all.front());
360 for (
size_t i = 0; i < images.size(); i++) {
362 const std::vector<vpColVector> &pointcloud_current = pointclouds[i];
371 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
372 mapOfImages[
"Camera1"] = &I_current;
374 std::map<std::string, const std::vector<vpColVector> *> mapOfPointclouds;
375 mapOfPointclouds[
"Camera2"] = &pointcloud_current;
377 tracker.track(mapOfImages, mapOfPointclouds, mapOfWidths, mapOfHeights);
378 cMo = tracker.getPose();
381 tracker.display(I, I_depth, cMo, depth_M_color * cMo, cam_color, cam_depth,
vpColor::red, 3);
386 I, 40, 20, std::string(
"Nb features: " + std::to_string(tracker.getError().getRows())),
vpColor::red);
394 #ifndef DEBUG_DISPLAY
404 for (
unsigned int i = 0; i < 3; i++) {
405 t_err[i] = pose_est[i] - pose_truth[i];
406 tu_err[i] = pose_est[i + 3] - pose_truth[i + 3];
409 const double max_translation_error = 0.006;
410 const double max_rotation_error = 0.03;
411 CHECK(sqrt(t_err.sumSquare()) < max_translation_error);
412 CHECK(sqrt(tu_err.sumSquare()) < max_rotation_error);
418 int main(
int argc,
char *argv[])
420 Catch::Session session;
422 auto cli = session.cli()
423 | Catch::Clara::Opt(runBenchmark)
425 (
"run benchmark comparing naive code with ViSP implementation");
429 session.applyCommandLine(argc, argv);
430 int numFailed = session.run();
437 int main() {
return EXIT_SUCCESS; }
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)