42 #include <visp3/core/vpConfig.h>
44 #if defined(VISP_HAVE_MODULE_MBT) && (defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_OPENCV))
46 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
47 #include <type_traits>
50 #include <visp3/core/vpIoTools.h>
51 #include <visp3/gui/vpDisplayD3D.h>
52 #include <visp3/gui/vpDisplayGDI.h>
53 #include <visp3/gui/vpDisplayGTK.h>
54 #include <visp3/gui/vpDisplayOpenCV.h>
55 #include <visp3/gui/vpDisplayX.h>
56 #include <visp3/io/vpImageIo.h>
57 #include <visp3/io/vpParseArgv.h>
58 #include <visp3/mbt/vpMbGenericTracker.h>
60 #define GETOPTARGS "i:dcle:mCh"
62 #ifdef ENABLE_VISP_NAMESPACE
68 void usage(
const char *name,
const char *badparam)
71 Regression test for vpGenericTracker and depth.\n\
74 %s [-i <test image path>] [-c] [-d] [-h] [-l] \n\
75 [-e <last frame index>] [-m] [-C]\n",
80 -i <input image path> \n\
81 Set image input path.\n\
82 These images come from ViSP-images-x.y.z.tar.gz available \n\
83 on the ViSP website.\n\
84 Setting the VISP_INPUT_IMAGE_PATH environment\n\
85 variable produces the same behavior than using\n\
89 Turn off the display.\n\
92 Disable the mouse click. Useful to automate the \n\
93 execution of this program without human intervention.\n\
96 Use the scanline for visibility tests.\n\
98 -e <last frame index>\n\
99 Specify the index of the last frame. Once reached, the tracking is stopped.\n\
102 Set a tracking mask.\n\
108 Print the help.\n\n");
111 fprintf(stdout,
"\nERROR: Bad parameter [%s]\n", badparam);
114 bool getOptions(
int argc,
const char **argv, std::string &ipath,
bool &click_allowed,
bool &display,
bool &useScanline,
115 int &lastFrame,
bool &use_mask,
bool &use_color_image)
126 click_allowed =
false;
135 lastFrame = atoi(optarg_);
141 use_color_image =
true;
144 usage(argv[0],
nullptr);
149 usage(argv[0], optarg_);
155 if ((c == 1) || (c == -1)) {
157 usage(argv[0],
nullptr);
158 std::cerr <<
"ERROR: " << std::endl;
159 std::cerr <<
" Bad argument " << optarg_ << std::endl << std::endl;
166 template <
typename Type>
170 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
171 static_assert(std::is_same<Type, unsigned char>::value || std::is_same<Type, vpRGBa>::value,
172 "Template function supports only unsigned char and vpRGBa images!");
174 #if VISP_HAVE_DATASET_VERSION >= 0x030600
175 std::string ext(
"png");
177 std::string ext(
"pgm");
179 char buffer[FILENAME_MAX];
180 snprintf(buffer, FILENAME_MAX, std::string(input_directory +
"/Images/Image_%04d." + ext).c_str(), cpt);
181 std::string image_filename = buffer;
183 snprintf(buffer, FILENAME_MAX, std::string(input_directory +
"/Depth/Depth_%04d.bin").c_str(), cpt);
184 std::string depth_filename = buffer;
186 snprintf(buffer, FILENAME_MAX, std::string(input_directory +
"/CameraPose/Camera_%03d.txt").c_str(), cpt);
187 std::string pose_filename = buffer;
195 unsigned int depth_width = 0, depth_height = 0;
196 std::ifstream file_depth(depth_filename.c_str(), std::ios::in | std::ios::binary);
197 if (!file_depth.is_open())
202 I_depth.
resize(depth_height, depth_width);
203 pointcloud.resize(depth_height * depth_width);
205 const float depth_scale = 0.000030518f;
206 for (
unsigned int i = 0; i < I_depth.
getHeight(); i++) {
207 for (
unsigned int j = 0; j < I_depth.
getWidth(); j++) {
209 double x = 0.0, y = 0.0, Z = I_depth[i][j] * depth_scale;
215 pointcloud[i * I_depth.
getWidth() + j] = pt3d;
219 std::ifstream file_pose(pose_filename.c_str());
220 if (!file_pose.is_open()) {
224 for (
unsigned int i = 0; i < 4; i++) {
225 for (
unsigned int j = 0; j < 4; j++) {
226 file_pose >> cMo[i][j];
233 template <
typename Type>
234 bool run(
vpImage<Type> &I,
const std::string &input_directory,
bool opt_click_allowed,
bool opt_display,
235 bool useScanline,
int opt_lastFrame,
bool use_mask)
237 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
238 static_assert(std::is_same<Type, unsigned char>::value || std::is_same<Type, vpRGBa>::value,
239 "Template function supports only unsigned char and vpRGBa images!");
242 #if defined(VISP_HAVE_X11)
243 vpDisplayX display1, display2;
244 #elif defined(VISP_HAVE_GDI)
246 #elif defined(HAVE_OPENCV_HIGHGUI)
248 #elif defined(VISP_HAVE_D3D9)
250 #elif defined(VISP_HAVE_GTK)
256 std::vector<int> tracker_type;
260 #if defined(VISP_HAVE_PUGIXML)
261 tracker.loadConfigFile(input_directory +
"/Config/chateau_depth.xml");
267 tracker.setCameraParameters(cam_depth);
271 tracker.setDepthNormalPclPlaneEstimationMethod(2);
272 tracker.setDepthNormalPclPlaneEstimationRansacMaxIter(200);
273 tracker.setDepthNormalPclPlaneEstimationRansacThreshold(0.001);
274 tracker.setDepthNormalSamplingStep(2, 2);
276 tracker.setDepthDenseSamplingStep(4, 4);
278 #if defined(VISP_HAVE_MODULE_KLT) && defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
279 tracker.setKltMaskBorder(5);
284 tracker.setNearClippingDistance(0.01);
285 tracker.setFarClippingDistance(2.0);
288 tracker.loadModel(input_directory +
"/Models/chateau.cao");
298 tracker.loadModel(input_directory +
"/Models/cube.cao",
false, T);
300 tracker.getCameraParameters(cam_depth);
301 tracker.setDisplayFeatures(
true);
302 tracker.setScanLineVisibilityTest(useScanline);
307 std::vector<vpColVector> pointcloud;
309 if (!read_data(input_directory, cpt_frame, cam_depth, I, I_depth_raw, pointcloud, cMo_truth)) {
310 std::cerr <<
"Cannot read first frame!" << std::endl;
315 const double roi_step = 7.0;
316 const double roi_step2 = 6.0;
319 for (
unsigned int i = (
unsigned int)(I.
getRows() / roi_step);
320 i < (
unsigned int)(I.
getRows() * roi_step2 / roi_step); i++) {
321 for (
unsigned int j = (
unsigned int)(I.
getCols() / roi_step);
322 j < (
unsigned int)(I.
getCols() * roi_step2 / roi_step); j++) {
326 tracker.setMask(mask);
331 #ifdef VISP_HAVE_DISPLAY
332 display1.init(I, 0, 0,
"Image");
333 display2.init(I_depth, (
int)I.
getWidth(), 0,
"Depth");
338 depth_M_color[0][3] = -0.05;
339 tracker.initFromPose(I, depth_M_color * cMo_truth);
341 bool click =
false, quit =
false, correct_accuracy =
true;
342 std::vector<double> vec_err_t, vec_err_tu;
343 std::vector<double> time_vec;
344 while (read_data(input_directory, cpt_frame, cam_depth, I, I_depth_raw, pointcloud, cMo_truth) && !quit &&
345 (opt_lastFrame > 0 ? (
int)cpt_frame <= opt_lastFrame :
true)) {
354 std::map<std::string, const vpImage<Type> *> mapOfImages;
355 std::map<std::string, const std::vector<vpColVector> *> mapOfPointclouds;
356 mapOfPointclouds[
"Camera"] = &pointcloud;
357 std::map<std::string, unsigned int> mapOfWidths, mapOfHeights;
358 mapOfWidths[
"Camera"] = I_depth.
getWidth();
359 mapOfHeights[
"Camera"] = I_depth.
getHeight();
361 tracker.track(mapOfImages, mapOfPointclouds, mapOfWidths, mapOfHeights);
364 time_vec.push_back(t);
367 tracker.display(I_depth, cMo, cam_depth,
vpColor::red, 3);
370 std::stringstream ss;
371 ss <<
"Frame: " << cpt_frame;
374 ss <<
"Nb features: " << tracker.getError().getRows();
382 for (
unsigned int i = 0; i < 3; i++) {
383 t_est[i] = pose_est[i];
384 t_truth[i] = pose_truth[i];
385 tu_est[i] = pose_est[i + 3];
386 tu_truth[i] = pose_truth[i + 3];
389 vpColVector t_err = t_truth - t_est, tu_err = tu_truth - tu_est;
391 vec_err_t.push_back(t_err2);
392 vec_err_tu.push_back(tu_err2);
393 const double t_thresh = useScanline ? 0.003 : 0.002;
394 const double tu_thresh = useScanline ? 0.5 : 0.4;
395 if (!use_mask && (t_err2 > t_thresh || tu_err2 > tu_thresh)) {
396 std::cerr <<
"Pose estimated exceeds the threshold (t_thresh = " << t_thresh <<
", tu_thresh = " << tu_thresh
397 <<
")!" << std::endl;
398 std::cout <<
"t_err: " << t_err2 <<
" ; tu_err: " << tu_err2 << std::endl;
399 correct_accuracy =
false;
413 if (opt_display && opt_click_allowed) {
434 if (!time_vec.empty())
439 if (!vec_err_t.empty())
440 std::cout <<
"Max translation error: " << *std::max_element(vec_err_t.begin(), vec_err_t.end()) << std::endl;
442 if (!vec_err_tu.empty())
443 std::cout <<
"Max thetau error: " << *std::max_element(vec_err_tu.begin(), vec_err_tu.end()) << std::endl;
445 return correct_accuracy ? EXIT_SUCCESS : EXIT_FAILURE;
449 int main(
int argc,
const char *argv[])
452 std::string env_ipath;
453 std::string opt_ipath =
"";
454 bool opt_click_allowed =
true;
455 bool opt_display =
true;
456 bool useScanline =
false;
457 #if defined(__mips__) || defined(__mips) || defined(mips) || defined(__MIPS__)
459 int opt_lastFrame = 5;
461 int opt_lastFrame = -1;
463 bool use_mask =
false;
464 bool use_color_image =
false;
471 if (!getOptions(argc, argv, opt_ipath, opt_click_allowed, opt_display, useScanline, opt_lastFrame, use_mask,
476 std::cout <<
"useScanline: " << useScanline << std::endl;
477 std::cout <<
"use_mask: " << use_mask << std::endl;
478 std::cout <<
"use_color_image: " << use_color_image << std::endl;
481 if (opt_ipath.empty() && env_ipath.empty()) {
482 usage(argv[0],
nullptr);
483 std::cerr << std::endl <<
"ERROR:" << std::endl;
484 std::cerr <<
" Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
485 <<
" environment variable to specify the location of the " << std::endl
486 <<
" image path where test images are located." << std::endl
492 std::string input_directory =
495 std::cerr <<
"ViSP-images does not contain the folder: " << input_directory <<
"!" << std::endl;
499 if (use_color_image) {
501 return run(I_color, input_directory, opt_click_allowed, opt_display, useScanline, opt_lastFrame, use_mask);
505 return run(I_gray, input_directory, opt_click_allowed, opt_display, useScanline, opt_lastFrame, use_mask);
509 std::cout <<
"Catch an exception: " << e << std::endl;
513 #elif !(defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_OPENCV))
516 std::cout <<
"Cannot run this example: install Lapack, Eigen3 or OpenCV" << std::endl;
522 std::cout <<
"Enable MBT module (VISP_HAVE_MODULE_MBT) to launch this test." << std::endl;
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 const vpColor yellow
Display for windows using Direct3D 3rd party. Thus to enable this class Direct3D should be installed....
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...
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 displayRectangle(const vpImage< unsigned char > &I, const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1)
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.
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)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
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 getCols() const
unsigned int getHeight() const
unsigned int getRows() const
static double rad(double deg)
static double getMedian(const std::vector< double > &v)
static double getStdev(const std::vector< double > &v, bool useBesselCorrection=false)
static double getMean(const std::vector< double > &v)
static double deg(double rad)
Real-time 6D object pose tracking using its CAD model.
@ ROBUST_FEATURE_ESTIMATION
Robust scheme to estimate the normal of the plane.
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
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.
Defines a rectangle in the plane.
VISP_EXPORT double measureTimeMs()