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