Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
AbsoluteOrientationRANSAC.cpp
1 #include "AbsoluteOrientationRANSAC.hh"
2 #include <Base/Math/Matrix3x3.hh>
3 #include <Base/Math/Matrix.hh>
4 #include <Base/Math/Vector.hh>
5 #include <Base/Geometry/Quaternion.hh>
6 #include <MathAlgo/SVD.hh>
7 #include <iostream>
8 
9 #ifdef BIAS_HAVE_GSL
10 // Include for InvChiSquareCulmProbFun()
11 # include <MathAlgo/GSL.hh>
12 #endif
13 
14 using namespace std;
15 using namespace BIAS;
16 
17 AbsoluteOrientationRANSAC::AbsoluteOrientationRANSAC()
18  : sampleSize_(AbsoluteOrientation::MIN_CORRESPONDENCES),
19  numSamples_(100), maxError_(0.01),
20  minRatio_(0.75), refine_(true), greedy_(false),
21  useWeightedTargetFunction_(false)
22 {
23 #ifndef BIAS_DEBUG
24  randomizer_.Reset();
25 #endif
26 }
27 
29 {
30 }
31 
33 SetSignificance(double significance)
34 {
35  if (significance <= 0.0 || significance >= 1.0) {
36  BIASERR("Invalid significance level " << significance <<
37  " given (must be between 0.0 and 1.0)!");
38  } else {
39 #ifdef BIAS_HAVE_GSL
40  maxError_ = InvChiSquareCulmProbFun(1.0-significance, 3); // 3 dof
41 #else
42  BIASWARNONCE("No GSL support, using fixed significance level of 0.05!");
43  significance = 0.05;
44  maxError_ = 5.9915;
45 #endif
46  }
47 }
48 
49 int AbsoluteOrientationRANSAC::
50 Compute_(const std::vector< BIAS::Vector3<double> > &X,
51  const std::vector< BIAS::Vector3<double> > &Y,
52  const std::vector< BIAS::Matrix3x3<double> > &CovX,
53  const std::vector< BIAS::Matrix3x3<double> > &CovY,
55  double &ds, bool enforceScale,
56  std::vector<bool> &inliers, std::vector<double> &errors,
57  double &errorSum, const std::vector<double> &w)
58 {
59  const unsigned int num = X.size();
60  const bool useCovs = (CovX.size() > 0 || CovY.size() > 0);
61  const bool useWeights = (w.size() > 0);
62 
63  BIASASSERT(num >= sampleSize_);
64  BIASASSERT(X.size() == num && Y.size() == num);
65  BIASASSERT(!useCovs || (CovX.size() == num && CovY.size() == num));
66  BIASASSERT(!useWeights || w.size() == num);
67 #ifdef BIAS_DEBUG
68  if (useWeights && useCovs) {
69  BEXCEPTION("Weights and covariances should NOT be used at the same time "
70  "in robust absolute orientation estimation!");
71  }
72 #endif
73 
74  int res = 0;
75  std::vector<int> samples(0);
76  std::vector< Vector3<double> > sampleX(0);
77  std::vector< Vector3<double> > sampleY(0);
78  std::vector< Matrix3x3<double> > sampleCovX(0);
79  std::vector< Matrix3x3<double> > sampleCovY(0);
80  std::vector<double> samplew(0);
81  BIAS::RMatrix actdR, bestdR;
82  BIAS::Vector3<double> actdt, bestdt;
83  double actds, bestds = 0.0;
84  double actScore = 0.0, bestScore = 0.0;
85  double actErrorSum = 0.0;
86  //double bestErrorSum = 0.0;
87  int actInlierCount = -1, bestInlierCount = -1;
88  std::vector<bool> actInliers;
89  std::vector<double> actErrors;
90  bool init = false;
91  bool done = false;
92 
93  // Evaluate each sample solution and find best solution
94 
95  for (unsigned int k = 0; k < numSamples_ && !done; k++)
96  {
97  res = CreateRandomSample_(sampleSize_, X, Y, CovX, CovY, w,
98  samples, sampleX, sampleY,
99  sampleCovX, sampleCovY, samplew);
100  BIASASSERT(res == (int)sampleSize_);
101 
102  actdR = dR; actdt = dt; actds = ds;
103  res = solver_.Compute_(sampleX, sampleY, actdR, actdt, actds,
104  enforceScale, samplew);
105  if (res == 0) {
106  actInlierCount = EvaluateInliers_(actInliers, actErrors, actErrorSum,
107  X, Y, CovX, CovY, actdR, actdt, actds, w);
108  if (useWeightedTargetFunction_)
109  {
110  actScore = 0.0;
111  for (register unsigned int i = 0; i < num; i++) {
112  if (actInliers[i] && actErrors[i] <= maxError_) {
113  actScore += fabs(maxError_-actErrors[i])/maxError_;
114  }
115  }
116  } else {
117  actScore = (double)actInlierCount;
118  }
119  if (!init || actScore > bestScore) {
120  bestScore = actScore;
121  bestInlierCount = actInlierCount;
122  //bestErrorSum = actErrorSum;
123  bestdR = actdR;
124  bestdt = actdt;
125  bestds = actds;
126  init = true;
127  done = (greedy_ && bestInlierCount/(double)num >= minRatio_);
128  }
129  }
130  }
131 
132  if (init && bestInlierCount >= (int)sampleSize_)
133  // && bestInlierCount/(double)num >= minRatio_)
134  {
135  // Refine best solution optionally
136  if (refine_)
137  {
138  EvaluateInliers_(actInliers, actErrors, actErrorSum,
139  X, Y, CovX, CovY, bestdR, bestdt, bestds, w);
140  samples.clear();
141  sampleX.clear();
142  sampleY.clear();
143  samples.reserve(bestInlierCount);
144  sampleX.reserve(bestInlierCount);
145  sampleY.reserve(bestInlierCount);
146  if (useCovs) {
147  sampleCovX.clear();
148  sampleCovY.clear();
149  sampleCovX.reserve(bestInlierCount);
150  sampleCovY.reserve(bestInlierCount);
151  }
152  if (useWeights) {
153  samplew.clear();
154  samplew.reserve(bestInlierCount);
155  }
156  for (register unsigned int i = 0; i < num; i++)
157  {
158  if (actInliers[i]) {
159  samples.push_back(i);
160  sampleX.push_back(X[i]);
161  sampleY.push_back(Y[i]);
162  if (useCovs) {
163  sampleCovX.push_back(CovX[i]);
164  sampleCovY.push_back(CovY[i]);
165  }
166  if (useWeights) {
167  samplew.push_back(w[i]);
168  }
169  }
170  }
171  BIASASSERT((int)samples.size() == bestInlierCount);
172  dR = bestdR; dt = bestdt; ds = bestds;
173  res = solver_.Compute_(sampleX, sampleY, dR, dt, ds,
174  enforceScale, samplew);
175  if (res == 0) {
176  return EvaluateInliers_(inliers, errors, errorSum,
177  X, Y, CovX, CovY, dR, dt, ds, w);
178  } else {
179  BIASWARN("Refinement of RANSAC solution failed!");
180  return -1;
181  }
182  }
183  } else {
184  dR = bestdR; dt = bestdt; ds = bestds;
185  return EvaluateInliers_(inliers, errors, errorSum,
186  X, Y, CovX, CovY, dR, dt, ds, w);
187  }
188  BIASWARN("RANSAC failed, found no solution with enough inliers "
189  << "(found " << bestInlierCount << ", needed min. "
190  << sampleSize_ << " inliers)!");
191  return -1;
192 }
193 
194 int AbsoluteOrientationRANSAC::
195 ComputeRotation_(const std::vector< BIAS::Vector3<double> > &X,
196  const std::vector< BIAS::Vector3<double> > &Y,
197  const std::vector< BIAS::Matrix3x3<double> > &CovX,
198  const std::vector< BIAS::Matrix3x3<double> > &CovY,
199  BIAS::RMatrix &dR, std::vector<bool> &inliers,
200  std::vector<double> &errors, double &errorSum,
201  const std::vector<double> &w)
202 {
203  const unsigned int num = X.size();
204  const bool useCovs = (CovX.size() > 0 || CovY.size() > 0);
205  const bool useWeights = (w.size() > 0);
206 
207  BIASASSERT(num >= sampleSize_);
208  BIASASSERT(X.size() == num && Y.size() == num);
209  BIASASSERT(!useCovs || (CovX.size() == num && CovY.size() == num));
210  BIASASSERT(!useWeights || w.size() == num);
211 #ifdef BIAS_DEBUG
212  if (useWeights && useCovs) {
213  BEXCEPTION("Weights and covariances should NOT be used at the same time "
214  "in robust absolute rotation estimation!");
215  }
216 #endif
217 
218  int res = 0;
219  std::vector<int> samples(0);
220  std::vector< Vector3<double> > sampleX(0);
221  std::vector< Vector3<double> > sampleY(0);
222  std::vector< Matrix3x3<double> > sampleCovX(0);
223  std::vector< Matrix3x3<double> > sampleCovY(0);
224  std::vector<double> samplew(0);
225  BIAS::RMatrix actdR, bestdR;
226  double actScore = 0.0, bestScore = 0.0;
227  double actErrorSum = 0.0;
228  //bestErrorSum = 0.0;
229  int actInlierCount = -1, bestInlierCount = -1;
230  std::vector<bool> actInliers;
231  std::vector<double> actErrors;
232  bool init = false;
233  bool done = false;
234 
235  // Evaluate each sample solution and find best solution
236 
237  for (unsigned int k = 0; k < numSamples_ && !done; k++)
238  {
239  res = CreateRandomSample_(sampleSize_, X, Y, CovX, CovY, w,
240  samples, sampleX, sampleY,
241  sampleCovX, sampleCovY, samplew);
242  BIASASSERT(res == (int)sampleSize_);
243 
244  actdR = dR;
245  res = solver_.ComputeRotation(sampleX, sampleY, actdR, samplew);
246  if (res == 0) {
247  actInlierCount = EvaluateInliers_(actInliers, actErrors, actErrorSum,
248  X, Y, CovX, CovY, actdR, w);
249  if (useWeightedTargetFunction_)
250  {
251  actScore = 0.0;
252  for (register unsigned int i = 0; i < num; i++) {
253  if (actInliers[i] && actErrors[i] <= maxError_) {
254  actScore += fabs(maxError_-actErrors[i])/maxError_;
255  }
256  }
257  } else {
258  actScore = (double)actInlierCount;
259  }
260  if (!init || actScore > bestScore) {
261  bestScore = actScore;
262  bestInlierCount = actInlierCount;
263  //bestErrorSum = actErrorSum;
264  bestdR = actdR;
265  init = true;
266  done = (greedy_ && bestInlierCount/(double)num >= minRatio_);
267  }
268  }
269 
270  }
271 
272  if (init && bestInlierCount >= (int)sampleSize_)
273  // && bestInlierCount/(double)num >= minRatio_)
274  {
275  // Refine best solution optionally
276  if (refine_) {
277  EvaluateInliers_(actInliers, actErrors, actErrorSum,
278  X, Y, CovX, CovY, bestdR, w);
279  samples.clear();
280  sampleX.clear();
281  sampleY.clear();
282  samples.reserve(bestInlierCount);
283  sampleX.reserve(bestInlierCount);
284  sampleY.reserve(bestInlierCount);
285  if (useCovs) {
286  sampleCovX.clear();
287  sampleCovY.clear();
288  sampleCovX.reserve(bestInlierCount);
289  sampleCovY.reserve(bestInlierCount);
290  }
291  if (useWeights) {
292  samplew.clear();
293  samplew.reserve(bestInlierCount);
294  }
295  for (register unsigned int i = 0; i < num; i++)
296  {
297  if (actInliers[i]) {
298  samples.push_back(i);
299  sampleX.push_back(X[i]);
300  sampleY.push_back(Y[i]);
301  if (useCovs) {
302  sampleCovX.push_back(CovX[i]);
303  sampleCovY.push_back(CovY[i]);
304  }
305  if (useWeights) {
306  samplew.push_back(w[i]);
307  }
308  }
309  }
310  BIASASSERT((int)samples.size() == bestInlierCount);
311  dR = bestdR;
312  res = solver_.ComputeRotation(sampleX, sampleY, dR, samplew);
313  if (res == 0) {
314  return EvaluateInliers_(inliers, errors, errorSum,
315  X, Y, CovX, CovY, dR, w);
316  } else {
317  BIASWARN("Refinement of RANSAC solution failed!");
318  return -1;
319  }
320  }
321  } else {
322  dR = bestdR;
323  return EvaluateInliers_(inliers, errors, errorSum,
324  X, Y, CovX, CovY, dR, w);
325  }
326  BIASWARN("RANSAC failed, found no solution with enough inliers "
327  << "(found " << bestInlierCount << ", needed min. "
328  << sampleSize_ << " inliers)!");
329  return -1;
330 }
331 
333 GetResidualErrors(std::vector<double> &errors,
334  const std::vector< BIAS::Vector3<double> > &X,
335  const std::vector< BIAS::Vector3<double> > &Y,
336  const BIAS::RMatrix &dR, const BIAS::Vector3<double> &dt,
337  const double &ds, const std::vector<bool> &inliers,
338  const std::vector<double> &w)
339 {
340  const unsigned int num = X.size();
341 #ifdef BIASASSERT_ISACTIVE
342  const bool useWeights = (w.size() > 0);
343 #endif //BIAS_DEBUG
344  const bool useInliers = (inliers.size() > 0);
345 
346  BIASASSERT(X.size() == num && Y.size() == num);
347  BIASASSERT(!useInliers || inliers.size() == num);
348  BIASASSERT(!useWeights || w.size() == num);
349 
350  // Compute residual error of inliers only
351  if (useInliers) {
352  double errorSum = 0.0;
353  solver_.GetResidualErrors(errors, X, Y, dR, dt, ds, w);
354  for (register unsigned int i = 0; i < num; i++) {
355  if (inliers[i]) {
356  errorSum += fabs(errors[i]);
357  }
358  }
359  return errorSum;
360  } else {
361  return solver_.GetResidualErrors(errors, X, Y, dR, dt, ds, w);
362  }
363 }
364 
366 GetResidualErrors(std::vector<double> &errors,
367  const std::vector< BIAS::Vector3<double> > &X,
368  const std::vector< BIAS::Vector3<double> > &Y,
369  const std::vector< BIAS::Matrix3x3<double> > &CovX,
370  const std::vector< BIAS::Matrix3x3<double> > &CovY,
371  const BIAS::RMatrix &dR, const BIAS::Vector3<double> &dt,
372  const double &ds, const std::vector<bool> &inliers)
373 {
374  const unsigned int num = X.size();
375  const bool useInliers = (inliers.size() > 0);
376 
377  BIASASSERT(X.size() == num && Y.size() == num);
378  BIASASSERT(CovX.size() == num && CovY.size() == num);
379  BIASASSERT(!useInliers || inliers.size() == num);
380 
381  // Compute residual error of inliers only
382  if (useInliers) {
383  double errorSum = 0.0;
384  solver_.GetResidualErrors(errors, X, Y, CovX, CovY, dR, dt, ds);
385  for (register unsigned int i = 0; i < num; i++) {
386  if (inliers[i]) {
387  errorSum += fabs(errors[i]);
388  }
389  }
390  return errorSum;
391  } else {
392  return solver_.GetResidualErrors(errors, X, Y, CovX, CovY, dR, dt, ds);
393  }
394 }
395 
397 GetResidualErrors(std::vector<double> &errors,
398  const std::vector< BIAS::Vector3<double> > &X,
399  const std::vector< BIAS::Vector3<double> > &Y,
400  const BIAS::RMatrix &dR, const std::vector<bool> &inliers,
401  const std::vector<double> &w)
402 {
403  const unsigned int num = X.size();
404 #ifdef BIASASSERT_ISACTIVE
405  const bool useWeights = (w.size() > 0);
406 #endif //BIAS_DEBUG
407  const bool useInliers = (inliers.size() > 0);
408 
409  BIASASSERT(X.size() == num && Y.size() == num);
410  BIASASSERT(!useInliers || inliers.size() == num);
411  BIASASSERT(!useWeights || w.size() == num);
412 
413  // Compute residual error of inliers only
414  if (useInliers) {
415  double errorSum = 0.0;
416  solver_.GetResidualErrors(errors, X, Y, dR, w);
417  for (register unsigned int i = 0; i < num; i++) {
418  if (inliers[i]) {
419  errorSum += fabs(errors[i]);
420  }
421  }
422  return errorSum;
423  } else {
424  return solver_.GetResidualErrors(errors, X, Y, dR, w);
425  }
426 }
427 
429 GetResidualErrors(std::vector<double> &errors,
430  const std::vector< BIAS::Vector3<double> > &X,
431  const std::vector< BIAS::Vector3<double> > &Y,
432  const std::vector< BIAS::Matrix3x3<double> > &CovX,
433  const std::vector< BIAS::Matrix3x3<double> > &CovY,
434  const BIAS::RMatrix &dR, const std::vector<bool> &inliers)
435 {
436  const unsigned int num = X.size();
437  const bool useInliers = (inliers.size() > 0);
438 
439  BIASASSERT(X.size() == num && Y.size() == num);
440  BIASASSERT(CovX.size() == num && CovY.size() == num);
441  BIASASSERT(!useInliers || inliers.size() == num);
442 
443  // Compute residual error of inliers only
444  if (useInliers) {
445  double errorSum = 0.0;
446  solver_.GetResidualErrors(errors, X, Y, CovX, CovY, dR);
447  for (register unsigned int i = 0; i < num; i++) {
448  if (inliers[i]) {
449  errorSum += fabs(errors[i]);
450  }
451  }
452  return errorSum;
453  } else {
454  return solver_.GetResidualErrors(errors, X, Y, CovX, CovY, dR);
455  }
456 }
457 
458 int AbsoluteOrientationRANSAC::
459 CreateRandomSample_(unsigned int samplesize,
460  const std::vector< Vector3<double> > &X,
461  const std::vector< Vector3<double> > &Y,
462  const std::vector< Matrix3x3<double> > &CovX,
463  const std::vector< Matrix3x3<double> > &CovY,
464  const std::vector<double> &w,
465  std::vector<int> &samples,
466  std::vector< Vector3<double> > &sampleX,
467  std::vector< Vector3<double> > &sampleY,
468  std::vector< Matrix3x3<double> > &sampleCovX,
469  std::vector< Matrix3x3<double> > &sampleCovY,
470  std::vector<double> &samplew)
471 {
472  const unsigned int num = X.size();
473  const bool useCovs = (CovX.size() > 0 || CovY.size() > 0);
474  const bool useWeights = (w.size() > 0);
475 
476  BIASASSERT(X.size() == num && Y.size() == num);
477  BIASASSERT(!useCovs || (CovX.size() == num && CovY.size() == num));
478  BIASASSERT(!useWeights || w.size() == num);
479  BIASASSERT(num >= samplesize);
480 
481  samples.clear();
482  sampleX.clear();
483  sampleY.clear();
484  samples.reserve(samplesize);
485  sampleX.reserve(samplesize);
486  sampleY.reserve(samplesize);
487  if (useCovs) {
488  sampleCovX.clear();
489  sampleCovY.clear();
490  sampleCovX.reserve(samplesize);
491  sampleCovY.reserve(samplesize);
492  }
493  if (useWeights) {
494  samplew.clear();
495  samplew.reserve(samplesize);
496  }
497  int r;
498  std::vector<bool> selected(num, false);
499  for (register unsigned int i = 0; i < samplesize; i++) {
500  r = randomizer_.GetUniformDistributedInt(0, int(num)-1);
501  for (register unsigned int j = 0; selected[r] && j < num; j++) {
502  r = (r+1) % num;
503  }
504  selected[r] = true;
505  samples.push_back(r);
506  sampleX.push_back(X[r]);
507  sampleY.push_back(Y[r]);
508  if (useCovs) {
509  sampleCovX.push_back(CovX[r]);
510  sampleCovY.push_back(CovY[r]);
511  }
512  if (useWeights) {
513  samplew.push_back(w[r]);
514  }
515  }
516  return samples.size();
517 }
518 
519 int AbsoluteOrientationRANSAC::
520 EvaluateInliers_(std::vector<bool> &inliers,
521  std::vector<double> &errors, double &errorSum,
522  const std::vector< Vector3<double> > &X,
523  const std::vector< Vector3<double> > &Y,
524  const std::vector< Matrix3x3<double> > &CovX,
525  const std::vector< Matrix3x3<double> > &CovY,
526  const RMatrix &dR, const Vector3<double> &dt, const double &ds,
527  const std::vector<double> &w)
528 {
529  const unsigned int num = X.size();
530  const bool useCovs = (CovX.size() > 0 || CovY.size() > 0);
531 #ifdef BIAS_DEBUG
532  const bool useWeights = (w.size() > 0);
533 #endif //BIAS_DEBUG
534  BIASASSERT(X.size() == num && Y.size() == num);
535  BIASASSERT(!useCovs || (CovX.size() == num && CovY.size() == num));
536  BIASASSERT(!useWeights || w.size() == num);
537 #ifdef BIAS_DEBUG
538  if (useWeights && useCovs) {
539  BIASERR("Weights and covariances should NOT be used at the same time!");
540  BIASABORT;
541  }
542 #endif
543 
544  // Compute residual errors for all correspondences
545  if (useCovs) {
546  solver_.GetResidualErrors(errors, X, Y, CovX, CovY, dR, dt, ds);
547  } else {
548  solver_.GetResidualErrors(errors, X, Y, dR, dt, ds, w);
549  }
550 
551  // Compute inliers and squared error sum for inliers only
552  inliers.resize(num);
553  errorSum = 0.0;
554  int inlierCount = 0;
555  double error;
556  for (register unsigned int i = 0; i < num; i++) {
557  error = fabs(errors[i]);
558  if (error > maxError_) {
559  inliers[i] = false;
560  } else {
561  inliers[i] = true;
562  inlierCount++;
563  errorSum += error;
564  }
565  }
566  return inlierCount;
567 }
568 
569 int AbsoluteOrientationRANSAC::
570 EvaluateInliers_(std::vector<bool> &inliers,
571  std::vector<double> &errors, double &errorSum,
572  const std::vector< Vector3<double> > &X,
573  const std::vector< Vector3<double> > &Y,
574  const std::vector< Matrix3x3<double> > &CovX,
575  const std::vector< Matrix3x3<double> > &CovY,
576  const RMatrix &dR, const std::vector<double> &w)
577 {
578  const unsigned int num = X.size();
579  const bool useCovs = (CovX.size() > 0 || CovY.size() > 0);
580 #ifdef BIAS_DEBUG
581  const bool useWeights = (w.size() > 0);
582 #endif //BIAS_DEBUG
583  BIASASSERT(X.size() == num && Y.size() == num);
584  BIASASSERT(!useCovs || (CovX.size() == num && CovY.size() == num));
585  BIASASSERT(!useWeights || w.size() == num);
586 #ifdef BIAS_DEBUG
587  if (useWeights && useCovs) {
588  BIASERR("Weights and covariances should NOT be used at the same time!");
589  BIASABORT;
590  }
591 #endif
592 
593  // Compute residual errors for all correspondences
594  if (useCovs) {
595  solver_.GetResidualErrors(errors, X, Y, CovX, CovY, dR);
596  } else {
597  solver_.GetResidualErrors(errors, X, Y, dR, w);
598  }
599 
600  // Compute inliers and squared error sum for inliers only
601  inliers.resize(num);
602  errorSum = 0.0;
603  int inlierCount = 0;
604  double error;
605  for (register unsigned int i = 0; i < num; i++) {
606  error = fabs(errors[i]);
607  if (error > maxError_) {
608  inliers[i] = false;
609  } else {
610  inliers[i] = true;
611  inlierCount++;
612  errorSum += error;
613  }
614  }
615  return inlierCount;
616 }
Computes similarity transformation between 3D point sets.
int GetUniformDistributedInt(const int min, const int max)
get uniform distributed random variable including min/max
Definition: Random.cpp:139
BIASMathAlgo_EXPORT double InvChiSquareCulmProbFun(double x, int deg_freedom)
Definition: GSL.cpp:81
3D rotation matrix
Definition: RMatrix.hh:49
double GetResidualErrors(std::vector< double > &errors, const std::vector< Vector3< double > > &X, const std::vector< Vector3< double > > &Y, const RMatrix &dR, const Vector3< double > &dt, const double &ds=1.0, const std::vector< double > &w=std::vector< double >(0))
Computes residual errors of 3D point sets X and Y with respect to given rotation dR, translation dt and isometric scale ds.
double GetResidualErrors(std::vector< double > &errors, const std::vector< Vector3< double > > &X, const std::vector< Vector3< double > > &Y, const RMatrix &dR, const Vector3< double > &dt, const double &ds=1.0, const std::vector< bool > &inliers=std::vector< bool >(0), const std::vector< double > &w=std::vector< double >(0))
Computes residual errors for inliers of 3D point sets X and Y with respect to given rotation dR...
void Reset()
calls srand() with a seed generated from system call time, also initializes some other variables ...
Definition: Random.cpp:113
void SetSignificance(double significance)
Compute max.
int ComputeRotation(const std::vector< Vector3< double > > &X, const std::vector< Vector3< double > > &Y, RMatrix &dR, const std::vector< double > &w=std::vector< double >(0))
Computes rotation dR between corresponding 3D ray sets X and Y using the currently set algorithm...