34 #include <visp3/core/vpDebug.h>
35 #include <visp3/core/vpColVector.h>
36 #include <visp3/core/vpRansac.h>
37 #include <visp3/vision/vpHomography.h>
39 #include <visp3/core/vpDisplay.h>
40 #include <visp3/core/vpImage.h>
41 #include <visp3/core/vpMeterPixelConversion.h>
52 #ifndef DOXYGEN_SHOULD_SKIP_THIS
54 bool iscolinear(
double *x1,
double *x2,
double *x3);
57 bool iscolinear(
double *x1,
double *x2,
double *x3)
72 bool vpHomography::degenerateConfiguration(
const vpColVector &x,
unsigned int *ind,
double threshold_area)
77 for (i = 1; i < 4; ++i) {
78 for (j = 0; j < i; ++j) {
79 if (ind[i] == ind[j]) {
85 unsigned int n = x.
getRows() / 4;
89 for (i = 0; i < 4; ++i) {
90 pb[i][0] = x[2 * ind[i]];
91 pb[i][1] = x[(2 * ind[i]) + 1];
94 pa[i][0] = x[(2 * n) + (2 * ind[i])];
95 pa[i][1] = x[(2 * n) + (2 * ind[i]) + 1];
101 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])) +
102 (-pa[i][0] * pa[k][1])) + (pa[1][j] * pa[k][1]));
106 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])) +
107 (-pa[i][0] * pa[k][1])) + (pa[1][j] * pa[k][1]));
111 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])) +
112 (-pa[i][0] * pa[k][1])) + (pa[1][j] * pa[k][1]));
116 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])) +
117 (-pa[i][0] * pa[k][1])) + (pa[1][j] * pa[k][1]));
119 double sum_area = area012 + area013 + area023 + area123;
121 if (sum_area < threshold_area) {
124 else if (iscolinear(pa[0], pa[1], pa[2])) {
127 else if (iscolinear(pa[0], pa[1], pa[3])) {
130 else if (iscolinear(pa[0], pa[2], pa[3])) {
133 else if (iscolinear(pa[1], pa[2], pa[3])) {
136 else if (iscolinear(pb[0], pb[1], pb[2])) {
139 else if (iscolinear(pb[0], pb[1], pb[3])) {
142 else if (iscolinear(pb[0], pb[2], pb[3])) {
145 else if (iscolinear(pb[1], pb[2], pb[3])) {
165 bool vpHomography::degenerateConfiguration(
const vpColVector &x,
unsigned int *ind)
167 for (
unsigned int i = 1; i < 4; ++i) {
168 for (
unsigned int j = 0; j < i; ++j) {
169 if (ind[i] == ind[j]) {
175 const unsigned int val_4 = 4;
176 unsigned int n = x.
getRows() / val_4;
179 unsigned int n2 = 2 * n;
180 for (
unsigned int i = 0; i < val_4; ++i) {
181 unsigned int ind2 = 2 * ind[i];
183 pb[i][1] = x[ind2 + 1];
186 pa[i][0] = x[n2 + ind2];
187 pa[i][1] = x[n2 + ind2 + 1];
191 if (iscolinear(pa[0], pa[1], pa[2])) {
194 else if (iscolinear(pa[0], pa[1], pa[3])) {
197 else if (iscolinear(pa[0], pa[2], pa[3])) {
200 else if (iscolinear(pa[1], pa[2], pa[3])) {
203 else if (iscolinear(pb[0], pb[1], pb[2])) {
206 else if (iscolinear(pb[0], pb[1], pb[3])) {
209 else if (iscolinear(pb[0], pb[2], pb[3])) {
212 else if (iscolinear(pb[1], pb[2], pb[3])) {
220 bool vpHomography::degenerateConfiguration(
const std::vector<double> &xb,
const std::vector<double> &yb,
221 const std::vector<double> &xa,
const std::vector<double> &ya)
223 unsigned int n =
static_cast<unsigned int>(xb.size());
228 std::vector<vpColVector> pa(n), pb(n);
229 for (
unsigned i = 0; i < n; ++i) {
240 for (
unsigned int i = 0; i < (n - 2); ++i) {
241 for (
unsigned int j = i + 1; j < (n - 1); ++j) {
242 for (
unsigned int k = j + 1; k < n; ++k) {
243 if (isColinear(pa[i], pa[j], pa[k])) {
246 if (isColinear(pb[i], pb[j], pb[k])) {
257 const unsigned int val_4 = 4;
258 unsigned int n = x.
getRows() / val_4;
259 std::vector<double> xa(4), xb(4);
260 std::vector<double> ya(4), yb(4);
261 unsigned int n2 = n * 2;
262 for (
unsigned int i = 0; i < val_4; ++i) {
263 unsigned int ind2 = 2 * ind[i];
267 xa[i] = x[n2 + ind2];
268 ya[i] = x[n2 + ind2 + 1];
280 for (
unsigned int i = 0; i < 9; ++i) {
289 unsigned int n = x.
getRows() / 4;
290 unsigned int n2 = n * 2;
297 for (
unsigned int i = 0; i < n; ++i) {
298 unsigned int i2 = 2 * i;
301 pb[i][1] = x[i2 + 1];
305 pa[i][0] = x[n2 + i2];
306 pa[i][1] = x[n2 + i2 + 1];
312 for (
unsigned int i = 0; i < 9; ++i) {
321 for (
unsigned int i = 0; i < n; ++i) {
324 d[i] = sqrt((pa[i] - Hpb).sumSquare());
334 void vpHomography::initRansac(
unsigned int n,
double *xb,
double *yb,
double *xa,
double *ya,
vpColVector &x)
337 unsigned int n2 = n * 2;
338 for (
unsigned int i = 0; i < n; ++i) {
339 unsigned int i2 = 2 * i;
343 x[n2 + i2 + 1] = ya[i];
347 bool vpHomography::ransac(
const std::vector<double> &xb,
const std::vector<double> &yb,
const std::vector<double> &xa,
348 const std::vector<double> &ya,
vpHomography &aHb, std::vector<bool> &inliers,
349 double &residual,
unsigned int nbInliersConsensus,
double threshold,
bool normalization)
351 unsigned int n =
static_cast<unsigned int>(xb.size());
352 if ((yb.size() != n) || (xa.size() != n) || (ya.size() != n)) {
361 vpUniRand random(
static_cast<long>(time(
nullptr)));
363 std::vector<unsigned int> best_consensus;
364 std::vector<unsigned int> cur_consensus;
365 std::vector<unsigned int> cur_outliers;
366 std::vector<unsigned int> cur_randoms;
368 std::vector<unsigned int> rand_ind;
370 unsigned int nbMinRandom = 4;
371 unsigned int ransacMaxTrials = 1000;
372 unsigned int maxDegenerateIter = 1000;
374 unsigned int nbTrials = 0;
375 unsigned int nbDegenerateIter = 0;
376 unsigned int nbInliers = 0;
378 bool foundSolution =
false;
380 std::vector<double> xa_rand(nbMinRandom);
381 std::vector<double> ya_rand(nbMinRandom);
382 std::vector<double> xb_rand(nbMinRandom);
383 std::vector<double> yb_rand(nbMinRandom);
385 if (inliers.size() != n) {
389 while ((nbTrials < ransacMaxTrials) && (nbInliers < nbInliersConsensus)) {
390 cur_outliers.clear();
393 bool degenerate =
true;
394 while (degenerate ==
true) {
395 std::vector<bool> usedPt(n,
false);
398 for (
unsigned int i = 0; i < nbMinRandom; ++i) {
400 unsigned int r =
static_cast<unsigned int>(ceil(random() * n)) - 1;
402 r =
static_cast<unsigned int>(ceil(random() * n)) - 1;
405 rand_ind.push_back(r);
414 if (!vpHomography::degenerateConfiguration(xb_rand, yb_rand, xa_rand, ya_rand)) {
425 if (nbDegenerateIter > maxDegenerateIter) {
426 vpERROR_TRACE(
"Unable to select a nondegenerate data set");
436 for (
unsigned int i = 0; i < nbMinRandom; ++i) {
446 r += (a - c).sumSquare();
450 r = sqrt(r / nbMinRandom);
452 unsigned int nbInliersCur = 0;
453 for (
unsigned int i = 0; i < n; ++i) {
463 double error = sqrt((a - c).sumSquare());
464 if (error <= threshold) {
466 cur_consensus.push_back(i);
470 cur_outliers.push_back(i);
475 if (nbInliersCur > nbInliers) {
476 foundSolution =
true;
477 best_consensus = cur_consensus;
478 nbInliers = nbInliersCur;
481 cur_consensus.clear();
485 if (nbTrials >= ransacMaxTrials) {
486 vpERROR_TRACE(
"Ransac reached the maximum number of trials");
487 foundSolution =
true;
492 if (nbInliers >= nbInliersConsensus) {
493 const unsigned int nbConsensus =
static_cast<unsigned int>(best_consensus.size());
494 std::vector<double> xa_best(nbConsensus);
495 std::vector<double> ya_best(nbConsensus);
496 std::vector<double> xb_best(nbConsensus);
497 std::vector<double> yb_best(nbConsensus);
499 for (
unsigned i = 0; i < nbConsensus; ++i) {
500 xa_best[i] = xa[best_consensus[i]];
501 ya_best[i] = ya[best_consensus[i]];
502 xb_best[i] = xb[best_consensus[i]];
503 yb_best[i] = yb[best_consensus[i]];
512 for (
unsigned int i = 0; i < nbConsensus; ++i) {
522 residual += (a - c).sumSquare();
525 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.