34 #include <visp3/core/vpColVector.h>
35 #include <visp3/core/vpRansac.h>
36 #include <visp3/vision/vpHomography.h>
38 #include <visp3/core/vpDisplay.h>
39 #include <visp3/core/vpImage.h>
40 #include <visp3/core/vpMeterPixelConversion.h>
49 #ifndef DOXYGEN_SHOULD_SKIP_THIS
51 bool iscolinear(
double *x1,
double *x2,
double *x3);
54 bool iscolinear(
double *x1,
double *x2,
double *x3)
69 bool vpHomography::degenerateConfiguration(
const vpColVector &x,
unsigned int *ind,
double threshold_area)
74 for (i = 1; i < 4; ++i) {
75 for (j = 0; j < i; ++j) {
76 if (ind[i] == ind[j]) {
82 unsigned int n = x.
getRows() / 4;
86 for (i = 0; i < 4; ++i) {
87 pb[i][0] = x[2 * ind[i]];
88 pb[i][1] = x[(2 * ind[i]) + 1];
91 pa[i][0] = x[(2 * n) + (2 * ind[i])];
92 pa[i][1] = x[(2 * n) + (2 * ind[i]) + 1];
98 double area012 = ((((((-pa[j][0] * pa[i][1]) + (pa[k][0] * pa[i][1])) + (pa[i][0] * pa[j][1])) - (pa[k][0] * pa[j][1])) +
99 (-pa[i][0] * pa[k][1])) + (pa[1][j] * pa[k][1]));
103 double area013 = ((((((-pa[j][0] * pa[i][1]) + (pa[k][0] * pa[i][1])) + (pa[i][0] * pa[j][1])) - (pa[k][0] * pa[j][1])) +
104 (-pa[i][0] * pa[k][1])) + (pa[1][j] * pa[k][1]));
108 double area023 = ((((((-pa[j][0] * pa[i][1]) + (pa[k][0] * pa[i][1])) + (pa[i][0] * pa[j][1])) - (pa[k][0] * pa[j][1])) +
109 (-pa[i][0] * pa[k][1])) + (pa[1][j] * pa[k][1]));
113 double area123 = ((((((-pa[j][0] * pa[i][1]) + (pa[k][0] * pa[i][1])) + (pa[i][0] * pa[j][1])) - (pa[k][0] * pa[j][1])) +
114 (-pa[i][0] * pa[k][1])) + (pa[1][j] * pa[k][1]));
116 double sum_area = area012 + area013 + area023 + area123;
118 if (sum_area < threshold_area) {
121 else if (iscolinear(pa[0], pa[1], pa[2])) {
124 else if (iscolinear(pa[0], pa[1], pa[3])) {
127 else if (iscolinear(pa[0], pa[2], pa[3])) {
130 else if (iscolinear(pa[1], pa[2], pa[3])) {
133 else if (iscolinear(pb[0], pb[1], pb[2])) {
136 else if (iscolinear(pb[0], pb[1], pb[3])) {
139 else if (iscolinear(pb[0], pb[2], pb[3])) {
142 else if (iscolinear(pb[1], pb[2], pb[3])) {
162 bool vpHomography::degenerateConfiguration(
const vpColVector &x,
unsigned int *ind)
164 for (
unsigned int i = 1; i < 4; ++i) {
165 for (
unsigned int j = 0; j < i; ++j) {
166 if (ind[i] == ind[j]) {
172 unsigned int n = x.
getRows() / 4;
175 unsigned int n2 = 2 * n;
176 for (
unsigned int i = 0; i < 4; ++i) {
177 unsigned int ind2 = 2 * ind[i];
179 pb[i][1] = x[ind2 + 1];
182 pa[i][0] = x[n2 + ind2];
183 pa[i][1] = x[n2 + ind2 + 1];
187 if (iscolinear(pa[0], pa[1], pa[2])) {
190 else if (iscolinear(pa[0], pa[1], pa[3])) {
193 else if (iscolinear(pa[0], pa[2], pa[3])) {
196 else if (iscolinear(pa[1], pa[2], pa[3])) {
199 else if (iscolinear(pb[0], pb[1], pb[2])) {
202 else if (iscolinear(pb[0], pb[1], pb[3])) {
205 else if (iscolinear(pb[0], pb[2], pb[3])) {
208 else if (iscolinear(pb[1], pb[2], pb[3])) {
216 bool vpHomography::degenerateConfiguration(
const std::vector<double> &xb,
const std::vector<double> &yb,
217 const std::vector<double> &xa,
const std::vector<double> &ya)
219 unsigned int n =
static_cast<unsigned int>(xb.size());
224 std::vector<vpColVector> pa(n), pb(n);
225 for (
unsigned i = 0; i < n; ++i) {
236 for (
unsigned int i = 0; i < (n - 2); ++i) {
237 for (
unsigned int j = i + 1; j < (n - 1); ++j) {
238 for (
unsigned int k = j + 1; k < n; ++k) {
239 if (isColinear(pa[i], pa[j], pa[k])) {
242 if (isColinear(pb[i], pb[j], pb[k])) {
253 unsigned int n = x.
getRows() / 4;
254 std::vector<double> xa(4), xb(4);
255 std::vector<double> ya(4), yb(4);
256 unsigned int n2 = n * 2;
257 for (
unsigned int i = 0; i < 4; ++i) {
258 unsigned int ind2 = 2 * ind[i];
262 xa[i] = x[n2 + ind2];
263 ya[i] = x[n2 + ind2 + 1];
275 for (
unsigned int i = 0; i < 9; ++i) {
284 unsigned int n = x.
getRows() / 4;
285 unsigned int n2 = n * 2;
292 for (
unsigned int i = 0; i < n; ++i) {
293 unsigned int i2 = 2 * i;
296 pb[i][1] = x[i2 + 1];
300 pa[i][0] = x[n2 + i2];
301 pa[i][1] = x[n2 + i2 + 1];
307 for (
unsigned int i = 0; i < 9; ++i) {
316 for (
unsigned int i = 0; i < n; ++i) {
319 d[i] = sqrt((pa[i] - Hpb).sumSquare());
329 void vpHomography::initRansac(
unsigned int n,
double *xb,
double *yb,
double *xa,
double *ya,
vpColVector &x)
332 unsigned int n2 = n * 2;
333 for (
unsigned int i = 0; i < n; ++i) {
334 unsigned int i2 = 2 * i;
338 x[n2 + i2 + 1] = ya[i];
342 bool vpHomography::ransac(
const std::vector<double> &xb,
const std::vector<double> &yb,
const std::vector<double> &xa,
343 const std::vector<double> &ya,
vpHomography &aHb, std::vector<bool> &inliers,
344 double &residual,
unsigned int nbInliersConsensus,
double threshold,
bool normalization)
346 unsigned int n =
static_cast<unsigned int>(xb.size());
347 if ((yb.size() != n) || (xa.size() != n) || (ya.size() != n)) {
356 vpUniRand random(
static_cast<long>(time(
nullptr)));
358 std::vector<unsigned int> best_consensus;
359 std::vector<unsigned int> cur_consensus;
360 std::vector<unsigned int> cur_outliers;
361 std::vector<unsigned int> cur_randoms;
363 std::vector<unsigned int> rand_ind;
365 unsigned int nbMinRandom = 4;
366 unsigned int ransacMaxTrials = 1000;
367 unsigned int maxDegenerateIter = 1000;
369 unsigned int nbTrials = 0;
370 unsigned int nbDegenerateIter = 0;
371 unsigned int nbInliers = 0;
373 bool foundSolution =
false;
375 std::vector<double> xa_rand(nbMinRandom);
376 std::vector<double> ya_rand(nbMinRandom);
377 std::vector<double> xb_rand(nbMinRandom);
378 std::vector<double> yb_rand(nbMinRandom);
380 if (inliers.size() != n) {
384 while ((nbTrials < ransacMaxTrials) && (nbInliers < nbInliersConsensus)) {
385 cur_outliers.clear();
388 bool degenerate =
true;
389 while (degenerate ==
true) {
390 std::vector<bool> usedPt(n,
false);
393 for (
unsigned int i = 0; i < nbMinRandom; ++i) {
395 unsigned int r =
static_cast<unsigned int>(ceil(random() * n)) - 1;
397 r =
static_cast<unsigned int>(ceil(random() * n)) - 1;
400 rand_ind.push_back(r);
409 if (!vpHomography::degenerateConfiguration(xb_rand, yb_rand, xa_rand, ya_rand)) {
420 if (nbDegenerateIter > maxDegenerateIter) {
431 for (
unsigned int i = 0; i < nbMinRandom; ++i) {
441 r += (a - c).sumSquare();
445 r = sqrt(r / nbMinRandom);
447 unsigned int nbInliersCur = 0;
448 for (
unsigned int i = 0; i < n; ++i) {
458 double error = sqrt((a - c).sumSquare());
459 if (error <= threshold) {
461 cur_consensus.push_back(i);
465 cur_outliers.push_back(i);
470 if (nbInliersCur > nbInliers) {
471 foundSolution =
true;
472 best_consensus = cur_consensus;
473 nbInliers = nbInliersCur;
476 cur_consensus.clear();
480 if (nbTrials >= ransacMaxTrials) {
481 vpERROR_TRACE(
"Ransac reached the maximum number of trials");
482 foundSolution =
true;
487 if (nbInliers >= nbInliersConsensus) {
488 const unsigned int nbConsensus =
static_cast<unsigned int>(best_consensus.size());
489 std::vector<double> xa_best(nbConsensus);
490 std::vector<double> ya_best(nbConsensus);
491 std::vector<double> xb_best(nbConsensus);
492 std::vector<double> yb_best(nbConsensus);
494 for (
unsigned i = 0; i < nbConsensus; ++i) {
495 xa_best[i] = xa[best_consensus[i]];
496 ya_best[i] = ya[best_consensus[i]];
497 xb_best[i] = xb[best_consensus[i]];
498 yb_best[i] = yb[best_consensus[i]];
507 for (
unsigned int i = 0; i < nbConsensus; ++i) {
517 residual += (a - c).sumSquare();
520 residual = sqrt(residual / nbConsensus);
Type * data
Address of the first element of the data array.
unsigned int getRows() const
Implementation of column vector and the associated operations.
static vpColVector cross(const vpColVector &a, const vpColVector &b)
void resize(unsigned int i, bool flagNullify=true)
error that can be emitted by ViSP classes.
@ dimensionError
Bad dimension.
Implementation of an homography and operations on homographies.
static void DLT(const std::vector< double > &xb, const std::vector< double > &yb, const std::vector< double > &xa, const std::vector< double > &ya, vpHomography &aHb, bool normalization=true)
static void HLM(const std::vector< double > &xb, const std::vector< double > &yb, const std::vector< double > &xa, const std::vector< double > &ya, bool isplanar, vpHomography &aHb)
static bool ransac(const std::vector< double > &xb, const std::vector< double > &yb, const std::vector< double > &xa, const std::vector< double > &ya, vpHomography &aHb, std::vector< bool > &inliers, double &residual, unsigned int nbInliersConsensus, double threshold, bool normalization=true)
Implementation of a matrix and operations on matrices.
Class for generating random numbers with uniform probability density.