Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpPoseRansac.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Pose computation.
32 */
33
38
39#include <algorithm> // std::count
40#include <cmath> // std::fabs
41#include <float.h> // DBL_MAX
42#include <iostream>
43#include <limits> // numeric_limits
44#include <map>
45
46#include <visp3/core/vpColVector.h>
47#include <visp3/core/vpMath.h>
48#include <visp3/core/vpRansac.h>
49#include <visp3/vision/vpPose.h>
50#include <visp3/vision/vpPoseException.h>
51
52#if defined(VISP_HAVE_THREADS)
53#include <thread>
54#endif
55
56#define EPS 1e-6
57
59
60#ifndef DOXYGEN_SHOULD_SKIP_THIS
61namespace
62{
63// For std::map<vpPoint>
64struct CompareObjectPointDegenerate
65{
66 bool operator()(const vpPoint &point1, const vpPoint &point2) const
67 {
68 const unsigned int index_0 = 0;
69 const unsigned int index_1 = 1;
70 const unsigned int index_2 = 2;
71 const double val3 = 3.;
72 bool rc = false;
73 const double dist1 =
74 (point1.get_oX() * point1.get_oX()) + (point1.get_oY() * point1.get_oY()) + (point1.get_oZ() * point1.get_oZ());
75 const double dist2 =
76 (point2.get_oX() * point2.get_oX()) + (point2.get_oY() * point2.get_oY()) + (point2.get_oZ() * point2.get_oZ());
77
78 if ((dist1 - dist2) < (-val3 * EPS * EPS)) {
79 return true;
80 }
81 if ((dist1 - dist2) > (val3 * EPS * EPS)) {
82 return false;
83 }
84
85 if ((point1.oP[index_0] - point2.oP[index_0]) < -EPS) {
86 return true;
87 }
88 if ((point1.oP[index_0] - point2.oP[index_0]) > EPS) {
89 return false;
90 }
91
92 if ((point1.oP[index_1] - point2.oP[index_1]) < -EPS) {
93 return true;
94 }
95 if ((point1.oP[index_1] - point2.oP[index_1]) > EPS) {
96 return false;
97 }
98
99 if ((point1.oP[index_2] - point2.oP[index_2]) < -EPS) {
100 return true;
101 }
102 if ((point1.oP[index_2] - point2.oP[index_2]) > EPS) {
103 return false;
104 }
105
106 return rc;
107 }
108};
109
110// For std::map<vpPoint>
111struct CompareImagePointDegenerate
112{
113 bool operator()(const vpPoint &point1, const vpPoint &point2) const
114 {
115 bool rc = false;
116 const double dist1 = (point1.get_x() * point1.get_x()) + (point1.get_y() * point1.get_y());
117 const double dist2 = (point2.get_x() * point2.get_x()) + (point2.get_y() * point2.get_y());
118 const double val2 = 2.;
119 if ((dist1 - dist2) < (-val2 * EPS * EPS)) {
120 return true;
121 }
122 if ((dist1 - dist2) > (val2 * EPS * EPS)) {
123 return false;
124 }
125
126 if ((point1.p[0] - point2.p[0]) < -EPS) {
127 return true;
128 }
129 if ((point1.p[0] - point2.p[0]) > EPS) {
130 return false;
131 }
132
133 if ((point1.p[1] - point2.p[1]) < -EPS) {
134 return true;
135 }
136 if ((point1.p[1] - point2.p[1]) > EPS) {
137 return false;
138 }
139
140 return rc;
141 }
142};
143
144// std::find_if
145struct FindDegeneratePoint
146{
147 explicit FindDegeneratePoint(const vpPoint &pt) : m_pt(pt) { }
148
149 bool operator()(const vpPoint &pt)
150 {
151 const unsigned int index_0 = 0;
152 const unsigned int index_1 = 1;
153 const unsigned int index_2 = 2;
154 bool result_cond1 = ((std::fabs(m_pt.oP[index_0] - pt.oP[index_0]) < EPS) && (std::fabs(m_pt.oP[index_1] - pt.oP[index_1]) < EPS)
155 && (std::fabs(m_pt.oP[index_2] - pt.oP[index_2]) < EPS));
156 bool result_cond2 = (std::fabs(m_pt.p[index_0] - pt.p[index_0]) < EPS) && (std::fabs(m_pt.p[index_1] - pt.p[index_1]) < EPS);
157 return result_cond1 || result_cond2;
158 }
159
160 vpPoint m_pt;
161};
162} // namespace
163#endif // DOXYGEN_SHOULD_SKIP_THIS
164
165bool vpPose::vpRansacFunctor::poseRansacImpl()
166{
167 const unsigned int size = static_cast<unsigned int>(m_listOfUniquePoints.size());
168 const unsigned int nbMinRandom = 4;
169 int nbTrials = 0;
170
171 vpPoint p; // Point used to project using the estimated pose
172
173 bool foundSolution = false;
174 while ((nbTrials < m_ransacMaxTrials) && (m_nbInliers < m_ransacNbInlierConsensus)) {
175 // Hold the list of the index of the inliers (points in the consensus set)
176 std::vector<unsigned int> cur_consensus;
177 // Hold the list of the index of the outliers
178 std::vector<unsigned int> cur_outliers;
179 // Hold the list of the index of the points randomly picked
180 std::vector<unsigned int> cur_randoms;
181 // Hold the list of the current inliers points to avoid to add a
182 // degenerate point if the flag is set
183 std::vector<vpPoint> cur_inliers;
184
185 // Use a temporary variable because if not, the cMo passed in parameters
186 // will be modified when
187 // we compute the pose for the minimal sample sets but if the pose is not
188 // correct when we pass a function pointer we do not want to modify the
189 // cMo passed in parameters
190 vpHomogeneousMatrix cMo_tmp;
191
192 // Vector of used points, initialized at false for all points
193 std::vector<bool> usedPt(size, false);
194
195 vpPose poseMin;
196 unsigned int i = 0;
197 bool stop_loop = false;
198 while ((i < nbMinRandom) && (stop_loop == false)) {
199 if (static_cast<size_t>(std::count(usedPt.begin(), usedPt.end(), true)) == usedPt.size()) {
200 // All points were picked once, break otherwise we stay in an infinite loop
201 stop_loop = true;
202 }
203 if (!stop_loop) {
204 // Pick a point randomly
205 unsigned int r_ = m_uniRand.uniform(0, size);
206
207 while (usedPt[r_]) {
208 // If already picked, pick another point randomly
209 r_ = m_uniRand.uniform(0, size);
210 }
211 // Mark this point as already picked
212 usedPt[r_] = true;
213 vpPoint pt = m_listOfUniquePoints[r_];
214
215 bool degenerate = false;
216 if (m_checkDegeneratePoints) {
217 if (std::find_if(poseMin.listOfPoints.begin(), poseMin.listOfPoints.end(), FindDegeneratePoint(pt)) !=
218 poseMin.listOfPoints.end()) {
219 degenerate = true;
220 }
221 }
222
223 if (!degenerate) {
224 poseMin.addPoint(pt);
225 cur_randoms.push_back(r_);
226 // Increment the number of points picked
227 ++i;
228 }
229 }
230 }
231
232 bool stop_for_loop = false;
233 if (poseMin.npt < nbMinRandom) {
234 ++nbTrials;
235 stop_for_loop = true;
236 }
237
238 if (!stop_for_loop) {
239 bool is_pose_valid = false;
240 double r_min = DBL_MAX;
241
242 try {
243 is_pose_valid = poseMin.computePose(vpPose::DEMENTHON_LAGRANGE_VIRTUAL_VS, cMo_tmp);
244 r_min = poseMin.computeResidual(cMo_tmp);
245 }
246 catch (...) {
247 // no need to take action
248 }
249
250 // If residual returned is not a number (NAN), set valid to false
251 if (vpMath::isNaN(r_min)) {
252 is_pose_valid = false;
253 }
254
255 // If at pose computation is OK we can continue, otherwise pick another random set
256 if (is_pose_valid) {
257 double r = sqrt(r_min) / static_cast<double>(nbMinRandom); // FS should be r = sqrt(r_min / (double)nbMinRandom);
258 // Filter the pose using some criterion (orientation angles,
259 // translations, etc.)
260 bool isPoseValid = true;
261 if (m_func != nullptr) {
262 isPoseValid = m_func(cMo_tmp);
263 if (isPoseValid) {
264 m_cMo = cMo_tmp;
265 }
266 }
267 else {
268 // No post filtering on pose, so copy cMo_temp to cMo
269 m_cMo = cMo_tmp;
270 }
271
272 if (isPoseValid && (r < m_ransacThreshold)) {
273 unsigned int nbInliersCur = 0;
274 unsigned int iter = 0;
275 std::vector<vpPoint>::const_iterator m_listofuniquepoints_end = m_listOfUniquePoints.end();
276 for (std::vector<vpPoint>::const_iterator it = m_listOfUniquePoints.begin(); it != m_listofuniquepoints_end;
277 ++it, ++iter) {
278 p.setWorldCoordinates(it->get_oX(), it->get_oY(), it->get_oZ());
279 p.track(m_cMo);
280
281 double error = sqrt(vpMath::sqr(p.get_x() - it->get_x()) + vpMath::sqr(p.get_y() - it->get_y()));
282 if (error < m_ransacThreshold) {
283 bool degenerate = false;
284 if (m_checkDegeneratePoints) {
285 if (std::find_if(cur_inliers.begin(), cur_inliers.end(), FindDegeneratePoint(*it)) != cur_inliers.end()) {
286 degenerate = true;
287 }
288 }
289
290 if (!degenerate) {
291 // the point is considered as inlier if the error is below the
292 // threshold
293 ++nbInliersCur;
294 cur_consensus.push_back(iter);
295 cur_inliers.push_back(*it);
296 }
297 else {
298 cur_outliers.push_back(iter);
299 }
300 }
301 else {
302 cur_outliers.push_back(iter);
303 }
304 }
305
306 if (nbInliersCur > m_nbInliers) {
307 foundSolution = true;
308 m_best_consensus = cur_consensus;
309 m_nbInliers = nbInliersCur;
310 }
311
312 ++nbTrials;
313
314 if (nbTrials >= m_ransacMaxTrials) {
315 foundSolution = true;
316 }
317 }
318 else {
319 ++nbTrials;
320 }
321 }
322 else {
323 ++nbTrials;
324 }
325 }
326 }
327
328 return foundSolution;
329}
330
332{
333 // Check only for adding / removing problem
334 // Do not take into account problem with element modification here
335 if (listP.size() != listOfPoints.size()) {
336 std::cerr << "You should not modify vpPose::listP!" << std::endl;
337 listOfPoints = std::vector<vpPoint>(listP.begin(), listP.end());
338 }
339
340 ransacInliers.clear();
341 ransacInlierIndex.clear();
342
343 std::vector<unsigned int> best_consensus;
344 unsigned int nbInliers = 0;
345
346 vpHomogeneousMatrix cMo_lagrange, cMo_dementhon;
347
348 const size_t minNbPoints = 4;
349 if (listOfPoints.size() < minNbPoints) {
350 throw(vpPoseException(vpPoseException::notInitializedError, "Not enough point to compute the pose"));
351 }
352
353 std::vector<vpPoint> listOfUniquePoints;
354 std::map<size_t, size_t> mapOfUniquePointIndex;
355
356 // Get RANSAC flags
357 bool prefilterDegeneratePoints = ransacFlag == PREFILTER_DEGENERATE_POINTS;
358 bool checkDegeneratePoints = ransacFlag == CHECK_DEGENERATE_POINTS;
359
360 if (prefilterDegeneratePoints) {
361 // Remove degenerate object points
362 std::map<vpPoint, size_t, CompareObjectPointDegenerate> filterObjectPointMap;
363 size_t index_pt = 0;
364 std::vector<vpPoint>::const_iterator listofpoints_end = listOfPoints.end();
365 for (std::vector<vpPoint>::const_iterator it_pt = listOfPoints.begin(); it_pt != listofpoints_end;
366 ++it_pt, ++index_pt) {
367 if (filterObjectPointMap.find(*it_pt) == filterObjectPointMap.end()) {
368 filterObjectPointMap[*it_pt] = index_pt;
369 }
370 }
371
372 std::map<vpPoint, size_t, CompareImagePointDegenerate> filterImagePointMap;
373 std::map<vpPoint, size_t, CompareObjectPointDegenerate>::const_iterator filterobjectpointmap_end = filterObjectPointMap.end();
374 for (std::map<vpPoint, size_t, CompareObjectPointDegenerate>::const_iterator it = filterObjectPointMap.begin();
375 it != filterobjectpointmap_end; ++it) {
376 if (filterImagePointMap.find(it->first) == filterImagePointMap.end()) {
377 filterImagePointMap[it->first] = it->second;
378
379 listOfUniquePoints.push_back(it->first);
380 mapOfUniquePointIndex[listOfUniquePoints.size() - 1] = it->second;
381 }
382 }
383 }
384 else {
385 // No prefiltering
386 listOfUniquePoints = listOfPoints;
387
388 size_t index_pt = 0;
389 std::vector<vpPoint>::const_iterator listofpoints_end = listOfPoints.end();
390 for (std::vector<vpPoint>::const_iterator it_pt = listOfPoints.begin(); it_pt != listofpoints_end;
391 ++it_pt, ++index_pt) {
392 mapOfUniquePointIndex[index_pt] = index_pt;
393 }
394 }
395
396 const unsigned int minNbUniquePts = 4;
397 if (listOfUniquePoints.size() < minNbUniquePts) {
398 throw(vpPoseException(vpPoseException::notInitializedError, "Not enough point to compute the pose"));
399 }
400
401#if defined(VISP_HAVE_THREADS)
402 unsigned int nbThreads = 1;
403 bool executeParallelVersion = useParallelRansac;
404#else
405 bool executeParallelVersion = false;
406#endif
407
408 if (executeParallelVersion) {
409#if defined(VISP_HAVE_THREADS)
410 if (nbParallelRansacThreads <= 0) {
411 // Get number of CPU threads
412 nbThreads = std::thread::hardware_concurrency();
413 if (nbThreads <= 1) {
414 nbThreads = 1;
415 executeParallelVersion = false;
416 }
417 }
418 else {
419 nbThreads = nbParallelRansacThreads;
420 }
421#endif
422 }
423
424 bool foundSolution = false;
425
426 if (executeParallelVersion) {
427#if defined(VISP_HAVE_THREADS)
428 std::vector<std::thread> threadpool;
429 std::vector<vpRansacFunctor> ransacWorkers;
430
431 int splitTrials = ransacMaxTrials / nbThreads;
432 for (size_t i = 0; i < static_cast<size_t>(nbThreads); ++i) {
433 unsigned int initial_seed = static_cast<unsigned int>(i);
434 if (i < static_cast<size_t>(nbThreads) - 1) {
435 ransacWorkers.emplace_back(cMo, ransacNbInlierConsensus, splitTrials, ransacThreshold, initial_seed,
436 checkDegeneratePoints, listOfUniquePoints, func);
437 }
438 else {
439 int maxTrialsRemainder = ransacMaxTrials - splitTrials * (nbThreads - 1);
440 ransacWorkers.emplace_back(cMo, ransacNbInlierConsensus, maxTrialsRemainder, ransacThreshold, initial_seed,
441 checkDegeneratePoints, listOfUniquePoints, func);
442 }
443 }
444
445 for (auto &worker : ransacWorkers) {
446 threadpool.emplace_back(&vpRansacFunctor::operator(), &worker);
447 }
448
449 for (auto &th : threadpool) {
450 th.join();
451 }
452
453 bool successRansac = false;
454 size_t best_consensus_size = 0;
455
456 for (auto &worker : ransacWorkers) {
457 if (worker.getResult()) {
458 successRansac = true;
459
460 if (worker.getBestConsensus().size() > best_consensus_size) {
461 nbInliers = worker.getNbInliers();
462 best_consensus = worker.getBestConsensus();
463 best_consensus_size = worker.getBestConsensus().size();
464 }
465 }
466 }
467
468 foundSolution = successRansac;
469#endif
470 }
471 else {
472 // Sequential RANSAC
473 vpRansacFunctor sequentialRansac(cMo, ransacNbInlierConsensus, ransacMaxTrials, ransacThreshold, 0,
474 checkDegeneratePoints, listOfUniquePoints, func);
475 sequentialRansac();
476 foundSolution = sequentialRansac.getResult();
477
478 if (foundSolution) {
479 nbInliers = sequentialRansac.getNbInliers();
480 best_consensus = sequentialRansac.getBestConsensus();
481 }
482 }
483 if (foundSolution) {
484 const unsigned int nbMinRandom = 4;
485
486 // --comment: print the nbInliers
487 // Display the random picked points (cur_randoms)
488 // Display the outliers (cur_outliers)
489
490 // Even if the cardinality of the best consensus set is inferior to
491 // ransacNbInlierConsensus, we want to refine the solution with data in
492 // best_consensus and return this pose. This is an approach used for
493 // example in p118 in Multiple View Geometry in Computer Vision, Hartley,
494 // R.~I. and Zisserman, A.
495 if (nbInliers >= nbMinRandom) {
496 // Refine the solution using all the points in the consensus set and
497 // with VVS pose estimation
498 vpPose pose;
499 size_t best_consensus_size = best_consensus.size();
500 for (size_t i = 0; i < best_consensus_size; ++i) {
501 vpPoint pt = listOfUniquePoints[best_consensus[i]];
502
503 pose.addPoint(pt);
504 ransacInliers.push_back(pt);
505 }
506
507 // Update the list of inlier index
508 std::vector<unsigned int>::const_iterator best_consensus_end = best_consensus.end();
509 for (std::vector<unsigned int>::const_iterator it_index = best_consensus.begin();
510 it_index != best_consensus_end; ++it_index) {
511 ransacInlierIndex.push_back(static_cast<unsigned int>(mapOfUniquePointIndex[*it_index]));
512 }
513
514 pose.setCovarianceComputation(computeCovariance);
516
517 // In some rare cases, the final pose could not respect the pose
518 // criterion even if the 4 minimal points picked respect the pose
519 // criterion.
520 if ((func != nullptr) && (!func(cMo))) {
521 return false;
522 }
523
524 if (computeCovariance) {
525 covarianceMatrix = pose.covarianceMatrix;
526 }
527 }
528 else {
529 return false;
530 }
531 }
532
533 return foundSolution;
534}
535
536int vpPose::computeRansacIterations(double probability, double epsilon, const int sampleSize, int maxIterations)
537{
538 probability = std::max<double>(probability, 0.0);
539 probability = std::min<double>(probability, 1.0);
540 epsilon = std::max<double>(epsilon, 0.0);
541 epsilon = std::min<double>(epsilon, 1.0);
542
543 if (vpMath::nul(epsilon)) {
544 // no outliers
545 return 1;
546 }
547
548 if (maxIterations <= 0) {
549 maxIterations = std::numeric_limits<int>::max();
550 }
551
552 double logarg, logval, N;
553 logarg = -std::pow(1.0 - epsilon, sampleSize);
554#ifdef VISP_HAVE_FUNC_LOG1P
555 logval = log1p(logarg);
556#else
557 logval = log(1.0 + logarg);
558#endif
559 if (vpMath::nul(logval, std::numeric_limits<double>::epsilon())) {
560 std::cerr << "vpMath::nul(log(1.0 - std::pow(1.0 - epsilon, "
561 "sampleSize)), std::numeric_limits<double>::epsilon())"
562 << std::endl;
563 return 0;
564 }
565
566 N = log(std::max<double>(1.0 - probability, std::numeric_limits<double>::epsilon())) / logval;
567 if ((logval < 0.0) && (N < maxIterations)) {
568 return static_cast<int>(ceil(N));
569 }
570
571 return maxIterations;
572}
573
574void vpPose::findMatch(std::vector<vpPoint> &p2D, std::vector<vpPoint> &p3D,
575 const unsigned int &numberOfInlierToReachAConsensus, const double &threshold,
576 unsigned int &ninliers, std::vector<vpPoint> &listInliers, vpHomogeneousMatrix &cMo,
577 const int &maxNbTrials, bool useParallelRansac, unsigned int nthreads,
579{
580 vpPose pose;
581
582 size_t p2D_size = p2D.size();
583 size_t p3D_size = p3D.size();
584 for (size_t i = 0; i < p2D_size; ++i) {
585 for (size_t j = 0; j < p3D_size; ++j) {
586 vpPoint pt(p3D[j].getWorldCoordinates());
587 pt.set_x(p2D[i].get_x());
588 pt.set_y(p2D[i].get_y());
589 pose.addPoint(pt);
590 }
591 }
592
593 const size_t minNbPts = 4;
594 if (pose.listP.size() < minNbPts) {
595 throw(vpPoseException(vpPoseException::notEnoughPointError, "Not enough point (%d) to compute the pose by ransac",
596 pose.listP.size()));
597 }
598 else {
599 pose.setUseParallelRansac(useParallelRansac);
600 pose.setNbParallelRansacThreads(nthreads);
601 // Since we add duplicate points, we need to check for degenerate configuration
603 pose.setRansacMaxTrials(maxNbTrials);
604 pose.setRansacNbInliersToReachConsensus(numberOfInlierToReachAConsensus);
605 pose.setRansacThreshold(threshold);
606 pose.computePose(vpPose::RANSAC, cMo, func);
607 ninliers = pose.getRansacNbInliers();
608 listInliers = pose.getRansacInliers();
609 }
610}
611
612END_VISP_NAMESPACE
Implementation of an homogeneous matrix and operations on such kind of matrices.
static bool isNaN(double value)
Definition vpMath.cpp:101
static double sqr(double x)
Definition vpMath.h:203
static bool nul(double x, double threshold=0.001)
Definition vpMath.h:453
Class that defines a 3D point in the object frame and allows forward projection of a 3D point in the ...
Definition vpPoint.h:79
double get_oX() const
Get the point oX coordinate in the object frame.
Definition vpPoint.cpp:418
void set_x(double x)
Set the point x coordinate in the image plane.
Definition vpPoint.cpp:471
double get_y() const
Get the point y coordinate in the image plane.
Definition vpPoint.cpp:429
double get_oZ() const
Get the point oZ coordinate in the object frame.
Definition vpPoint.cpp:422
double get_x() const
Get the point x coordinate in the image plane.
Definition vpPoint.cpp:427
double get_oY() const
Get the point oY coordinate in the object frame.
Definition vpPoint.cpp:420
void set_y(double y)
Set the point y coordinate in the image plane.
Definition vpPoint.cpp:473
Error that can be emitted by the vpPose class and its derivatives.
@ notEnoughPointError
Not enough points to compute the pose.
@ notInitializedError
Something is not initialized.
void setRansacMaxTrials(const int &rM)
Definition vpPose.h:416
static int computeRansacIterations(double probability, double epsilon, const int sampleSize=4, int maxIterations=2000)
void addPoint(const vpPoint &P)
Definition vpPose.cpp:96
void setRansacNbInliersToReachConsensus(const unsigned int &nbC)
Definition vpPose.h:397
@ RANSAC
Definition vpPose.h:92
@ DEMENTHON_LAGRANGE_VIRTUAL_VS
Definition vpPose.h:103
void setCovarianceComputation(const bool &flag)
Definition vpPose.h:439
static void findMatch(std::vector< vpPoint > &p2D, std::vector< vpPoint > &p3D, const unsigned int &numberOfInlierToReachAConsensus, const double &threshold, unsigned int &ninliers, std::vector< vpPoint > &listInliers, vpHomogeneousMatrix &cMo, const int &maxNbTrials=10000, bool useParallelRansac=true, unsigned int nthreads=0, FuncCheckValidityPose func=nullptr)
unsigned int npt
Number of point used in pose computation.
Definition vpPose.h:118
bool computePose(vpPoseMethodType method, vpHomogeneousMatrix &cMo, FuncCheckValidityPose func=nullptr)
Definition vpPose.cpp:385
std::vector< vpPoint > getRansacInliers() const
Definition vpPose.h:431
std::list< vpPoint > listP
Array of point (use here class vpPoint).
Definition vpPose.h:119
double computeResidual(const vpHomogeneousMatrix &cMo) const
Compute and return the sum of squared residuals expressed in meter^2 for the pose matrix cMo.
Definition vpPose.cpp:298
bool(* FuncCheckValidityPose)(const vpHomogeneousMatrix &)
Definition vpPose.h:125
void setRansacFilterFlag(const RANSAC_FILTER_FLAGS &flag)
Definition vpPose.h:469
vpPose()
Definition vpPose.cpp:65
@ CHECK_DEGENERATE_POINTS
Definition vpPose.h:115
@ PREFILTER_DEGENERATE_POINTS
Definition vpPose.h:114
unsigned int getRansacNbInliers() const
Definition vpPose.h:421
void setUseParallelRansac(bool use)
Definition vpPose.h:500
void setNbParallelRansacThreads(int nb)
Definition vpPose.h:486
bool poseRansac(vpHomogeneousMatrix &cMo, FuncCheckValidityPose func=nullptr)
void setRansacThreshold(const double &t)
Definition vpPose.h:402
vpColVector p
Definition vpTracker.h:69