4 #include <visp3/core/vpConfig.h>
6 #if defined(VISP_HAVE_OCCIPITAL_STRUCTURE) && defined(VISP_HAVE_PUGIXML) && \
7 (((VISP_HAVE_OPENCV_VERSION < 0x050000) && (defined(HAVE_OPENCV_FEATURES2D) || defined(HAVE_OPENCV_XFEATURES2D))) || ((VISP_HAVE_OPENCV_VERSION >= 0x050000) && defined(HAVE_OPENCV_FEATURES)))
9 #include <visp3/core/vpDisplay.h>
10 #include <visp3/core/vpIoTools.h>
11 #include <visp3/core/vpXmlParserCamera.h>
12 #include <visp3/gui/vpDisplayFactory.h>
13 #include <visp3/mbt/vpMbGenericTracker.h>
14 #include <visp3/sensor/vpOccipitalStructure.h>
15 #include <visp3/vision/vpKeyPoint.h>
17 int main(
int argc,
char *argv[])
19 #ifdef ENABLE_VISP_NAMESPACE
23 std::string config_color =
"", config_depth =
"";
24 std::string model_color =
"", model_depth =
"";
25 std::string init_file =
"";
26 bool use_ogre =
false;
27 bool use_scanline =
false;
28 bool use_edges =
true;
30 bool use_depth =
true;
32 bool auto_init =
false;
33 double proj_error_threshold = 25;
34 std::string learning_data =
"learning/data-learned.bin";
35 bool display_projection_error =
false;
37 for (
int i = 1; i < argc; i++) {
38 if (std::string(argv[i]) ==
"--config_color" && i + 1 < argc) {
39 config_color = std::string(argv[i + 1]);
41 else if (std::string(argv[i]) ==
"--config_depth" && i + 1 < argc) {
42 config_depth = std::string(argv[i + 1]);
44 else if (std::string(argv[i]) ==
"--model_color" && i + 1 < argc) {
45 model_color = std::string(argv[i + 1]);
47 else if (std::string(argv[i]) ==
"--model_depth" && i + 1 < argc) {
48 model_depth = std::string(argv[i + 1]);
50 else if (std::string(argv[i]) ==
"--init_file" && i + 1 < argc) {
51 init_file = std::string(argv[i + 1]);
53 else if (std::string(argv[i]) ==
"--proj_error_threshold" && i + 1 < argc) {
54 proj_error_threshold = std::atof(argv[i + 1]);
56 else if (std::string(argv[i]) ==
"--use_ogre") {
59 else if (std::string(argv[i]) ==
"--use_scanline") {
62 else if (std::string(argv[i]) ==
"--use_edges" && i + 1 < argc) {
63 use_edges = (std::atoi(argv[i + 1]) == 0 ? false :
true);
65 else if (std::string(argv[i]) ==
"--use_klt" && i + 1 < argc) {
66 use_klt = (std::atoi(argv[i + 1]) == 0 ? false :
true);
68 else if (std::string(argv[i]) ==
"--use_depth" && i + 1 < argc) {
69 use_depth = (std::atoi(argv[i + 1]) == 0 ? false :
true);
71 else if (std::string(argv[i]) ==
"--learn") {
74 else if (std::string(argv[i]) ==
"--learning_data" && i + 1 < argc) {
75 learning_data = argv[i + 1];
77 else if (std::string(argv[i]) ==
"--auto_init") {
80 else if (std::string(argv[i]) ==
"--display_proj_error") {
81 display_projection_error =
true;
83 else if (std::string(argv[i]) ==
"--help" || std::string(argv[i]) ==
"-h") {
84 std::cout <<
"Usage: \n"
86 <<
" [--model_color <object.cao>] [--model_depth <object.cao>]"
87 " [--config_color <object.xml>] [--config_depth <object.xml>]"
88 " [--init_file <object.init>] [--use_ogre] [--use_scanline]"
89 " [--proj_error_threshold <threshold between 0 and 90> (default: "
90 << proj_error_threshold
92 " [--use_edges <0|1> (default: 1)] [--use_klt <0|1> (default: 1)] [--use_depth <0|1> (default: 1)]"
93 " [--learn] [--auto_init] [--learning_data <path to .bin> (default: learning/data-learned.bin)]"
94 " [--display_proj_error]"
97 std::cout <<
"\n** How to track a 4.2 cm width cube with manual initialization:\n"
98 << argv[0] <<
" --model_color model/cube/cube.cao --use_edges 1 --use_klt 1 --use_depth 1" << std::endl;
99 std::cout <<
"\n** How to learn the cube and create a learning database:\n"
100 << argv[0] <<
" --model_color model/cube/cube.cao --use_edges 1 --use_klt 1 --use_depth 1 --learn"
102 std::cout <<
"\n** How to track the cube with initialization from learning database:\n"
103 << argv[0] <<
" --model_color model/cube/cube.cao --use_edges 1 --use_klt 1 --use_depth 1 --auto_init"
110 if (model_depth.empty()) {
111 model_depth = model_color;
114 if (config_color.empty()) {
115 config_color = (parentname.empty() ?
"" : (parentname +
"/")) +
vpIoTools::getNameWE(model_color) +
".xml";
117 if (config_depth.empty()) {
118 config_depth = (parentname.empty() ?
"" : (parentname +
"/")) +
vpIoTools::getNameWE(model_color) +
"_depth.xml";
120 if (init_file.empty()) {
121 init_file = (parentname.empty() ?
"" : (parentname +
"/")) +
vpIoTools::getNameWE(model_color) +
".init";
123 std::cout <<
"Tracked features: " << std::endl;
124 std::cout <<
" Use edges : " << use_edges << std::endl;
125 std::cout <<
" Use klt : " << use_klt << std::endl;
126 std::cout <<
" Use depth : " << use_depth << std::endl;
127 std::cout <<
"Tracker options: " << std::endl;
128 std::cout <<
" Use ogre : " << use_ogre << std::endl;
129 std::cout <<
" Use scanline: " << use_scanline << std::endl;
130 std::cout <<
" Proj. error : " << proj_error_threshold << std::endl;
131 std::cout <<
" Display proj. error: " << display_projection_error << std::endl;
132 std::cout <<
"Config files: " << std::endl;
133 std::cout <<
" Config color: "
134 <<
"\"" << config_color <<
"\"" << std::endl;
135 std::cout <<
" Config depth: "
136 <<
"\"" << config_depth <<
"\"" << std::endl;
137 std::cout <<
" Model color : "
138 <<
"\"" << model_color <<
"\"" << std::endl;
139 std::cout <<
" Model depth : "
140 <<
"\"" << model_depth <<
"\"" << std::endl;
141 std::cout <<
" Init file : "
142 <<
"\"" << init_file <<
"\"" << std::endl;
143 std::cout <<
"Learning options : " << std::endl;
144 std::cout <<
" Learn : " << learn << std::endl;
145 std::cout <<
" Auto init : " << auto_init << std::endl;
146 std::cout <<
" Learning data: " << learning_data << std::endl;
148 if (!use_edges && !use_klt && !use_depth) {
149 std::cout <<
"You must choose at least one visual features between edge, KLT and depth." << std::endl;
153 if (config_color.empty() || config_depth.empty() || model_color.empty() || model_depth.empty() || init_file.empty()) {
154 std::cout <<
"config_color.empty() || config_depth.empty() || model_color.empty() || model_depth.empty() || "
161 ST::CaptureSessionSettings settings;
162 settings.source = ST::CaptureSessionSourceId::StructureCore;
163 settings.structureCore.visibleEnabled =
true;
164 settings.applyExpensiveCorrection =
true;
170 std::cout <<
"Catch an exception: " << e.
what() << std::endl;
171 std::cout <<
"Check if the Structure Core camera is connected..." << std::endl;
179 std::cout <<
"Sensor internal camera parameters for color camera: " << cam_color << std::endl;
180 std::cout <<
"Sensor internal camera parameters for depth camera: " << cam_depth << std::endl;
186 unsigned int _posx = 100, _posy = 50;
188 #ifdef VISP_HAVE_DISPLAY
189 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
196 if (use_edges || use_klt)
197 display1->init(I_gray, _posx, _posy,
"Color stream");
199 display2->init(I_depth, _posx + I_gray.getWidth() + 10, _posy,
"Depth stream");
203 sc.
acquire((
unsigned char *)I_color.bitmap, (
unsigned char *)I_depth_raw.bitmap,
nullptr,
nullptr,
nullptr);
205 if (use_edges || use_klt) {
227 std::vector<int> trackerTypes;
228 if (use_edges && use_klt)
233 trackerTypes.push_back(vpMbGenericTracker::KLT_TRACKER);
240 std::map<std::string, vpHomogeneousMatrix> mapOfCameraTransformations;
241 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
242 std::map<std::string, std::string> mapOfInitFiles;
243 std::map<std::string, const std::vector<vpColVector> *> mapOfPointclouds;
244 std::map<std::string, unsigned int> mapOfWidths, mapOfHeights;
245 std::map<std::string, vpHomogeneousMatrix> mapOfCameraPoses;
247 std::vector<vpColVector> pointcloud;
251 if ((use_edges || use_klt) && use_depth) {
252 tracker.loadConfigFile(config_color, config_depth);
253 tracker.loadModel(model_color, model_depth);
254 std::cout <<
"Sensor internal depth_M_color: \n" << depth_M_color << std::endl;
255 mapOfCameraTransformations[
"Camera2"] = depth_M_color;
256 tracker.setCameraTransformationMatrix(mapOfCameraTransformations);
257 mapOfImages[
"Camera1"] = &I_gray;
258 mapOfImages[
"Camera2"] = &I_depth;
259 mapOfInitFiles[
"Camera1"] = init_file;
260 tracker.setCameraParameters(cam_color, cam_depth);
262 else if (use_edges || use_klt) {
263 tracker.loadConfigFile(config_color);
264 tracker.loadModel(model_color);
265 tracker.setCameraParameters(cam_color);
267 else if (use_depth) {
268 tracker.loadConfigFile(config_depth);
269 tracker.loadModel(model_depth);
270 tracker.setCameraParameters(cam_depth);
273 tracker.setDisplayFeatures(
true);
274 tracker.setOgreVisibilityTest(use_ogre);
275 tracker.setScanLineVisibilityTest(use_scanline);
276 tracker.setProjectionErrorComputation(
true);
277 tracker.setProjectionErrorDisplay(display_projection_error);
279 #if ((VISP_HAVE_OPENCV_VERSION < 0x050000) && defined(HAVE_OPENCV_XFEATURES2D)) || ((VISP_HAVE_OPENCV_VERSION >= 0x050000) && defined(HAVE_OPENCV_FEATURES))
280 std::string detectorName =
"SIFT";
281 std::string extractorName =
"SIFT";
282 std::string matcherName =
"BruteForce";
283 #elif ((VISP_HAVE_OPENCV_VERSION < 0x050000) && defined(HAVE_OPENCV_FEATURES2D)) || ((VISP_HAVE_OPENCV_VERSION >= 0x050000) && defined(HAVE_OPENCV_FEATURES))
284 std::string detectorName =
"FAST";
285 std::string extractorName =
"ORB";
287 std::string matcherName =
"BruteForce-Hamming";
290 if (learn || auto_init) {
294 #if ((VISP_HAVE_OPENCV_VERSION < 0x050000) && defined(HAVE_OPENCV_FEATURES2D)) || ((VISP_HAVE_OPENCV_VERSION >= 0x050000) && defined(HAVE_OPENCV_FEATURES))
295 cv::Ptr<cv::ORB> orb_detector = keypoint.
getDetector(
"ORB").dynamicCast<cv::ORB>();
297 orb_detector->setNLevels(1);
304 std::cout <<
"Cannot enable auto detection. Learning file \"" << learning_data <<
"\" doesn't exist" << std::endl;
310 if ((use_edges || use_klt) && use_depth)
311 tracker.initClick(mapOfImages, mapOfInitFiles,
true);
312 else if (use_edges || use_klt)
313 tracker.initClick(I_gray, init_file,
true);
315 tracker.initClick(I_depth, init_file,
true);
321 bool run_auto_init =
false;
323 run_auto_init =
true;
325 std::vector<double> times_vec;
331 bool learn_position =
false;
337 bool tracking_failed =
false;
340 sc.
acquire((
unsigned char *)I_color.bitmap, (
unsigned char *)I_depth_raw.bitmap, &pointcloud);
342 if (use_edges || use_klt || run_auto_init) {
351 if ((use_edges || use_klt) && use_depth) {
352 mapOfImages[
"Camera1"] = &I_gray;
353 mapOfPointclouds[
"Camera2"] = &pointcloud;
354 mapOfWidths[
"Camera2"] = width;
355 mapOfHeights[
"Camera2"] = height;
357 else if (use_edges || use_klt) {
358 mapOfImages[
"Camera"] = &I_gray;
360 else if (use_depth) {
361 mapOfPointclouds[
"Camera"] = &pointcloud;
362 mapOfWidths[
"Camera"] = width;
363 mapOfHeights[
"Camera"] = height;
368 if (keypoint.
matchPoint(I_gray, cam_color, cMo)) {
369 std::cout <<
"Auto init succeed" << std::endl;
370 if ((use_edges || use_klt) && use_depth) {
371 mapOfCameraPoses[
"Camera1"] = cMo;
372 mapOfCameraPoses[
"Camera2"] = depth_M_color * cMo;
373 tracker.initFromPose(mapOfImages, mapOfCameraPoses);
375 else if (use_edges || use_klt) {
376 tracker.initFromPose(I_gray, cMo);
378 else if (use_depth) {
379 tracker.initFromPose(I_depth, depth_M_color * cMo);
383 if (use_edges || use_klt) {
397 tracker.setDisplayFeatures(
true);
399 run_auto_init =
false;
401 if ((use_edges || use_klt) && use_depth) {
402 tracker.track(mapOfImages, mapOfPointclouds, mapOfWidths, mapOfHeights);
404 else if (use_edges || use_klt) {
405 tracker.track(I_gray);
407 else if (use_depth) {
408 tracker.track(mapOfImages, mapOfPointclouds, mapOfWidths, mapOfHeights);
413 tracking_failed =
true;
415 std::cout <<
"Tracker needs to restart (tracking exception)" << std::endl;
416 run_auto_init =
true;
421 cMo = tracker.getPose();
424 double proj_error = 0;
427 proj_error = tracker.getProjectionError();
430 proj_error = tracker.computeCurrentProjectionError(I_gray, cMo, cam_color);
433 if (auto_init && proj_error > proj_error_threshold) {
434 std::cout <<
"Tracker needs to restart (projection error detected: " << proj_error <<
")" << std::endl;
435 run_auto_init =
true;
436 tracking_failed =
true;
440 if (!tracking_failed) {
442 tracker.setDisplayFeatures(
true);
444 if ((use_edges || use_klt) && use_depth) {
445 tracker.display(I_gray, I_depth, cMo, depth_M_color * cMo, cam_color, cam_depth,
vpColor::red, 3);
449 else if (use_edges || use_klt) {
450 tracker.display(I_gray, cMo, cam_color,
vpColor::red, 3);
453 else if (use_depth) {
454 tracker.display(I_depth, cMo, cam_depth,
vpColor::red, 3);
459 std::stringstream ss;
460 ss <<
"Nb features: " << tracker.getError().size();
464 std::stringstream ss;
465 ss <<
"Features: edges " << tracker.getNbFeaturesEdge() <<
", klt " << tracker.getNbFeaturesKlt()
466 <<
", depth " << tracker.getNbFeaturesDepthDense();
471 std::stringstream ss;
472 ss <<
"Loop time: " << loop_t <<
" ms";
475 if (use_edges || use_klt) {
491 learn_position =
true;
494 run_auto_init =
true;
508 if (learn_position) {
510 std::vector<cv::KeyPoint> trainKeyPoints;
511 keypoint.
detect(I_gray, trainKeyPoints);
514 std::vector<vpPolygon> polygons;
515 std::vector<std::vector<vpPoint> > roisPt;
516 std::pair<std::vector<vpPolygon>, std::vector<std::vector<vpPoint> > > pair = tracker.getPolygonFaces();
517 polygons = pair.first;
518 roisPt = pair.second;
521 std::vector<cv::Point3f> points3f;
525 keypoint.
buildReference(I_gray, trainKeyPoints, points3f,
true, learn_id++);
528 for (std::vector<cv::KeyPoint>::const_iterator it = trainKeyPoints.begin(); it != trainKeyPoints.end(); ++it) {
531 learn_position =
false;
532 std::cout <<
"Data learned" << std::endl;
535 times_vec.push_back(loop_t);
538 std::cout <<
"Save learning file: " << learning_data << std::endl;
543 std::cout <<
"Catch an exception: " << e.
what() << std::endl;
546 #if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11) && defined(VISP_HAVE_DISPLAY)
547 if (display1 !=
nullptr) {
550 if (display2 !=
nullptr) {
555 if (!times_vec.empty()) {
563 #elif defined(VISP_HAVE_OCCIPITAL_STRUCTURE)
566 std::cout <<
"Install OpenCV 3rd party, configure and build ViSP again to use this example" << std::endl;
572 std::cout <<
"Install libStructure 3rd party, configure and build ViSP again to use this example" << std::endl;
Generic class defining intrinsic camera parameters.
static const vpColor none
static const vpColor yellow
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 displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
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)
error that can be emitted by ViSP classes.
const std::string & getStringMessage() const
const char * what() const
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpHomogeneousMatrix inverse() const
static void createDepthHistogram(const vpImage< uint16_t > &src_depth, vpImage< vpRGBa > &dest_rgba)
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
Class that allows keypoints 2D features detection (and descriptors extraction) and matching thanks to...
unsigned int matchPoint(const vpImage< unsigned char > &I)
void setExtractor(const vpFeatureDescriptorType &extractorType)
void loadLearningData(const std::string &filename, bool binaryMode=false, bool append=false)
void detect(const vpImage< unsigned char > &I, std::vector< cv::KeyPoint > &keyPoints, const vpRect &rectangle=vpRect())
static void compute3DForPointsInPolygons(const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, std::vector< cv::KeyPoint > &candidates, const std::vector< vpPolygon > &polygons, const std::vector< std::vector< vpPoint > > &roisPt, std::vector< cv::Point3f > &points, cv::Mat *descriptors=nullptr)
void setMatcher(const std::string &matcherName)
void saveLearningData(const std::string &filename, bool binaryMode=false, bool saveTrainingImages=true)
void setDetector(const vpFeatureDetectorType &detectorType)
unsigned int buildReference(const vpImage< unsigned char > &I)
cv::Ptr< cv::FeatureDetector > getDetector(const vpFeatureDetectorType &type) const
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)
Real-time 6D object pose tracking using its CAD model.
unsigned int getHeight(vpOccipitalStructureStream stream_type)
vpCameraParameters getCameraParameters(const vpOccipitalStructureStream stream_type, vpCameraParameters::vpCameraParametersProjType type=vpCameraParameters::perspectiveProjWithoutDistortion)
void acquire(vpImage< unsigned char > &gray, bool undistorted=false, double *ts=nullptr)
unsigned int getWidth(vpOccipitalStructureStream stream_type)
vpHomogeneousMatrix getTransform(const vpOccipitalStructureStream from, const vpOccipitalStructureStream to)
bool open(const ST::CaptureSessionSettings &settings)
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.
VISP_EXPORT double measureTimeMs()