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/vpDisplayFactory.h>
28 #include <visp3/mbt/vpMbGenericTracker.h>
30 #if (VISP_HAVE_OPENCV_VERSION < 0x030000) && defined(HAVE_OPENCV_HIGHGUI)
31 #include <opencv2/highgui/highgui.hpp>
32 #elif (VISP_HAVE_OPENCV_VERSION >= 0x030000) && defined(HAVE_OPENCV_VIDEOIO)
33 #include <opencv2/videoio/videoio.hpp>
36 #ifdef ENABLE_VISP_NAMESPACE
40 typedef enum { state_detection, state_tracking, state_quit } state_t;
44 void createCaoFile(
double cubeEdgeSize)
46 std::ofstream fileStream;
47 fileStream.open(
"cube.cao", std::ofstream::out | std::ofstream::trunc);
49 fileStream <<
"# 3D Points\n";
50 fileStream <<
"8 # Number of points\n";
51 fileStream << cubeEdgeSize / 2 <<
" " << cubeEdgeSize / 2 <<
" " << 0 <<
" # Point 0: (X, Y, Z)\n";
52 fileStream << cubeEdgeSize / 2 <<
" " << -cubeEdgeSize / 2 <<
" " << 0 <<
" # Point 1\n";
53 fileStream << -cubeEdgeSize / 2 <<
" " << -cubeEdgeSize / 2 <<
" " << 0 <<
" # Point 2\n";
54 fileStream << -cubeEdgeSize / 2 <<
" " << cubeEdgeSize / 2 <<
" " << 0 <<
" # Point 3\n";
55 fileStream << -cubeEdgeSize / 2 <<
" " << cubeEdgeSize / 2 <<
" " << -cubeEdgeSize <<
" # Point 4\n";
56 fileStream << -cubeEdgeSize / 2 <<
" " << -cubeEdgeSize / 2 <<
" " << -cubeEdgeSize <<
" # Point 5\n";
57 fileStream << cubeEdgeSize / 2 <<
" " << -cubeEdgeSize / 2 <<
" " << -cubeEdgeSize <<
" # Point 6\n";
58 fileStream << cubeEdgeSize / 2 <<
" " << cubeEdgeSize / 2 <<
" " << -cubeEdgeSize <<
" # Point 7\n";
59 fileStream <<
"# 3D Lines\n";
60 fileStream <<
"0 # Number of lines\n";
61 fileStream <<
"# Faces from 3D lines\n";
62 fileStream <<
"0 # Number of faces\n";
63 fileStream <<
"# Faces from 3D points\n";
64 fileStream <<
"6 # Number of faces\n";
65 fileStream <<
"4 0 3 2 1 # Face 0: [number of points] [index of the 3D points]...\n";
66 fileStream <<
"4 1 2 5 6\n";
67 fileStream <<
"4 4 7 6 5\n";
68 fileStream <<
"4 0 7 4 3\n";
69 fileStream <<
"4 5 2 3 4\n";
70 fileStream <<
"4 0 1 6 7 # Face 5\n";
71 fileStream <<
"# 3D cylinders\n";
72 fileStream <<
"0 # Number of cylinders\n";
73 fileStream <<
"# 3D circles\n";
74 fileStream <<
"0 # Number of circles\n";
81 std::vector<vpHomogeneousMatrix> cMo_vec;
84 bool ret = detector.
detect(I, tagSize, cam, cMo_vec);
87 for (
size_t i = 0; i < cMo_vec.size(); i++) {
95 return state_tracking;
98 return state_detection;
112 return state_detection;
119 if (projection_error > projection_error_threshold) {
120 return state_detection;
128 std::stringstream ss;
133 return state_tracking;
136 int main(
int argc,
const char **argv)
140 double opt_tag_size = 0.08;
141 float opt_quad_decimate = 1.0;
142 int opt_nthreads = 1;
143 std::string opt_intrinsic_file =
"";
144 std::string opt_camera_name =
"";
145 double opt_cube_size = 0.125;
146 #ifdef VISP_HAVE_OPENCV
147 bool opt_use_texture =
false;
149 double opt_projection_error_threshold = 40.;
151 #if !(defined(VISP_HAVE_DISPLAY))
152 bool display_off =
true;
154 bool display_off =
false;
157 for (
int i = 1; i < argc; i++) {
158 if (std::string(argv[i]) ==
"--tag-size" && i + 1 < argc) {
159 opt_tag_size = atof(argv[i + 1]);
161 else if (std::string(argv[i]) ==
"--input" && i + 1 < argc) {
162 opt_device = atoi(argv[i + 1]);
164 else if (std::string(argv[i]) ==
"--quad-decimate" && i + 1 < argc) {
165 opt_quad_decimate = (float)atof(argv[i + 1]);
167 else if (std::string(argv[i]) ==
"--nthreads" && i + 1 < argc) {
168 opt_nthreads = atoi(argv[i + 1]);
170 else if (std::string(argv[i]) ==
"--intrinsic" && i + 1 < argc) {
171 opt_intrinsic_file = std::string(argv[i + 1]);
173 else if (std::string(argv[i]) ==
"--camera-name" && i + 1 < argc) {
174 opt_camera_name = std::string(argv[i + 1]);
176 else if (std::string(argv[i]) ==
"--display-off") {
179 else if (std::string(argv[i]) ==
"--tag-family" && i + 1 < argc) {
182 else if (std::string(argv[i]) ==
"--cube-size" && i + 1 < argc) {
183 opt_cube_size = atof(argv[i + 1]);
184 #ifdef VISP_HAVE_OPENCV
186 else if (std::string(argv[i]) ==
"--texture") {
187 opt_use_texture =
true;
190 else if (std::string(argv[i]) ==
"--projection-error" && i + 1 < argc) {
191 opt_projection_error_threshold = atof(argv[i + 1]);
193 else if (std::string(argv[i]) ==
"--help" || std::string(argv[i]) ==
"-h") {
194 std::cout <<
"Usage: " << argv[0]
195 <<
" [--input <camera id>]"
196 <<
" [--cube-size <size in m>]"
197 <<
" [--tag-size <size in m>]"
198 <<
" [--quad-decimate <decimation>]"
199 <<
" [--nthreads <nb>]"
200 <<
" [--intrinsic <xml intrinsic file>]"
201 <<
" [--camera-name <camera name in xml file>]"
202 <<
" [--tag-family <0: TAG_36h11, 1: TAG_36h10, 2: TAG_36ARTOOLKIT, 3: TAG_25h9, 4: TAG_25h7, 5: TAG_16h5>]";
203 #if (defined(VISP_HAVE_DISPLAY))
204 std::cout <<
" [--display-off]";
206 std::cout <<
" [--texture]"
207 <<
" [--projection-error <30 - 100>]"
208 <<
" [--help,-h]" << std::endl;
213 createCaoFile(opt_cube_size);
216 bool camIsInit =
false;
217 #if defined(VISP_HAVE_PUGIXML)
219 if (!opt_intrinsic_file.empty() && !opt_camera_name.empty()) {
225 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
226 std::shared_ptr<vpDisplay> display;
235 #if defined(VISP_HAVE_V4L2)
237 std::ostringstream device;
238 device <<
"/dev/video" << opt_device;
239 std::cout <<
"Use Video 4 Linux grabber on device " << device.str() << std::endl;
243 #elif ((VISP_HAVE_OPENCV_VERSION < 0x030000) && defined(HAVE_OPENCV_HIGHGUI))|| ((VISP_HAVE_OPENCV_VERSION >= 0x030000) && defined(HAVE_OPENCV_VIDEOIO))
244 std::cout <<
"Use OpenCV grabber on device " << opt_device << std::endl;
245 cv::VideoCapture g(opt_device);
247 std::cout <<
"Failed to open the camera" << std::endl;
259 std::cout <<
"Cube size: " << opt_cube_size << std::endl;
260 std::cout <<
"AprilTag size: " << opt_tag_size << std::endl;
261 std::cout <<
"AprilTag family: " << opt_tag_family << std::endl;
262 std::cout <<
"Camera parameters:\n" << cam << std::endl;
263 std::cout <<
"Detection: " << std::endl;
264 std::cout <<
" Quad decimate: " << opt_quad_decimate << std::endl;
265 std::cout <<
" Threads number: " << opt_nthreads << std::endl;
266 std::cout <<
"Tracker: " << std::endl;
267 std::cout <<
" Use edges : 1" << std::endl;
268 std::cout <<
" Use texture: "
269 #ifdef VISP_HAVE_OPENCV
270 << opt_use_texture << std::endl;
272 <<
" na" << std::endl;
274 std::cout <<
" Projection error: " << opt_projection_error_threshold << std::endl;
278 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
292 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
310 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO)
311 if (opt_use_texture) {
320 tracker.setKltOpencv(klt_settings);
321 tracker.setKltMaskBorder(5);
334 state_t state = state_detection;
337 while (state != state_quit) {
339 #if defined(VISP_HAVE_V4L2)
341 #elif ((VISP_HAVE_OPENCV_VERSION < 0x030000) && defined(HAVE_OPENCV_HIGHGUI))|| ((VISP_HAVE_OPENCV_VERSION >= 0x030000) && defined(HAVE_OPENCV_VIDEOIO))
348 if (state == state_detection) {
349 state = detectAprilTag(I, detector, opt_tag_size, cam, cMo);
352 if (state == state_tracking) {
359 if (state == state_tracking) {
360 state = track(I, tracker, opt_projection_error_threshold, cMo);
372 std::cerr <<
"Catch an exception: " << e.
getMessage() << std::endl;
375 #if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
386 #if !defined(VISP_HAVE_APRILTAG)
387 std::cout <<
"ViSP is not build with Apriltag support" << std::endl;
389 #if !(defined(VISP_HAVE_V4L2) || defined(VISP_HAVE_OPENCV))
390 std::cout <<
"ViSP is not build with v4l2 or OpenCV support" << std::endl;
392 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
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)
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.