39 #include <visp3/core/vpConfig.h>
41 #if defined(VISP_HAVE_CATCH2) && defined(VISP_HAVE_APRILTAG) && (VISP_HAVE_DATASET_VERSION >= 0x030300)
43 #include <catch_amalgamated.hpp>
46 #include <visp3/core/vpDisplay.h>
47 #include <visp3/core/vpIoTools.h>
48 #include <visp3/core/vpPixelMeterConversion.h>
49 #include <visp3/core/vpPoint.h>
50 #include <visp3/detection/vpDetectorAprilTag.h>
51 #include <visp3/io/vpImageIo.h>
52 #include <visp3/vision/vpPose.h>
54 #ifdef ENABLE_VISP_NAMESPACE
61 std::string m_message;
62 std::vector<vpImagePoint> m_corners;
64 TagGroundTruth(
const std::string &msg,
const std::vector<vpImagePoint> &c) : m_message(msg), m_corners(c) { }
66 bool operator==(
const TagGroundTruth &b)
const
68 if (m_message != b.m_message || m_corners.size() != b.m_corners.size()) {
72 for (
size_t i = 0; i < m_corners.size(); i++) {
74 if (!
vpMath::equal(m_corners[i].get_u(), b.m_corners[i].get_u(), 0.5) ||
75 !
vpMath::equal(m_corners[i].get_v(), b.m_corners[i].get_v(), 0.5)) {
83 bool operator!=(
const TagGroundTruth &b)
const {
return !(*
this == b); }
85 double rmse(
const std::vector<vpImagePoint> &c)
89 if (m_corners.size() == c.size()) {
90 for (
size_t i = 0; i < m_corners.size(); i++) {
100 return sqrt(error / (2 * m_corners.size()));
104 #if defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_OPENCV) || defined(VISP_HAVE_EIGEN3)
105 std::ostream &operator<<(std::ostream &os, TagGroundTruth &t)
107 os << t.m_message << std::endl;
108 for (
size_t i = 0; i < t.m_corners.size(); i++) {
109 os << t.m_corners[i] << std::endl;
116 struct FailedTestCase
124 : m_family(family), m_method(method), m_tagId(tagId)
127 bool operator==(
const FailedTestCase &b)
const
129 return m_family == b.m_family && m_method == b.m_method && m_tagId == b.m_tagId;
132 bool operator!=(
const FailedTestCase &b)
const {
return !(*
this == b); }
136 TEST_CASE(
"Apriltag pose estimation test",
"[apriltag_pose_estimation_test]")
138 std::map<vpDetectorAprilTag::vpAprilTagFamily, std::string> apriltagMap = {
143 #if defined(VISP_HAVE_APRILTAG_BIG_FAMILY)
152 std::map<vpDetectorAprilTag::vpAprilTagFamily, double> tagSizeScales = {
157 #if defined(VISP_HAVE_APRILTAG_BIG_FAMILY)
166 std::vector<vpDetectorAprilTag::vpPoseEstimationMethod> poseMethods = {
169 #if defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_OPENCV) || defined(VISP_HAVE_EIGEN3)
176 std::map<vpDetectorAprilTag::vpPoseEstimationMethod, std::string> methodNames = {
180 #if defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_OPENCV) || defined(VISP_HAVE_EIGEN3)
187 const size_t nbTags = 5;
188 const double tagSize_ = 0.25;
189 std::map<int, double> tagsSize = {
190 {0, tagSize_}, {1, tagSize_}, {2, tagSize_}, {3, tagSize_ / 2}, {4, tagSize_ / 2},
193 std::map<int, double> errorTranslationThresh = {
194 {0, 0.025}, {1, 0.09}, {2, 0.05}, {3, 0.13}, {4, 0.09},
196 std::map<int, double> errorRotationThresh = {
197 {0, 0.04}, {1, 0.075}, {2, 0.07}, {3, 0.18}, {4, 0.13},
199 std::vector<FailedTestCase> ignoreTests = {
207 std::map<int, vpHomogeneousMatrix> groundTruthPoses;
208 for (
size_t i = 0; i < nbTags; i++) {
209 std::string filename =
211 std::to_string(i) + std::string(
".txt"));
212 std::ifstream file(filename);
213 groundTruthPoses[
static_cast<int>(i)].load(file);
216 for (
const auto &kv : apriltagMap) {
217 auto family = kv.first;
218 std::cout <<
"\nApriltag family: " << family << std::endl;
219 std::string filename =
221 std::string(
"AprilTag/benchmark/640x480/") + kv.second + std::string(
"_640x480.png"));
222 const double tagSize = tagSize_ * tagSizeScales[family];
227 REQUIRE(I.
getSize() == 640 * 480);
231 for (
auto method : poseMethods) {
232 std::cout <<
"\tPose estimation method: " << method << std::endl;
233 apriltag_detector.setAprilTagPoseEstimationMethod(method);
237 std::vector<vpHomogeneousMatrix> cMo_vec;
238 apriltag_detector.detect(I, tagSize, cam, cMo_vec);
239 CHECK(cMo_vec.size() == nbTags);
241 std::vector<std::vector<vpImagePoint> > tagsCorners = apriltag_detector.getPolygon();
242 CHECK(tagsCorners.size() == nbTags);
244 std::vector<std::string> messages = apriltag_detector.getMessage();
245 CHECK(messages.size() == nbTags);
247 std::vector<int> tagsId = apriltag_detector.getTagsId();
248 CHECK(tagsId.size() == nbTags);
249 std::map<int, int> idsCount;
250 for (
size_t i = 0; i < tagsId.size(); i++) {
251 idsCount[tagsId[i]]++;
252 CHECK((tagsId[i] >= 0 && tagsId[i] < 5));
254 CHECK(idsCount.size() == nbTags);
256 for (
size_t i = 0; i < cMo_vec.size(); i++) {
263 std::cout <<
"\t\tSame size, Tag: " << i << std::endl;
267 vpColVector error_translation =
vpColVector(pose.getTranslationVector() - pose_truth.getTranslationVector());
269 double error_trans = sqrt(error_translation.
sumSquare() / 3);
270 double error_orientation = sqrt(error_thetau.
sumSquare() / 3);
271 std::cout <<
"\t\t\tTranslation error: " << error_trans <<
" / Rotation error: " << error_orientation
273 CHECK((error_trans < errorTranslationThresh[
id] && error_orientation < errorRotationThresh[
id]));
279 apriltag_detector.detect(I);
281 std::vector<std::vector<vpImagePoint> > tagsCorners = apriltag_detector.getPolygon();
282 CHECK(tagsCorners.size() == nbTags);
284 std::vector<std::string> messages = apriltag_detector.getMessage();
285 CHECK(messages.size() == nbTags);
287 std::vector<int> tagsId = apriltag_detector.getTagsId();
288 CHECK(tagsId.size() == nbTags);
289 std::map<int, int> idsCount;
290 for (
size_t i = 0; i < tagsId.size(); i++) {
291 idsCount[tagsId[i]]++;
292 CHECK((tagsId[i] >= 0 && tagsId[i] < 5));
294 CHECK(idsCount.size() == nbTags);
296 for (
size_t idx = 0; idx < tagsId.size(); idx++) {
297 std::cout <<
"\t\tCustom size, Tag: " << idx << std::endl;
298 const int id = tagsId[idx];
300 apriltag_detector.getPose(idx, tagsSize[
id] * tagSizeScales[family], cam, cMo);
306 vpColVector error_translation =
vpColVector(pose.getTranslationVector() - pose_truth.getTranslationVector());
308 double error_trans = sqrt(error_translation.
sumSquare() / 3);
309 double error_orientation = sqrt(error_thetau.
sumSquare() / 3);
310 std::cout <<
"\t\t\tTranslation error: " << error_trans <<
" / Rotation error: " << error_orientation
312 if (std::find(ignoreTests.begin(), ignoreTests.end(),
313 FailedTestCase(family, method,
static_cast<int>(idx))) == ignoreTests.end()) {
314 CHECK((error_trans < errorTranslationThresh[
id] && error_orientation < errorRotationThresh[
id]));
321 apriltag_detector.detect(I);
323 std::vector<std::vector<vpImagePoint> > tagsCorners = apriltag_detector.getPolygon();
324 CHECK(tagsCorners.size() == nbTags);
326 std::vector<std::string> messages = apriltag_detector.getMessage();
327 CHECK(messages.size() == nbTags);
329 std::vector<int> tagsId = apriltag_detector.getTagsId();
330 CHECK(tagsId.size() == nbTags);
331 std::map<int, int> idsCount;
332 for (
size_t i = 0; i < tagsId.size(); i++) {
333 idsCount[tagsId[i]]++;
334 CHECK((tagsId[i] >= 0 && tagsId[i] < 5));
336 CHECK(idsCount.size() == nbTags);
338 for (
size_t idx = 0; idx < tagsId.size(); idx++) {
339 std::cout <<
"\t\tCustom size + aligned Z-axis, Tag: " << idx << std::endl;
340 const int id = tagsId[idx];
342 apriltag_detector.setZAlignedWithCameraAxis(
true);
343 apriltag_detector.getPose(idx, tagsSize[
id] * tagSizeScales[family], cam, cMo);
344 apriltag_detector.setZAlignedWithCameraAxis(
false);
351 vpColVector error_translation =
vpColVector(pose.getTranslationVector() - pose_truth.getTranslationVector());
353 double error_trans = sqrt(error_translation.
sumSquare() / 3);
354 double error_orientation = sqrt(error_thetau.
sumSquare() / 3);
355 std::cout <<
"\t\t\tTranslation error: " << error_trans <<
" / Rotation error: " << error_orientation
357 if (std::find(ignoreTests.begin(), ignoreTests.end(),
358 FailedTestCase(family, method,
static_cast<int>(idx))) == ignoreTests.end()) {
359 CHECK((error_trans < errorTranslationThresh[
id] && error_orientation < errorRotationThresh[
id]));
367 TEST_CASE(
"Apriltag corners accuracy test",
"[apriltag_corners_accuracy_test]")
369 std::map<vpDetectorAprilTag::vpAprilTagFamily, std::string> apriltagMap = {
374 #if defined(VISP_HAVE_APRILTAG_BIG_FAMILY)
383 const size_t nbTags = 5;
384 std::map<vpDetectorAprilTag::vpAprilTagFamily, std::map<int, std::vector<vpImagePoint> > > groundTruthCorners;
385 for (
const auto &kv : apriltagMap) {
386 std::string filename =
388 std::string(
"AprilTag/benchmark/640x480/corners_") + kv.second + std::string(
".txt"));
389 std::ifstream file(filename);
390 REQUIRE(file.is_open());
393 double p0x = 0, p0y = 0;
394 double p1x = 0, p1y = 0;
395 double p2x = 0, p2y = 0;
396 double p3x = 0, p3y = 0;
397 while (file >>
id >> p0x >> p0y >> p1x >> p1y >> p2x >> p2y >> p3x >> p3y) {
398 groundTruthCorners[kv.first][id].push_back(
vpImagePoint(p0y, p0x));
399 groundTruthCorners[kv.first][id].push_back(
vpImagePoint(p1y, p1x));
400 groundTruthCorners[kv.first][id].push_back(
vpImagePoint(p2y, p2x));
401 groundTruthCorners[kv.first][id].push_back(
vpImagePoint(p3y, p3x));
402 REQUIRE(groundTruthCorners[kv.first][
id].size() == 4);
406 for (
const auto &kv : apriltagMap) {
407 auto family = kv.first;
408 std::cout <<
"\nApriltag family: " << family << std::endl;
409 std::string filename =
411 std::string(
"AprilTag/benchmark/640x480/") + kv.second + std::string(
"_640x480.png"));
416 REQUIRE(I.
getSize() == 640 * 480);
419 apriltag_detector.detect(I);
420 std::vector<int> tagsId = apriltag_detector.getTagsId();
421 std::vector<std::vector<vpImagePoint> > tagsCorners = apriltag_detector.getTagsCorners();
423 REQUIRE(tagsCorners.size() == nbTags);
424 REQUIRE(tagsId.size() == nbTags);
425 for (
size_t i = 0; i < tagsCorners.size(); i++) {
426 const int tagId = tagsId[i];
427 REQUIRE(tagsCorners[i].size() == 4);
429 TagGroundTruth corners_ref(
"", groundTruthCorners[family][tagId]);
430 TagGroundTruth corners_cur(
"", tagsCorners[i]);
431 CHECK((corners_ref == corners_cur));
433 std::cout <<
"\tid: " << tagId <<
" - RMSE: " << corners_ref.rmse(corners_cur.m_corners) << std::endl;
438 #if defined(VISP_HAVE_LAPACK) || defined(VISP_HAVE_OPENCV) || defined(VISP_HAVE_EIGEN3)
439 TEST_CASE(
"Apriltag regression test",
"[apriltag_regression_test]")
441 #if (VISP_HAVE_DATASET_VERSION >= 0x030600)
450 REQUIRE(I.
getSize() == 640 * 480);
454 const double tagSize = 0.053;
455 const float quad_decimate = 1.0;
458 dynamic_cast<vpDetectorAprilTag *
>(detector)->setAprilTagPoseEstimationMethod(poseEstimationMethod);
463 std::vector<vpHomogeneousMatrix> cMo_vec;
467 std::map<std::string, TagGroundTruth> mapOfTagsGroundTruth;
469 std::string filename_ground_truth =
471 std::ifstream file_ground_truth(filename_ground_truth.c_str());
472 REQUIRE(file_ground_truth.is_open());
473 std::string message =
"";
474 double v1 = 0.0, v2 = 0.0, v3 = 0.0, v4 = 0.0;
475 double u1 = 0.0, u2 = 0.0, u3 = 0.0, u4 = 0.0;
476 while (file_ground_truth >> message >> v1 >> u1 >> v2 >> u2 >> v3 >> u3 >> v4 >> u4) {
477 std::vector<vpImagePoint> tagCorners(4);
478 tagCorners[0].set_ij(v1, u1);
479 tagCorners[1].set_ij(v2, u2);
480 tagCorners[2].set_ij(v3, u3);
481 tagCorners[3].set_ij(v4, u4);
482 mapOfTagsGroundTruth.insert(std::make_pair(message, TagGroundTruth(message, tagCorners)));
486 std::map<std::string, vpPoseVector> mapOfPosesGroundTruth;
488 std::string filename_ground_truth =
490 std::ifstream file_ground_truth(filename_ground_truth.c_str());
491 REQUIRE(file_ground_truth.is_open());
492 std::string message =
"";
493 double tx = 0.0, ty = 0.0, tz = 0.0;
494 double tux = 0.0, tuy = 0.0, tuz = 0.0;
495 while (file_ground_truth >> message >> tx >> ty >> tz >> tux >> tuy >> tuz) {
496 mapOfPosesGroundTruth.insert(std::make_pair(message,
vpPoseVector(tx, ty, tz, tux, tuy, tuz)));
501 std::vector<vpImagePoint> p = detector->
getPolygon(i);
503 std::string message = detector->
getMessage(i);
504 std::replace(message.begin(), message.end(),
' ',
'_');
505 std::map<std::string, TagGroundTruth>::iterator it = mapOfTagsGroundTruth.find(message);
506 TagGroundTruth current(message, p);
507 if (it == mapOfTagsGroundTruth.end()) {
508 std::cerr <<
"Problem with tag decoding (tag_family or id): " << message << std::endl;
510 else if (it->second != current) {
511 std::cerr <<
"Problem, current detection:\n" << current <<
"\nReference:\n" << it->second << std::endl;
513 REQUIRE(it != mapOfTagsGroundTruth.end());
514 CHECK(it->second == current);
517 for (
size_t i = 0; i < cMo_vec.size(); i++) {
520 std::string message = detector->
getMessage(i);
521 std::replace(message.begin(), message.end(),
' ',
'_');
522 std::map<std::string, vpPoseVector>::iterator it = mapOfPosesGroundTruth.find(message);
523 if (it == mapOfPosesGroundTruth.end()) {
524 std::cerr <<
"Problem with tag decoding (tag_family or id): " << message << std::endl;
526 REQUIRE(it != mapOfPosesGroundTruth.end());
527 std::cout <<
"Tag: " << message << std::endl;
528 std::cout <<
"\tEstimated pose: " << pose_vec.t() << std::endl;
529 std::cout <<
"\tReference pose: " << it->second.t() << std::endl;
530 for (
unsigned int cpt = 0; cpt < 3; cpt++) {
532 !
vpMath::equal(it->second[cpt + 3], pose_vec[cpt + 3], 0.005)) {
533 std::cerr <<
"Problem, current pose: " << pose_vec.t() <<
"\nReference pose: " << it->second.t() << std::endl;
535 CHECK((
vpMath::equal(it->second[cpt], pose_vec[cpt], 0.005) &&
536 vpMath::equal(it->second[cpt + 3], pose_vec[cpt + 3], 0.005)));
543 TEST_CASE(
"Apriltag copy constructor test",
"[apriltag_copy_constructor_test]")
545 const std::string filename =
551 REQUIRE(I.
getSize() == 640 * 480);
555 const double tagSize = 0.25 * 5 / 9;
556 const float quad_decimate = 1.0;
563 std::vector<vpHomogeneousMatrix> cMo_vec;
564 detector->
detect(I, tagSize, cam, cMo_vec);
565 std::vector<std::vector<vpImagePoint> > tagsCorners = detector->
getTagsCorners();
566 std::vector<int> tagsId = detector->
getTagsId();
573 std::vector<std::vector<vpImagePoint> > tagsCorners_copy = detector_copy.
getTagsCorners();
574 std::vector<int> tagsId_copy = detector_copy.getTagsId();
575 REQUIRE(tagsCorners_copy.size() == tagsCorners.size());
576 REQUIRE(tagsId_copy.size() == tagsId.size());
577 REQUIRE(tagsCorners_copy.size() == tagsId_copy.size());
579 for (
size_t i = 0; i < tagsCorners.size(); i++) {
580 const std::vector<vpImagePoint> &corners_ref = tagsCorners[i];
581 const std::vector<vpImagePoint> &corners_copy = tagsCorners_copy[i];
582 REQUIRE(corners_ref.size() == corners_copy.size());
584 for (
size_t j = 0; j < corners_ref.size(); j++) {
587 CHECK(corner_ref == corner_copy);
590 int id_ref = tagsId[i];
591 int id_copy = tagsId_copy[i];
592 CHECK(id_ref == id_copy);
595 std::vector<vpHomogeneousMatrix> cMo_vec_copy;
596 detector_copy.detect(I, tagSize, cam, cMo_vec_copy);
597 REQUIRE(cMo_vec.size() == cMo_vec_copy.size());
598 for (
size_t idx = 0; idx < cMo_vec_copy.size(); idx++) {
601 for (
unsigned int i = 0; i < 3; i++) {
602 for (
unsigned int j = 0; j < 4; j++) {
603 CHECK(
vpMath::equal(cMo[i][j], cMo_copy[i][j], std::numeric_limits<double>::epsilon()));
609 TEST_CASE(
"Apriltag assignment operator test",
"[apriltag_assignment_operator_test]")
611 const std::string filename =
617 REQUIRE(I.
getSize() == 640 * 480);
621 const double tagSize = 0.25 * 5 / 9;
622 const float quad_decimate = 1.0;
629 std::vector<vpHomogeneousMatrix> cMo_vec;
630 detector->
detect(I, tagSize, cam, cMo_vec);
631 std::vector<std::vector<vpImagePoint> > tagsCorners = detector->
getTagsCorners();
632 std::vector<int> tagsId = detector->
getTagsId();
639 std::vector<std::vector<vpImagePoint> > tagsCorners_copy = detector_copy.
getTagsCorners();
640 std::vector<int> tagsId_copy = detector_copy.
getTagsId();
641 REQUIRE(tagsCorners_copy.size() == tagsCorners.size());
642 REQUIRE(tagsId_copy.size() == tagsId.size());
643 REQUIRE(tagsCorners_copy.size() == tagsId_copy.size());
645 for (
size_t i = 0; i < tagsCorners.size(); i++) {
646 const std::vector<vpImagePoint> &corners_ref = tagsCorners[i];
647 const std::vector<vpImagePoint> &corners_copy = tagsCorners_copy[i];
648 REQUIRE(corners_ref.size() == corners_copy.size());
650 for (
size_t j = 0; j < corners_ref.size(); j++) {
653 CHECK(corner_ref == corner_copy);
656 int id_ref = tagsId[i];
657 int id_copy = tagsId_copy[i];
658 CHECK(id_ref == id_copy);
661 std::vector<vpHomogeneousMatrix> cMo_vec_copy;
662 detector_copy.
detect(I, tagSize, cam, cMo_vec_copy);
663 REQUIRE(cMo_vec.size() == cMo_vec_copy.size());
664 for (
size_t idx = 0; idx < cMo_vec_copy.size(); idx++) {
667 for (
unsigned int i = 0; i < 3; i++) {
668 for (
unsigned int j = 0; j < 4; j++) {
669 CHECK(
vpMath::equal(cMo[i][j], cMo_copy[i][j], std::numeric_limits<double>::epsilon()));
675 TEST_CASE(
"Apriltag getTagsPoints3D test",
"[apriltag_get_tags_points3D_test]")
677 const std::string filename =
683 REQUIRE(I.
getSize() == 640 * 480);
687 const double familyScale = 5.0 / 9;
688 const double tagSize = 0.25;
689 std::map<int, double> tagsSize = {
690 {-1, tagSize * familyScale}, {3, tagSize / 2 * familyScale}, {4, tagSize / 2 * familyScale} };
697 std::vector<vpHomogeneousMatrix> cMo_vec;
698 REQUIRE(detector.
detect(I));
701 std::vector<int> tagsId = detector.
getTagsId();
702 for (
size_t i = 0; i < tagsId.size(); i++) {
704 double size = tagsSize[-1];
705 if (tagsSize.find(
id) != tagsSize.end()) {
710 detector.
getPose(i, size, cam, cMo);
711 cMo_vec.push_back(cMo);
715 std::vector<std::vector<vpPoint> > tagsPoints = detector.
getTagsPoints3D(tagsId, tagsSize);
716 std::vector<std::vector<vpImagePoint> > tagsCorners = detector.
getTagsCorners();
717 REQUIRE(tagsPoints.size() == tagsCorners.size());
719 for (
size_t i = 0; i < tagsPoints.size(); i++) {
720 REQUIRE(tagsPoints[i].size() == tagsCorners[i].size());
722 for (
size_t j = 0; j < tagsPoints[i].size(); j++) {
723 vpPoint &pt = tagsPoints[i][j];
731 vpPose pose(tagsPoints[i]);
741 double epsilon = 1e-12;
743 for (
unsigned int row = 0; row < cMo.
getRows(); row++) {
744 for (
unsigned int col = 0; col < cMo.
getCols(); col++) {
745 CHECK(
vpMath::equal(cMo[row][col], cMo_manual[row][col], epsilon));
752 int main(
int argc,
const char *argv[])
754 Catch::Session session;
756 session.applyCommandLine(argc, argv);
757 int numFailed = session.run();
763 int main() {
return EXIT_SUCCESS; }
unsigned int getCols() const
unsigned int getRows() const
Generic class defining intrinsic camera parameters.
void initPersProjWithoutDistortion(double px, double py, double u0, double v0)
Implementation of column vector and the associated operations.
@ BEST_RESIDUAL_VIRTUAL_VS
@ HOMOGRAPHY_ORTHOGONAL_ITERATION
std::vector< std::vector< vpImagePoint > > getTagsCorners() const
void setAprilTagQuadDecimate(float quadDecimate)
std::vector< std::vector< vpPoint > > getTagsPoints3D(const std::vector< int > &tagsId, const std::map< int, double > &tagsSize) const
bool detect(const vpImage< unsigned char > &I) VP_OVERRIDE
@ TAG_CIRCLE21h7
AprilTag Circle21h7 pattern.
@ TAG_25h9
AprilTag 25h9 pattern.
@ TAG_CUSTOM48h12
AprilTag Custom48h12 pattern.
@ TAG_36h11
AprilTag 36h11 pattern (recommended)
@ TAG_STANDARD52h13
AprilTag Standard52h13 pattern.
@ TAG_16h5
AprilTag 16h5 pattern.
@ TAG_STANDARD41h12
AprilTag Standard41h12 pattern.
@ TAG_CIRCLE49h12
AprilTag Circle49h12 pattern.
std::vector< int > getTagsId() const
bool getPose(size_t tagIndex, double tagSize, const vpCameraParameters &cam, vpHomogeneousMatrix &cMo, vpHomogeneousMatrix *cMo2=nullptr, double *projError=nullptr, double *projError2=nullptr)
std::vector< std::vector< vpImagePoint > > & getPolygon()
size_t getNbObjects() const
std::vector< std::string > & getMessage()
Implementation of an homogeneous matrix and operations on such kind of matrices.
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
unsigned int getSize() const
static bool equal(double x, double y, double threshold=0.001)
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
Class that defines a 3D point in the object frame and allows forward projection of a 3D point in the ...
void set_x(double x)
Set the point x coordinate in the image plane.
void set_y(double y)
Set the point y coordinate in the image plane.
Implementation of a pose vector and operations on poses.
Class used for pose computation from N points (pose from point only). Some of the algorithms implemen...
@ DEMENTHON_LAGRANGE_VIRTUAL_VS
Implementation of a rotation vector as axis-angle minimal representation.
Class that consider the case of a translation vector.