4 #include <visp3/core/vpConfig.h>
13 #if defined(VISP_HAVE_APRILTAG) && defined(VISP_HAVE_MODULE_MBT) && \
14 (defined(VISP_HAVE_V4L2) || \
15 ((VISP_HAVE_OPENCV_VERSION < 0x030000) && defined(HAVE_OPENCV_HIGHGUI)) || \
16 ((VISP_HAVE_OPENCV_VERSION >= 0x030000) && defined(HAVE_OPENCV_VIDEOIO)))
22 #ifdef VISP_HAVE_MODULE_SENSOR
23 #include <visp3/sensor/vpV4l2Grabber.h>
25 #include <visp3/core/vpXmlParserCamera.h>
26 #include <visp3/detection/vpDetectorAprilTag.h>
27 #include <visp3/gui/vpDisplayGDI.h>
28 #include <visp3/gui/vpDisplayOpenCV.h>
29 #include <visp3/gui/vpDisplayX.h>
30 #include <visp3/mbt/vpMbGenericTracker.h>
32 #if (VISP_HAVE_OPENCV_VERSION < 0x030000) && defined(HAVE_OPENCV_HIGHGUI)
33 #include <opencv2/highgui/highgui.hpp>
34 #elif (VISP_HAVE_OPENCV_VERSION >= 0x030000) && defined(HAVE_OPENCV_VIDEOIO)
35 #include <opencv2/videoio/videoio.hpp>
38 #ifdef ENABLE_VISP_NAMESPACE
42 typedef enum { state_detection, state_tracking, state_quit } state_t;
46 void createCaoFile(
double cubeEdgeSize)
48 std::ofstream fileStream;
49 fileStream.open(
"cube.cao", std::ofstream::out | std::ofstream::trunc);
51 fileStream <<
"# 3D Points\n";
52 fileStream <<
"8 # Number of points\n";
53 fileStream << cubeEdgeSize / 2 <<
" " << cubeEdgeSize / 2 <<
" " << 0 <<
" # Point 0: (X, Y, Z)\n";
54 fileStream << cubeEdgeSize / 2 <<
" " << -cubeEdgeSize / 2 <<
" " << 0 <<
" # Point 1\n";
55 fileStream << -cubeEdgeSize / 2 <<
" " << -cubeEdgeSize / 2 <<
" " << 0 <<
" # Point 2\n";
56 fileStream << -cubeEdgeSize / 2 <<
" " << cubeEdgeSize / 2 <<
" " << 0 <<
" # Point 3\n";
57 fileStream << -cubeEdgeSize / 2 <<
" " << cubeEdgeSize / 2 <<
" " << -cubeEdgeSize <<
" # Point 4\n";
58 fileStream << -cubeEdgeSize / 2 <<
" " << -cubeEdgeSize / 2 <<
" " << -cubeEdgeSize <<
" # Point 5\n";
59 fileStream << cubeEdgeSize / 2 <<
" " << -cubeEdgeSize / 2 <<
" " << -cubeEdgeSize <<
" # Point 6\n";
60 fileStream << cubeEdgeSize / 2 <<
" " << cubeEdgeSize / 2 <<
" " << -cubeEdgeSize <<
" # Point 7\n";
61 fileStream <<
"# 3D Lines\n";
62 fileStream <<
"0 # Number of lines\n";
63 fileStream <<
"# Faces from 3D lines\n";
64 fileStream <<
"0 # Number of faces\n";
65 fileStream <<
"# Faces from 3D points\n";
66 fileStream <<
"6 # Number of faces\n";
67 fileStream <<
"4 0 3 2 1 # Face 0: [number of points] [index of the 3D points]...\n";
68 fileStream <<
"4 1 2 5 6\n";
69 fileStream <<
"4 4 7 6 5\n";
70 fileStream <<
"4 0 7 4 3\n";
71 fileStream <<
"4 5 2 3 4\n";
72 fileStream <<
"4 0 1 6 7 # Face 5\n";
73 fileStream <<
"# 3D cylinders\n";
74 fileStream <<
"0 # Number of cylinders\n";
75 fileStream <<
"# 3D circles\n";
76 fileStream <<
"0 # Number of circles\n";
83 std::vector<vpHomogeneousMatrix> cMo_vec;
86 bool ret = detector.
detect(I, tagSize, cam, cMo_vec);
89 for (
size_t i = 0; i < cMo_vec.size(); i++) {
97 return state_tracking;
100 return state_detection;
114 return state_detection;
121 if (projection_error > projection_error_threshold) {
122 return state_detection;
130 std::stringstream ss;
135 return state_tracking;
138 int main(
int argc,
const char **argv)
142 double opt_tag_size = 0.08;
143 float opt_quad_decimate = 1.0;
144 int opt_nthreads = 1;
145 std::string opt_intrinsic_file =
"";
146 std::string opt_camera_name =
"";
147 double opt_cube_size = 0.125;
148 #ifdef VISP_HAVE_OPENCV
149 bool opt_use_texture =
false;
151 double opt_projection_error_threshold = 40.;
153 #if !(defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV))
154 bool display_off =
true;
156 bool display_off =
false;
159 for (
int i = 1; i < argc; i++) {
160 if (std::string(argv[i]) ==
"--tag_size" && i + 1 < argc) {
161 opt_tag_size = atof(argv[i + 1]);
163 else if (std::string(argv[i]) ==
"--input" && i + 1 < argc) {
164 opt_device = atoi(argv[i + 1]);
166 else if (std::string(argv[i]) ==
"--quad-decimate" && i + 1 < argc) {
167 opt_quad_decimate = (float)atof(argv[i + 1]);
169 else if (std::string(argv[i]) ==
"--nthreads" && i + 1 < argc) {
170 opt_nthreads = atoi(argv[i + 1]);
172 else if (std::string(argv[i]) ==
"--intrinsic" && i + 1 < argc) {
173 opt_intrinsic_file = std::string(argv[i + 1]);
175 else if (std::string(argv[i]) ==
"--camera-name" && i + 1 < argc) {
176 opt_camera_name = std::string(argv[i + 1]);
178 else if (std::string(argv[i]) ==
"--display-off") {
181 else if (std::string(argv[i]) ==
"--tag-family" && i + 1 < argc) {
184 else if (std::string(argv[i]) ==
"--cube-size" && i + 1 < argc) {
185 opt_cube_size = atof(argv[i + 1]);
186 #ifdef VISP_HAVE_OPENCV
188 else if (std::string(argv[i]) ==
"--texture") {
189 opt_use_texture =
true;
192 else if (std::string(argv[i]) ==
"--projection-error" && i + 1 < argc) {
193 opt_projection_error_threshold = atof(argv[i + 1]);
195 else if (std::string(argv[i]) ==
"--help" || std::string(argv[i]) ==
"-h") {
196 std::cout <<
"Usage: " << argv[0]
197 <<
" [--input <camera id>]"
198 <<
" [--cube-size <size in m>]"
199 <<
" [--tag-size <size in m>]"
200 <<
" [--quad-decimate <decimation>]"
201 <<
" [--nthreads <nb>]"
202 <<
" [--intrinsic <xml intrinsic file>]"
203 <<
" [--camera-name <camera name in xml file>]"
204 <<
" [--tag-family <0: TAG_36h11, 1: TAG_36h10, 2: TAG_36ARTOOLKIT, 3: TAG_25h9, 4: TAG_25h7, 5: TAG_16h5>]";
205 #if (defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI) || defined(VISP_HAVE_OPENCV))
206 std::cout <<
" [--display-off]";
208 std::cout <<
" [--texture]"
209 <<
" [--projection-error <30 - 100>]"
210 <<
" [--help,-h]" << std::endl;
215 createCaoFile(opt_cube_size);
218 bool camIsInit =
false;
219 #if defined(VISP_HAVE_PUGIXML)
221 if (!opt_intrinsic_file.empty() && !opt_camera_name.empty()) {
231 #if defined(VISP_HAVE_V4L2)
233 std::ostringstream device;
234 device <<
"/dev/video" << opt_device;
235 std::cout <<
"Use Video 4 Linux grabber on device " << device.str() << std::endl;
239 #elif ((VISP_HAVE_OPENCV_VERSION < 0x030000) && defined(HAVE_OPENCV_HIGHGUI))|| ((VISP_HAVE_OPENCV_VERSION >= 0x030000) && defined(HAVE_OPENCV_VIDEOIO))
240 std::cout <<
"Use OpenCV grabber on device " << opt_device << std::endl;
241 cv::VideoCapture g(opt_device);
243 std::cout <<
"Failed to open the camera" << std::endl;
255 std::cout <<
"Cube size: " << opt_cube_size << std::endl;
256 std::cout <<
"AprilTag size: " << opt_tag_size << std::endl;
257 std::cout <<
"AprilTag family: " << opt_tag_family << std::endl;
258 std::cout <<
"Camera parameters:\n" << cam << std::endl;
259 std::cout <<
"Detection: " << std::endl;
260 std::cout <<
" Quad decimate: " << opt_quad_decimate << std::endl;
261 std::cout <<
" Threads number: " << opt_nthreads << std::endl;
262 std::cout <<
"Tracker: " << std::endl;
263 std::cout <<
" Use edges : 1" << std::endl;
264 std::cout <<
" Use texture: "
265 #ifdef VISP_HAVE_OPENCV
266 << opt_use_texture << std::endl;
268 <<
" na" << std::endl;
270 std::cout <<
" Projection error: " << opt_projection_error_threshold << std::endl;
276 d =
new vpDisplayX(I);
277 #elif defined(VISP_HAVE_GDI)
279 #elif defined(HAVE_OPENCV_HIGHGUI)
291 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
309 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
310 if (opt_use_texture) {
319 tracker.setKltOpencv(klt_settings);
320 tracker.setKltMaskBorder(5);
333 state_t state = state_detection;
336 while (state != state_quit) {
338 #if defined(VISP_HAVE_V4L2)
340 #elif ((VISP_HAVE_OPENCV_VERSION < 0x030000) && defined(HAVE_OPENCV_HIGHGUI))|| ((VISP_HAVE_OPENCV_VERSION >= 0x030000) && defined(HAVE_OPENCV_VIDEOIO))
347 if (state == state_detection) {
348 state = detectAprilTag(I, detector, opt_tag_size, cam, cMo);
351 if (state == state_tracking) {
358 if (state == state_tracking) {
359 state = track(I, tracker, opt_projection_error_threshold, cMo);
374 std::cerr <<
"Catch an exception: " << e.
getMessage() << std::endl;
384 #if !defined(VISP_HAVE_APRILTAG)
385 std::cout <<
"ViSP is not build with Apriltag support" << std::endl;
387 #if !(defined(VISP_HAVE_V4L2) || defined(VISP_HAVE_OPENCV))
388 std::cout <<
"ViSP is not build with v4l2 or OpenCV support" << std::endl;
390 std::cout <<
"Install missing 3rd parties, configure and build ViSP to run this tutorial" << std::endl;
Generic class defining intrinsic camera parameters.
void initPersProjWithoutDistortion(double px, double py, double u0, double v0)
@ perspectiveProjWithoutDistortion
Perspective projection without distortion model.
static const vpColor none
void setAprilTagQuadDecimate(float quadDecimate)
bool detect(const vpImage< unsigned char > &I) VP_OVERRIDE
@ TAG_36h11
AprilTag 36h11 pattern (recommended)
void setAprilTagNbThreads(int nThreads)
size_t getNbObjects() const
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...
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 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 char * getMessage() const
Implementation of an homogeneous matrix and operations on such kind of matrices.
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
unsigned int getWidth() const
unsigned int getHeight() const
Wrapper for the KLT (Kanade-Lucas-Tomasi) feature tracker implemented in OpenCV. Thus to enable this ...
void setBlockSize(int blockSize)
void setQuality(double qualityLevel)
void setHarrisFreeParameter(double harris_k)
void setMaxFeatures(int maxCount)
void setMinDistance(double minDistance)
void setWindowSize(int winSize)
void setPyramidLevels(int pyrMaxLevel)
static double rad(double deg)
Real-time 6D object pose tracking using its CAD model.
virtual void setCameraParameters(const vpCameraParameters &camera) VP_OVERRIDE
virtual void setDisplayFeatures(bool displayF) VP_OVERRIDE
virtual unsigned int getNbFeaturesEdge() const
virtual double computeCurrentProjectionError(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &_cMo, const vpCameraParameters &_cam) VP_OVERRIDE
virtual void getCameraParameters(vpCameraParameters &camera) const VP_OVERRIDE
virtual void initFromPose(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo) VP_OVERRIDE
virtual void getPose(vpHomogeneousMatrix &cMo) const VP_OVERRIDE
virtual unsigned int getNbFeaturesKlt() const
virtual void setMovingEdge(const vpMe &me)
virtual void setAngleDisappear(const double &a) VP_OVERRIDE
virtual void track(const vpImage< unsigned char > &I) VP_OVERRIDE
virtual void loadModel(const std::string &modelFile, bool verbose=false, const vpHomogeneousMatrix &T=vpHomogeneousMatrix()) VP_OVERRIDE
virtual void setTrackerType(int type)
virtual void display(const vpImage< unsigned char > &I, const vpHomogeneousMatrix &cMo, const vpCameraParameters &cam, const vpColor &col, unsigned int thickness=1, bool displayFullModel=false) VP_OVERRIDE
virtual void setAngleAppear(const double &a) VP_OVERRIDE
void setMu1(const double &mu_1)
void setRange(const unsigned int &range)
void setLikelihoodThresholdType(const vpLikelihoodThresholdType likelihood_threshold_type)
void setMaskNumber(const unsigned int &mask_number)
void setThreshold(const double &threshold)
void setSampleStep(const double &sample_step)
void setMaskSize(const unsigned int &mask_size)
void setMu2(const double &mu_2)
Class that is a wrapper over the Video4Linux2 (V4L2) driver.
void open(vpImage< unsigned char > &I)
void setScale(unsigned scale=vpV4l2Grabber::DEFAULT_SCALE)
void setDevice(const std::string &devname)
void acquire(vpImage< unsigned char > &I)
XML parser to load and save intrinsic camera parameters.
int parse(vpCameraParameters &cam, const std::string &filename, const std::string &camera_name, const vpCameraParameters::vpCameraParametersProjType &projModel, unsigned int image_width=0, unsigned int image_height=0, bool verbose=true)