4 #include <visp3/core/vpConfig.h>
6 #if defined(VISP_HAVE_OCCIPITAL_STRUCTURE) && defined(VISP_HAVE_OPENCV) && defined(VISP_HAVE_PUGIXML)
7 #include <visp3/core/vpDisplay.h>
8 #include <visp3/core/vpIoTools.h>
9 #include <visp3/core/vpXmlParserCamera.h>
10 #include <visp3/gui/vpDisplayGDI.h>
11 #include <visp3/gui/vpDisplayOpenCV.h>
12 #include <visp3/gui/vpDisplayX.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;
190 #elif defined(VISP_HAVE_GDI)
192 #elif defined(HAVE_OPENCV_HIGHGUI)
195 if (use_edges || use_klt)
196 d1.
init(I_gray, _posx, _posy,
"Color stream");
198 d2.init(I_depth, _posx + I_gray.getWidth() + 10, _posy,
"Depth stream");
201 sc.
acquire((
unsigned char *)I_color.bitmap, (
unsigned char *)I_depth_raw.bitmap,
nullptr,
nullptr,
nullptr);
203 if (use_edges || use_klt) {
225 std::vector<int> trackerTypes;
226 if (use_edges && use_klt)
231 trackerTypes.push_back(vpMbGenericTracker::KLT_TRACKER);
238 std::map<std::string, vpHomogeneousMatrix> mapOfCameraTransformations;
239 std::map<std::string, const vpImage<unsigned char> *> mapOfImages;
240 std::map<std::string, std::string> mapOfInitFiles;
241 std::map<std::string, const std::vector<vpColVector> *> mapOfPointclouds;
242 std::map<std::string, unsigned int> mapOfWidths, mapOfHeights;
243 std::map<std::string, vpHomogeneousMatrix> mapOfCameraPoses;
245 std::vector<vpColVector> pointcloud;
249 if ((use_edges || use_klt) && use_depth) {
250 tracker.loadConfigFile(config_color, config_depth);
251 tracker.loadModel(model_color, model_depth);
252 std::cout <<
"Sensor internal depth_M_color: \n" << depth_M_color << std::endl;
253 mapOfCameraTransformations[
"Camera2"] = depth_M_color;
254 tracker.setCameraTransformationMatrix(mapOfCameraTransformations);
255 mapOfImages[
"Camera1"] = &I_gray;
256 mapOfImages[
"Camera2"] = &I_depth;
257 mapOfInitFiles[
"Camera1"] = init_file;
258 tracker.setCameraParameters(cam_color, cam_depth);
260 else if (use_edges || use_klt) {
261 tracker.loadConfigFile(config_color);
262 tracker.loadModel(model_color);
263 tracker.setCameraParameters(cam_color);
265 else if (use_depth) {
266 tracker.loadConfigFile(config_depth);
267 tracker.loadModel(model_depth);
268 tracker.setCameraParameters(cam_depth);
271 tracker.setDisplayFeatures(
true);
272 tracker.setOgreVisibilityTest(use_ogre);
273 tracker.setScanLineVisibilityTest(use_scanline);
274 tracker.setProjectionErrorComputation(
true);
275 tracker.setProjectionErrorDisplay(display_projection_error);
277 #if (defined(VISP_HAVE_OPENCV_NONFREE) || defined(VISP_HAVE_OPENCV_XFEATURES2D)) || \
278 (VISP_HAVE_OPENCV_VERSION >= 0x030411 && CV_MAJOR_VERSION < 4) || (VISP_HAVE_OPENCV_VERSION >= 0x040400)
279 std::string detectorName =
"SIFT";
280 std::string extractorName =
"SIFT";
281 std::string matcherName =
"BruteForce";
283 std::string detectorName =
"FAST";
284 std::string extractorName =
"ORB";
285 std::string matcherName =
"BruteForce-Hamming";
288 if (learn || auto_init) {
292 #if !(defined(VISP_HAVE_OPENCV_NONFREE) || defined(VISP_HAVE_OPENCV_XFEATURES2D))
293 #if (VISP_HAVE_OPENCV_VERSION < 0x030000)
294 keypoint.setDetectorParameter(
"ORB",
"nLevels", 1);
296 cv::Ptr<cv::ORB> orb_detector = keypoint.
getDetector(
"ORB").dynamicCast<cv::ORB>();
298 orb_detector->setNLevels(1);
306 std::cout <<
"Cannot enable auto detection. Learning file \"" << learning_data <<
"\" doesn't exist" << std::endl;
312 if ((use_edges || use_klt) && use_depth)
313 tracker.initClick(mapOfImages, mapOfInitFiles,
true);
314 else if (use_edges || use_klt)
315 tracker.initClick(I_gray, init_file,
true);
317 tracker.initClick(I_depth, init_file,
true);
323 bool run_auto_init =
false;
325 run_auto_init =
true;
327 std::vector<double> times_vec;
333 bool learn_position =
false;
339 bool tracking_failed =
false;
342 sc.
acquire((
unsigned char *)I_color.bitmap, (
unsigned char *)I_depth_raw.bitmap, &pointcloud);
344 if (use_edges || use_klt || run_auto_init) {
353 if ((use_edges || use_klt) && use_depth) {
354 mapOfImages[
"Camera1"] = &I_gray;
355 mapOfPointclouds[
"Camera2"] = &pointcloud;
356 mapOfWidths[
"Camera2"] = width;
357 mapOfHeights[
"Camera2"] = height;
359 else if (use_edges || use_klt) {
360 mapOfImages[
"Camera"] = &I_gray;
362 else if (use_depth) {
363 mapOfPointclouds[
"Camera"] = &pointcloud;
364 mapOfWidths[
"Camera"] = width;
365 mapOfHeights[
"Camera"] = height;
370 if (keypoint.
matchPoint(I_gray, cam_color, cMo)) {
371 std::cout <<
"Auto init succeed" << std::endl;
372 if ((use_edges || use_klt) && use_depth) {
373 mapOfCameraPoses[
"Camera1"] = cMo;
374 mapOfCameraPoses[
"Camera2"] = depth_M_color * cMo;
375 tracker.initFromPose(mapOfImages, mapOfCameraPoses);
377 else if (use_edges || use_klt) {
378 tracker.initFromPose(I_gray, cMo);
380 else if (use_depth) {
381 tracker.initFromPose(I_depth, depth_M_color * cMo);
385 if (use_edges || use_klt) {
399 tracker.setDisplayFeatures(
true);
401 run_auto_init =
false;
403 if ((use_edges || use_klt) && use_depth) {
404 tracker.track(mapOfImages, mapOfPointclouds, mapOfWidths, mapOfHeights);
406 else if (use_edges || use_klt) {
407 tracker.track(I_gray);
409 else if (use_depth) {
410 tracker.track(mapOfImages, mapOfPointclouds, mapOfWidths, mapOfHeights);
415 tracking_failed =
true;
417 std::cout <<
"Tracker needs to restart (tracking exception)" << std::endl;
418 run_auto_init =
true;
423 cMo = tracker.getPose();
426 double proj_error = 0;
429 proj_error = tracker.getProjectionError();
432 proj_error = tracker.computeCurrentProjectionError(I_gray, cMo, cam_color);
435 if (auto_init && proj_error > proj_error_threshold) {
436 std::cout <<
"Tracker needs to restart (projection error detected: " << proj_error <<
")" << std::endl;
437 run_auto_init =
true;
438 tracking_failed =
true;
442 if (!tracking_failed) {
444 tracker.setDisplayFeatures(
true);
446 if ((use_edges || use_klt) && use_depth) {
447 tracker.display(I_gray, I_depth, cMo, depth_M_color * cMo, cam_color, cam_depth,
vpColor::red, 3);
451 else if (use_edges || use_klt) {
452 tracker.display(I_gray, cMo, cam_color,
vpColor::red, 3);
455 else if (use_depth) {
456 tracker.display(I_depth, cMo, cam_depth,
vpColor::red, 3);
461 std::stringstream ss;
462 ss <<
"Nb features: " << tracker.getError().size();
466 std::stringstream ss;
467 ss <<
"Features: edges " << tracker.getNbFeaturesEdge() <<
", klt " << tracker.getNbFeaturesKlt()
468 <<
", depth " << tracker.getNbFeaturesDepthDense();
473 std::stringstream ss;
474 ss <<
"Loop time: " << loop_t <<
" ms";
477 if (use_edges || use_klt) {
493 learn_position =
true;
496 run_auto_init =
true;
510 if (learn_position) {
512 std::vector<cv::KeyPoint> trainKeyPoints;
513 keypoint.
detect(I_gray, trainKeyPoints);
516 std::vector<vpPolygon> polygons;
517 std::vector<std::vector<vpPoint> > roisPt;
518 std::pair<std::vector<vpPolygon>, std::vector<std::vector<vpPoint> > > pair = tracker.getPolygonFaces();
519 polygons = pair.first;
520 roisPt = pair.second;
523 std::vector<cv::Point3f> points3f;
527 keypoint.
buildReference(I_gray, trainKeyPoints, points3f,
true, learn_id++);
530 for (std::vector<cv::KeyPoint>::const_iterator it = trainKeyPoints.begin(); it != trainKeyPoints.end(); ++it) {
533 learn_position =
false;
534 std::cout <<
"Data learned" << std::endl;
537 times_vec.push_back(loop_t);
540 std::cout <<
"Save learning file: " << learning_data << std::endl;
545 std::cout <<
"Catch an exception: " << e.
what() << std::endl;
548 if (!times_vec.empty()) {
556 #elif defined(VISP_HAVE_OCCIPITAL_STRUCTURE)
559 std::cout <<
"Install OpenCV 3rd party, configure and build ViSP again to use this example" << std::endl;
565 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
Display for windows using GDI (available on any windows 32 platform).
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="") VP_OVERRIDE
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 detection (and descriptors extraction) and matching thanks to OpenCV libr...
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)
VISP_EXPORT double measureTimeMs()