Visual Servoing Platform  version 3.6.1 under development (2024-07-27)
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 
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
61 namespace
62 {
63 // For std::map<vpPoint>
64 struct 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>
111 struct 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
145 struct 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 
165 bool 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 
331 bool vpPose::poseRansac(vpHomogeneousMatrix &cMo, FuncCheckValidityPose func)
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); //((unsigned int) time(nullptr) ^ 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 
484  if (foundSolution) {
485  const unsigned int nbMinRandom = 4;
486 
487  // --comment: print the nbInliers
488  // Display the random picked points (cur_randoms)
489  // Display the outliers (cur_outliers)
490 
491  // Even if the cardinality of the best consensus set is inferior to
492  // ransacNbInlierConsensus, we want to refine the solution with data in
493  // best_consensus and return this pose. This is an approach used for
494  // example in p118 in Multiple View Geometry in Computer Vision, Hartley,
495  // R.~I. and Zisserman, A.
496  if (nbInliers >= nbMinRandom) // if(nbInliers >= (unsigned)ransacNbInlierConsensus)
497  {
498  // Refine the solution using all the points in the consensus set and
499  // with VVS pose estimation
500  vpPose pose;
501  size_t best_consensus_size = best_consensus.size();
502  for (size_t i = 0; i < best_consensus_size; ++i) {
503  vpPoint pt = listOfUniquePoints[best_consensus[i]];
504 
505  pose.addPoint(pt);
506  ransacInliers.push_back(pt);
507  }
508 
509  // Update the list of inlier index
510  std::vector<unsigned int>::const_iterator best_consensus_end = best_consensus.end();
511  for (std::vector<unsigned int>::const_iterator it_index = best_consensus.begin();
512  it_index != best_consensus_end; ++it_index) {
513  ransacInlierIndex.push_back(static_cast<unsigned int>(mapOfUniquePointIndex[*it_index]));
514  }
515 
516  pose.setCovarianceComputation(computeCovariance);
518 
519  // In some rare cases, the final pose could not respect the pose
520  // criterion even if the 4 minimal points picked respect the pose
521  // criterion.
522  if ((func != nullptr) && (!func(cMo))) {
523  return false;
524  }
525 
526  if (computeCovariance) {
527  covarianceMatrix = pose.covarianceMatrix;
528  }
529  }
530  else {
531  return false;
532  }
533  }
534 
535  return foundSolution;
536 }
537 
538 int vpPose::computeRansacIterations(double probability, double epsilon, const int sampleSize, int maxIterations)
539 {
540  probability = std::max<double>(probability, 0.0);
541  probability = std::min<double>(probability, 1.0);
542  epsilon = std::max<double>(epsilon, 0.0);
543  epsilon = std::min<double>(epsilon, 1.0);
544 
545  if (vpMath::nul(epsilon)) {
546  // no outliers
547  return 1;
548  }
549 
550  if (maxIterations <= 0) {
551  maxIterations = std::numeric_limits<int>::max();
552  }
553 
554  double logarg, logval, N;
555  logarg = -std::pow(1.0 - epsilon, sampleSize);
556 #ifdef VISP_HAVE_FUNC_LOG1P
557  logval = log1p(logarg);
558 #else
559  logval = log(1.0 + logarg);
560 #endif
561  if (vpMath::nul(logval, std::numeric_limits<double>::epsilon())) {
562  std::cerr << "vpMath::nul(log(1.0 - std::pow(1.0 - epsilon, "
563  "sampleSize)), std::numeric_limits<double>::epsilon())"
564  << std::endl;
565  return 0;
566  }
567 
568  N = log(std::max<double>(1.0 - probability, std::numeric_limits<double>::epsilon())) / logval;
569  if ((logval < 0.0) && (N < maxIterations)) {
570  return static_cast<int>(ceil(N));
571  }
572 
573  return maxIterations;
574 }
575 
576 void vpPose::findMatch(std::vector<vpPoint> &p2D, std::vector<vpPoint> &p3D,
577  const unsigned int &numberOfInlierToReachAConsensus, const double &threshold,
578  unsigned int &ninliers, std::vector<vpPoint> &listInliers, vpHomogeneousMatrix &cMo,
579  const int &maxNbTrials, bool useParallelRansac, unsigned int nthreads,
580  FuncCheckValidityPose func)
581 {
582  vpPose pose;
583 
584  size_t p2D_size = p2D.size();
585  size_t p3D_size = p3D.size();
586  for (size_t i = 0; i < p2D_size; ++i) {
587  for (size_t j = 0; j < p3D_size; ++j) {
588  vpPoint pt(p3D[j].getWorldCoordinates());
589  pt.set_x(p2D[i].get_x());
590  pt.set_y(p2D[i].get_y());
591  pose.addPoint(pt);
592  }
593  }
594 
595  const size_t minNbPts = 4;
596  if (pose.listP.size() < minNbPts) {
597  throw(vpPoseException(vpPoseException::notEnoughPointError, "Not enough point (%d) to compute the pose by ransac",
598  pose.listP.size()));
599  }
600  else {
601  pose.setUseParallelRansac(useParallelRansac);
602  pose.setNbParallelRansacThreads(nthreads);
603  // Since we add duplicate points, we need to check for degenerate configuration
605  pose.setRansacMaxTrials(maxNbTrials);
606  pose.setRansacNbInliersToReachConsensus(numberOfInlierToReachAConsensus);
607  pose.setRansacThreshold(threshold);
608  pose.computePose(vpPose::RANSAC, cMo, func);
609  ninliers = pose.getRansacNbInliers();
610  listInliers = pose.getRansacInliers();
611  }
612 }
613 
614 END_VISP_NAMESPACE
void track(const vpHomogeneousMatrix &cMo)
Implementation of an homogeneous matrix and operations on such kind of matrices.
static bool isNaN(double value)
Definition: vpMath.cpp:92
static double sqr(double x)
Definition: vpMath.h:203
static bool nul(double x, double threshold=0.001)
Definition: vpMath.h:449
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:411
void set_x(double x)
Set the point x coordinate in the image plane.
Definition: vpPoint.cpp:464
double get_y() const
Get the point y coordinate in the image plane.
Definition: vpPoint.cpp:422
double get_oZ() const
Get the point oZ coordinate in the object frame.
Definition: vpPoint.cpp:415
double get_x() const
Get the point x coordinate in the image plane.
Definition: vpPoint.cpp:420
double get_oY() const
Get the point oY coordinate in the object frame.
Definition: vpPoint.cpp:413
void setWorldCoordinates(double oX, double oY, double oZ)
Definition: vpPoint.cpp:111
void set_y(double y)
Set the point y coordinate in the image plane.
Definition: vpPoint.cpp:466
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.
Class used for pose computation from N points (pose from point only). Some of the algorithms implemen...
Definition: vpPose.h:77
void setRansacMaxTrials(const int &rM)
Definition: vpPose.h:406
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:387
@ RANSAC
Definition: vpPose.h:87
@ DEMENTHON_LAGRANGE_VIRTUAL_VS
Definition: vpPose.h:98
void setCovarianceComputation(const bool &flag)
Definition: vpPose.h:429
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:113
bool computePose(vpPoseMethodType method, vpHomogeneousMatrix &cMo, FuncCheckValidityPose func=nullptr)
Definition: vpPose.cpp:385
std::list< vpPoint > listP
Array of point (use here class vpPoint)
Definition: vpPose.h:114
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
void setRansacFilterFlag(const RANSAC_FILTER_FLAGS &flag)
Definition: vpPose.h:459
@ CHECK_DEGENERATE_POINTS
Definition: vpPose.h:110
@ PREFILTER_DEGENERATE_POINTS
Definition: vpPose.h:109
unsigned int getRansacNbInliers() const
Definition: vpPose.h:411
void setUseParallelRansac(bool use)
Definition: vpPose.h:490
std::vector< vpPoint > getRansacInliers() const
Definition: vpPose.h:421
void setNbParallelRansacThreads(int nb)
Definition: vpPose.h:476
bool poseRansac(vpHomogeneousMatrix &cMo, FuncCheckValidityPose func=nullptr)
void setRansacThreshold(const double &t)
Definition: vpPose.h:392
vpColVector p
Definition: vpTracker.h:69