4#include <visp3/core/vpConfig.h>
5#include <visp3/core/vpDisplay.h>
6#include <visp3/core/vpIoTools.h>
7#include <visp3/core/vpXmlParserCamera.h>
8#include <visp3/gui/vpDisplayFactory.h>
9#include <visp3/io/vpImageIo.h>
10#include <visp3/mbt/vpMbGenericTracker.h>
12#if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGCODECS) && defined(VISP_HAVE_PUGIXML)
13#ifdef ENABLE_VISP_NAMESPACE
19bool read_data(
unsigned int cpt,
const std::string &video_color_images,
const std::string &video_depth_images,
20 bool disable_depth,
const std::string &video_ground_truth,
22 unsigned int &depth_width,
unsigned int &depth_height,
30 std::cerr <<
"Cannot read: " << filename_color << std::endl;
40 std::cerr <<
"Cannot read: " << filename_depth << std::endl;
43 cv::Mat depth_raw = cv::imread(filename_depth, cv::IMREAD_ANYDEPTH | cv::IMREAD_ANYCOLOR);
44 if (depth_raw.empty()) {
45 std::cerr <<
"Cannot read: " << filename_depth << std::endl;
49 depth_width =
static_cast<unsigned int>(depth_raw.cols);
50 depth_height =
static_cast<unsigned int>(depth_raw.rows);
51 I_depth_raw.
resize(depth_height, depth_width);
52 pointcloud.resize(depth_width * depth_height);
54 for (
int i = 0;
i < depth_raw.rows;
i++) {
55 for (
int j = 0;
j < depth_raw.cols;
j++) {
56 I_depth_raw[
i][
j] =
static_cast<uint16_t
>(32767.5f * depth_raw.at<cv::Vec3f>(
i,
j)[0]);
57 double x = 0.0,
y = 0.0;
59 double Z = depth_raw.at<cv::Vec3f>(
i,
j)[0] > 2.0f ? 0.0 : static_cast<double>(depth_raw.at<cv::Vec3f>(
i,
j)[0]);
61 size_t idx =
static_cast<size_t>(
i * depth_raw.cols +
j);
62 pointcloud[
idx].resize(3);
63 pointcloud[
idx][0] =
x * Z;
64 pointcloud[
idx][1] =
y * Z;
65 pointcloud[
idx][2] = Z;
73 cMo_ground_truth.
load(filename_pose);
79void usage(
const char **argv,
int error,
const std::string &data_path,
const std::string &model_path,
int first_frame)
81 std::cout <<
"Synopsis" << std::endl
83 <<
" [--data-path <path>] [--model-path <path>] [--first-frame <index>] [--depth-dense-mode <0|1>] "
84 <<
" [--depth-normals-mode <0|1>] [--me-mode <0|1>] [--klt-mode <0|1>] [--step-by-step] [--display-ground-truth] [--help, -h]" << std::endl
86 std::cout <<
"Description" << std::endl
87 <<
" --data-path <path> Path to the data generated by Blender get_camera_pose_teabox.py" << std::endl
89 <<
" Default: " << data_path << std::endl
91 <<
" --model-path <path> Path to the cad model and tracker settings." << std::endl
94 <<
" --first-frame <index> First frame number to process." << std::endl
95 <<
" Default: " << first_frame << std::endl
98 <<
" --depth-dense-mode Whether to use dense depth features (0 = off, 1 = on). default: 1" << std::endl
100 <<
" --depth-normals-mode Whether to use normal depth features (0 = off, 1 = on). default: 0" << std::endl
102 <<
" --me-mode Whether to use moving edge features (0 = off, 1 = on). default: 1" << std::endl
104 <<
" --klt-mode Whether to use KLT features (0 = off, 1 = on). Requires OpenCV. default: 1" << std::endl
107 <<
" --step-by-step Flag to enable step by step mode." << std::endl
109 <<
" --display-ground-truth Flag to enable displaying ground truth." << std::endl
110 <<
" When this flag is enabled, there is no tracking. This flag is useful" << std::endl
111 <<
" to validate the ground truth over the rendered images." << std::endl
113 <<
" --help, -h Print this helper message." << std::endl
116 std::cout <<
"Error" << std::endl
118 <<
"Unsupported parameter " << argv[
error] << std::endl;
122int main(
int argc,
const char **argv)
124 std::string opt_data_path =
"data/teabox";
125 std::string opt_model_path =
"model/teabox";
126 unsigned int opt_first_frame = 1;
127 int opt_meMode = 1, opt_kltMode = 1, opt_normalsMode = 0, opt_denseMode = 1;
129 bool disable_depth =
false;
130 bool opt_disable_klt =
false;
132 bool opt_display_ground_truth =
false;
133 bool opt_step_by_step =
false;
135 for (
int i = 1;
i < argc;
i++) {
136 if (std::string(argv[i]) ==
"--data-path" && i + 1 < argc) {
137 opt_data_path = std::string(argv[i + 1]);
140 else if (std::string(argv[i]) ==
"--model-path" && i + 1 < argc) {
141 opt_model_path = std::string(argv[i + 1]);
144 else if (std::string(argv[i]) ==
"--depth-dense-mode" && i + 1 < argc) {
145 opt_denseMode =
static_cast<unsigned int>(atoi(argv[i + 1]));
146 if (opt_denseMode < 0 || opt_denseMode > 1) {
147 usage(argv, 0, opt_data_path, opt_model_path, opt_first_frame);
152 else if (std::string(argv[i]) ==
"--depth-normals-mode" && i + 1 < argc) {
153 opt_normalsMode =
static_cast<unsigned int>(atoi(argv[i + 1]));
154 if (opt_normalsMode < 0 || opt_normalsMode > 1) {
155 usage(argv, 0, opt_data_path, opt_model_path, opt_first_frame);
160 else if (std::string(argv[i]) ==
"--me-mode" && i + 1 < argc) {
161 opt_meMode =
static_cast<unsigned int>(atoi(argv[i + 1]));
162 if (opt_meMode < 0 || opt_meMode > 1) {
163 usage(argv, 0, opt_data_path, opt_model_path, opt_first_frame);
168 else if (std::string(argv[i]) ==
"--klt-mode" && i + 1 < argc) {
169 opt_kltMode =
static_cast<unsigned int>(atoi(argv[i + 1]));
170 if (opt_kltMode < 0 || opt_kltMode > 1) {
171 usage(argv, 0, opt_data_path, opt_model_path, opt_first_frame);
176 else if (std::string(argv[i]) ==
"--display-ground-truth") {
177 opt_display_ground_truth =
true;
179 else if (std::string(argv[i]) ==
"--step-by-step") {
180 opt_step_by_step =
true;
182 else if (std::string(argv[i]) ==
"--first-frame" && i + 1 < argc) {
183 opt_first_frame =
static_cast<unsigned int>(atoi(argv[i + 1]));
186 else if (std::string(argv[i]) ==
"--help" || std::string(argv[i]) ==
"-h") {
187 usage(argv, 0, opt_data_path, opt_model_path, opt_first_frame);
191 usage(argv, i, opt_data_path, opt_model_path, opt_first_frame);
196 disable_depth = opt_denseMode == 0 && opt_normalsMode == 0;
202 std::string color_camera_name =
"Camera_L";
203 std::string depth_camera_name =
"Camera_R";
211 std::cout <<
"Input data" << std::endl;
212 std::cout <<
" Color images : " << video_color_images << std::endl;
213 std::cout <<
" Depth images : " << (disable_depth ?
"Disabled" : video_depth_images) << std::endl;
214 std::cout <<
" Extrinsics : " << (disable_depth ?
"Disabled" : extrinsic_file) << std::endl;
215 std::cout <<
" Color intrinsics: " << color_intrinsic_file << std::endl;
216 std::cout <<
" Depth intrinsics: " << (disable_depth ?
"Disabled" : depth_intrinsic_file) << std::endl;
217 std::cout <<
" Ground truth : " << ground_truth << std::endl;
218 std::cout <<
"Tracker settings" << std::endl;
219 std::cout <<
" Color config : " << mbt_config_color << std::endl;
220 std::cout <<
" Depth config : " << mbt_config_depth << std::endl;
221 std::cout <<
" CAD model : " << mbt_cad_model << std::endl;
222 std::cout <<
" First frame : " << opt_first_frame << std::endl;
223 std::cout <<
" Step by step : " << opt_step_by_step << std::endl;
224 if (opt_display_ground_truth) {
225 std::cout <<
" Ground truth is used to project the cad model (no tracking)" << std::endl;
228 std::cout <<
" Init file : " << mbt_init_file << std::endl;
229 std::cout <<
" Features : moving-edges " << (opt_disable_klt ?
"" :
"+ keypoints") << (disable_depth ?
"" :
" + depth") << std::endl;
234 int colorTracker = 0;
237 if (opt_meMode == 1) {
240 if (opt_kltMode == 1) {
241#if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
244 std::cerr <<
"Warning: keypoints cannot be used as features since ViSP is not built with OpenCV 3rd party" << std::endl;
248 if (colorTracker == 0) {
249 std::cerr <<
"You should use at least one type of color feature. If OpenCV is not installed, KLT features are disabled" << std::endl;
255 if (!disable_depth) {
256 int depthTracker = 0;
257 if (opt_denseMode == 1) {
260 if (opt_normalsMode == 1) {
268 if (!disable_depth) {
269 tracker.loadConfigFile(mbt_config_color, mbt_config_depth,
true);
272 tracker.loadConfigFile(mbt_config_color);
275 tracker.loadModel(mbt_cad_model);
282 std::cout <<
"Cannot found intrinsics for camera " << color_camera_name << std::endl;
286 std::cout <<
"Cannot found intrinsics for camera " << depth_camera_name << std::endl;
290 tracker.setCameraParameters(cam_color, cam_depth);
292 tracker.setCameraParameters(cam_color);
296 tracker.getCameraParameters(cam_color, cam_depth);
298 tracker.getCameraParameters(cam_color);
299 tracker.setDisplayFeatures(
true);
300 std::cout <<
"cam_color:\n" <<
cam_color << std::endl;
303 std::cout <<
"cam_depth:\n" <<
cam_depth << std::endl;
308 std::vector<vpColVector> pointcloud;
311 unsigned int frame_cpt = opt_first_frame;
312 read_data(frame_cpt, video_color_images, video_depth_images, disable_depth, ground_truth,
313 I, I_depth_raw, depth_width, depth_height, pointcloud, cam_depth, cMo_ground_truth);
316#if defined(VISP_HAVE_DISPLAY)
317#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
325 display1->init(I, 0, 0,
"Color image");
326 if (!disable_depth) {
327 display2->init(I_depth,
static_cast<int>(I.getWidth()), 0,
"Depth image");
334 if (!disable_depth) {
336 tracker.setCameraTransformationMatrix(
"Camera2", depth_M_color);
337 std::cout <<
"depth_M_color:\n" <<
depth_M_color << std::endl;
340 if (opt_display_ground_truth) {
341 tracker.initFromPose(I, cMo_ground_truth);
344 tracker.initClick(I, mbt_init_file,
true);
349 while (!quit &&
read_data(frame_cpt, video_color_images, video_depth_images, disable_depth,
350 ground_truth, I, I_depth_raw, depth_width, depth_height, pointcloud, cam_depth,
356 if (opt_display_ground_truth) {
357 tracker.initFromPose(I, cMo_ground_truth);
360 if (!disable_depth) {
361 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
362 std::map<std::string, const std::vector<vpColVector> *> mapOfPointClouds;
363 std::map<std::string, unsigned int> mapOfPointCloudWidths;
364 std::map<std::string, unsigned int> mapOfPointCloudHeights;
366 mapOfImages[
"Camera1"] = &I;
367 mapOfPointClouds[
"Camera2"] = &pointcloud;
370 tracker.track(mapOfImages, mapOfPointClouds, mapOfPointCloudWidths, mapOfPointCloudHeights);
378 std::cout <<
"\nFrame: " << frame_cpt << std::endl;
379 if (!opt_display_ground_truth)
380 std::cout <<
"cMo:\n" <<
cMo << std::endl;
381 std::cout <<
"cMo ground truth:\n" << cMo_ground_truth << std::endl;
382 if (!disable_depth) {
383 tracker.display(I, I_depth, cMo, depth_M_color * cMo, cam_color, cam_depth,
vpColor::red, 2);
391 std::ostringstream oss;
392 oss <<
"Frame: " << frame_cpt;
394 if (opt_step_by_step) {
402 if (!opt_display_ground_truth) {
404 std::stringstream ss;
405 ss <<
"Nb features: " <<
tracker.getError().size();
409 std::stringstream ss;
410 ss <<
"Features: edges " <<
tracker.getNbFeaturesEdge() <<
", klt " <<
tracker.getNbFeaturesKlt()
411 <<
", dense depth " <<
tracker.getNbFeaturesDepthDense() <<
", depth normals " <<
tracker.getNbFeaturesDepthNormal();
426 opt_step_by_step =
true;
429 opt_step_by_step =
false;
435 opt_step_by_step =
true;
445 catch (std::exception &e) {
446 std::cerr <<
"Catch exception: " <<
e.what() << std::endl;
449#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11) && defined(VISP_HAVE_DISPLAY)
450 if (display1 !=
nullptr) {
453 if (display2 !=
nullptr) {
463 std::cout <<
"To run this tutorial, ViSP should be built with OpenCV and pugixml libraries." << std::endl;
Generic class defining intrinsic camera parameters.
@ perspectiveProjWithoutDistortion
Perspective projection without distortion model.
static const vpColor none
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 setTitle(const vpImage< unsigned char > &I, const std::string &windowtitle)
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.
void load(std::ifstream &f)
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.
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Real-time 6D object pose tracking using its CAD model.
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
XML parser to load and save intrinsic camera parameters.
read_data(CameraParameters|None cam_depth, ImageGray I, rs.pipeline pipe)
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.