44 #include <visp3/core/vpConfig.h> 46 #if defined(VISP_HAVE_MODULE_MBT) \ 47 && (defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_OPENCV)) 49 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11) 50 #include <type_traits> 53 #include <visp3/core/vpIoTools.h> 54 #include <visp3/io/vpParseArgv.h> 55 #include <visp3/io/vpImageIo.h> 56 #include <visp3/gui/vpDisplayX.h> 57 #include <visp3/gui/vpDisplayGDI.h> 58 #include <visp3/gui/vpDisplayOpenCV.h> 59 #include <visp3/gui/vpDisplayD3D.h> 60 #include <visp3/gui/vpDisplayGTK.h> 61 #include <visp3/mbt/vpMbGenericTracker.h> 63 #define GETOPTARGS "i:dcle:mCh" 67 void usage(
const char *name,
const char *badparam)
70 Regression test for vpGenericTracker and depth.\n\ 73 %s [-i <test image path>] [-c] [-d] [-h] [-l] \n\ 74 [-e <last frame index>] [-m] [-C]\n", name);
78 -i <input image path> \n\ 79 Set image input path.\n\ 80 These images come from ViSP-images-x.y.z.tar.gz available \n\ 81 on the ViSP website.\n\ 82 Setting the VISP_INPUT_IMAGE_PATH environment\n\ 83 variable produces the same behavior than using\n\ 87 Turn off the display.\n\ 90 Disable the mouse click. Useful to automate the \n\ 91 execution of this program without human intervention.\n\ 94 Use the scanline for visibility tests.\n\ 96 -e <last frame index>\n\ 97 Specify the index of the last frame. Once reached, the tracking is stopped.\n\ 100 Set a tracking mask.\n\ 106 Print the help.\n\n");
109 fprintf(stdout,
"\nERROR: Bad parameter [%s]\n", badparam);
112 bool getOptions(
int argc,
const char **argv, std::string &ipath,
bool &click_allowed,
bool &display,
113 bool &useScanline,
int &lastFrame,
bool &use_mask,
bool &use_color_image)
124 click_allowed =
false;
133 lastFrame = atoi(optarg_);
139 use_color_image =
true;
142 usage(argv[0], NULL);
147 usage(argv[0], optarg_);
153 if ((c == 1) || (c == -1)) {
155 usage(argv[0], NULL);
156 std::cerr <<
"ERROR: " << std::endl;
157 std::cerr <<
" Bad argument " << optarg_ << std::endl << std::endl;
164 template <
typename Type>
165 bool read_data(
const std::string &input_directory,
int cpt,
const vpCameraParameters &cam_depth,
169 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11) 170 static_assert(std::is_same<Type, unsigned char>::value || std::is_same<Type, vpRGBa>::value,
171 "Template function supports only unsigned char and vpRGBa images!");
174 sprintf(buffer, std::string(input_directory +
"/Images/Image_%04d.pgm").c_str(), cpt);
175 std::string image_filename = buffer;
177 sprintf(buffer, std::string(input_directory +
"/Depth/Depth_%04d.bin").c_str(), cpt);
178 std::string depth_filename = buffer;
180 sprintf(buffer, std::string(input_directory +
"/CameraPose/Camera_%03d.txt").c_str(), cpt);
181 std::string pose_filename = buffer;
189 unsigned int depth_width = 0, depth_height = 0;
190 std::ifstream file_depth(depth_filename.c_str(), std::ios::in | std::ios::binary);
191 if (!file_depth.is_open())
196 I_depth.
resize(depth_height, depth_width);
197 pointcloud.resize(depth_height*depth_width);
199 const float depth_scale = 0.000030518f;
200 for (
unsigned int i = 0; i < I_depth.
getHeight(); i++) {
201 for (
unsigned int j = 0; j < I_depth.
getWidth(); j++) {
203 double x = 0.0, y = 0.0, Z = I_depth[i][j] * depth_scale;
209 pointcloud[i*I_depth.
getWidth()+j] = pt3d;
213 std::ifstream file_pose(pose_filename.c_str());
214 if (!file_pose.is_open()) {
218 for (
unsigned int i = 0; i < 4; i++) {
219 for (
unsigned int j = 0; j < 4; j++) {
220 file_pose >> cMo[i][j];
227 template <
typename Type>
228 bool run(
vpImage<Type> &I,
const std::string &input_directory,
bool opt_click_allowed,
229 bool opt_display,
bool useScanline,
int opt_lastFrame,
bool use_mask) {
230 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11) 231 static_assert(std::is_same<Type, unsigned char>::value || std::is_same<Type, vpRGBa>::value,
232 "Template function supports only unsigned char and vpRGBa images!");
235 #if defined VISP_HAVE_X11 237 #elif defined VISP_HAVE_GDI 239 #elif defined VISP_HAVE_OPENCV 241 #elif defined VISP_HAVE_D3D9 243 #elif defined VISP_HAVE_GTK 249 std::vector<int> tracker_type;
252 tracker.loadConfigFile(input_directory +
"/Config/chateau_depth.xml");
258 tracker.setCameraParameters(cam_depth);
262 tracker.setDepthNormalPclPlaneEstimationMethod(2);
263 tracker.setDepthNormalPclPlaneEstimationRansacMaxIter(200);
264 tracker.setDepthNormalPclPlaneEstimationRansacThreshold(0.001);
265 tracker.setDepthNormalSamplingStep(2, 2);
267 tracker.setDepthDenseSamplingStep(4, 4);
269 #if defined(VISP_HAVE_MODULE_KLT) && (defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION >= 0x020100)) 270 tracker.setKltMaskBorder(5);
275 tracker.setNearClippingDistance(0.01);
276 tracker.setFarClippingDistance(2.0);
279 tracker.loadModel(input_directory +
"/Models/chateau.cao");
289 tracker.loadModel(input_directory +
"/Models/cube.cao",
false, T);
291 tracker.getCameraParameters(cam_depth);
292 tracker.setDisplayFeatures(
true);
293 tracker.setScanLineVisibilityTest(useScanline);
298 std::vector<vpColVector> pointcloud;
300 if (!read_data(input_directory, cpt_frame, cam_depth, I, I_depth_raw, pointcloud, cMo_truth)) {
301 std::cerr <<
"Cannot read first frame!" << std::endl;
306 const double roi_step = 7.0;
307 const double roi_step2 = 6.0;
310 for (
unsigned int i = (
unsigned int) (I.
getRows()/roi_step); i < (
unsigned int) (I.
getRows()*roi_step2/roi_step); i++) {
311 for (
unsigned int j = (
unsigned int) (I.
getCols()/roi_step); j < (
unsigned int) (I.
getCols()*roi_step2/roi_step); j++) {
315 tracker.setMask(mask);
320 #ifdef VISP_HAVE_DISPLAY 321 display1.
init(I, 0, 0,
"Image");
327 depth_M_color[0][3] = -0.05;
328 tracker.initFromPose(I, depth_M_color*cMo_truth);
330 bool click =
false, quit =
false, correct_accuracy =
true;
331 std::vector<double> vec_err_t, vec_err_tu;
332 std::vector<double> time_vec;
333 while (read_data(input_directory, cpt_frame, cam_depth, I, I_depth_raw, pointcloud, cMo_truth) && !quit
334 && (opt_lastFrame > 0 ? (
int)cpt_frame <= opt_lastFrame :
true)) {
343 std::map<std::string, const vpImage<Type> *> mapOfImages;
344 std::map<std::string, const std::vector<vpColVector> *> mapOfPointclouds;
345 mapOfPointclouds[
"Camera"] = &pointcloud;
346 std::map<std::string, unsigned int> mapOfWidths, mapOfHeights;
347 mapOfWidths[
"Camera"] = I_depth.
getWidth();
348 mapOfHeights[
"Camera"] = I_depth.
getHeight();
350 tracker.track(mapOfImages, mapOfPointclouds, mapOfWidths, mapOfHeights);
353 time_vec.push_back(t);
356 tracker.display(I_depth, cMo, cam_depth,
vpColor::red, 3);
359 std::stringstream ss;
360 ss <<
"Frame: " << cpt_frame;
363 ss <<
"Nb features: " << tracker.getError().getRows();
371 for (
unsigned int i = 0; i < 3; i++) {
372 t_est[i] = pose_est[i];
373 t_truth[i] = pose_truth[i];
374 tu_est[i] = pose_est[i+3];
375 tu_truth[i] = pose_truth[i+3];
378 vpColVector t_err = t_truth-t_est, tu_err = tu_truth-tu_est;
380 vec_err_t.push_back( t_err2 );
381 vec_err_tu.push_back( tu_err2 );
382 const double t_thresh = useScanline ? 0.003 : 0.002;
383 const double tu_thresh = useScanline ? 0.5 : 0.4;
384 if ( !use_mask && (t_err2 > t_thresh || tu_err2 > tu_thresh) ) {
385 std::cerr <<
"Pose estimated exceeds the threshold (t_thresh = " << t_thresh <<
", tu_thresh = " << tu_thresh <<
")!" << std::endl;
386 std::cout <<
"t_err: " << t_err2 <<
" ; tu_err: " << tu_err2 << std::endl;
387 correct_accuracy =
false;
401 if (opt_display && opt_click_allowed) {
422 if (!time_vec.empty())
426 if (!vec_err_t.empty())
427 std::cout <<
"Max translation error: " << *std::max_element(vec_err_t.begin(), vec_err_t.end()) << std::endl;
429 if (!vec_err_tu.empty())
430 std::cout <<
"Max thetau error: " << *std::max_element(vec_err_tu.begin(), vec_err_tu.end()) << std::endl;
432 return correct_accuracy ? EXIT_SUCCESS : EXIT_FAILURE;
436 int main(
int argc,
const char *argv[])
439 std::string env_ipath;
440 std::string opt_ipath =
"";
441 bool opt_click_allowed =
true;
442 bool opt_display =
true;
443 bool useScanline =
false;
444 #if defined(__mips__) || defined(__mips) || defined(mips) || defined(__MIPS__) 446 int opt_lastFrame = 5;
448 int opt_lastFrame = -1;
450 bool use_mask =
false;
451 bool use_color_image =
false;
458 if (!getOptions(argc, argv, opt_ipath, opt_click_allowed, opt_display,
459 useScanline, opt_lastFrame, use_mask, use_color_image)) {
463 std::cout <<
"useScanline: " << useScanline << std::endl;
464 std::cout <<
"use_mask: " << use_mask << std::endl;
465 std::cout <<
"use_color_image: " << use_color_image << std::endl;
468 if (opt_ipath.empty() && env_ipath.empty()) {
469 usage(argv[0], NULL);
470 std::cerr << std::endl <<
"ERROR:" << std::endl;
471 std::cerr <<
" Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
472 <<
" environment variable to specify the location of the " << std::endl
473 <<
" image path where test images are located." << std::endl
479 std::string input_directory =
vpIoTools::createFilePath(!opt_ipath.empty() ? opt_ipath : env_ipath,
"mbt-depth/Castle-simu");
481 std::cerr <<
"ViSP-images does not contain the folder: " << input_directory <<
"!" << std::endl;
485 if (use_color_image) {
487 return run(I_color, input_directory, opt_click_allowed, opt_display, useScanline, opt_lastFrame, use_mask);
490 return run(I_gray, input_directory, opt_click_allowed, opt_display, useScanline, opt_lastFrame, use_mask);
493 std::cout <<
"Catch an exception: " << e << std::endl;
497 #elif !(defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_EIGEN3) || defined(VISP_HAVE_OPENCV)) 499 std::cout <<
"Cannot run this example: install Lapack, Eigen3 or OpenCV" << std::endl;
504 std::cout <<
"Enable MBT module (VISP_HAVE_MODULE_MBT) to launch this test." << std::endl;
unsigned int getCols() const
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
unsigned int getWidth() const
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Implementation of an homogeneous matrix and operations on such kind of matrices.
static double getMedian(const std::vector< double > &v)
Display for windows using GDI (available on any windows 32 platform).
static double getStdev(const std::vector< double > &v, bool useBesselCorrection=false)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
static const vpColor none
error that can be emited by ViSP classes.
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
Real-time 6D object pose tracking using its CAD model.
static void flush(const vpImage< unsigned char > &I)
VISP_EXPORT double measureTimeMs()
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
static double getMean(const std::vector< double > &v)
Display for windows using Direct3D 3rd party. Thus to enable this class Direct3D should be installed...
unsigned int getRows() const
static void display(const vpImage< unsigned char > &I)
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
Generic class defining intrinsic camera parameters.
void init(vpImage< unsigned char > &I, int win_x=-1, int win_y=-1, const std::string &win_title="")
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
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 double rad(double deg)
void initPersProjWithoutDistortion(double px, double py, double u0, double v0)
static double deg(double rad)
static void read(vpImage< unsigned char > &I, const std::string &filename)
Implementation of column vector and the associated operations.
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))
Implementation of a pose vector and operations on poses.
unsigned int getHeight() const
Defines a rectangle in the plane.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
static const vpColor yellow
Definition of the vpImage class member functions.
static void createDepthHistogram(const vpImage< uint16_t > &src_depth, vpImage< vpRGBa > &dest_rgba)