42 #include <visp3/core/vpDebug.h>
43 #include <visp3/core/vpMatrix.h>
44 #include <visp3/core/vpRobust.h>
45 #include <visp3/vision/vpHomography.h>
48 #include <visp3/core/vpException.h>
49 #include <visp3/core/vpMatrixException.h>
63 :
vpArray2D<double>(3, 3), m_aMb(), m_bP()
69 :
vpArray2D<double>(3, 3), m_aMb(), m_bP()
107 double tx = arb[0], ty = arb[1], tz = arb[2], tux = arb[3], tuy = arb[4], tuz = arb[5];
108 m_aMb.
buildFrom(tx, ty, tz, tux, tuy, tuz);
128 void vpHomography::insert(
const vpPlane &bP) { m_bP = bP; }
135 if (rank !=
nullptr) {
140 unsigned int nbRows = H.
getRows();
141 unsigned int nbCols = H.
getCols();
142 for (
unsigned int i = 0; i < nbRows; ++i) {
143 for (
unsigned int j = 0; j < nbCols; ++j) {
144 H[i][j] = Minv[i][j];
165 const unsigned int nbCols = 3, nbRows = 3;
166 for (
unsigned int i = 0; i < nbRows; ++i) {
167 for (
unsigned int j = 0; j < nbCols; ++j) {
169 for (
unsigned int k = 0; k < nbCols; ++k) {
170 s += (*this)[i][k] * H[k][j];
180 const unsigned int requiredSize = 3;
181 if (b.
size() != requiredSize) {
187 for (
unsigned int i = 0; i < requiredSize; ++i) {
189 for (
unsigned int j = 0; j < requiredSize; ++j) {
190 a[i] += (*this)[i][j] * b[j];
199 const unsigned int nbData = 9;
202 for (
unsigned int i = 0; i < nbData; ++i) {
218 v1[0] = ((*this)[0][0] * v[0]) + ((*
this)[0][1] * v[1]) + ((*
this)[0][2] * v[2]);
219 v1[1] = ((*this)[1][0] * v[0]) + ((*
this)[1][1] * v[1]) + ((*
this)[1][2] * v[2]);
220 v1[2] = ((*this)[2][0] * v[0]) + ((*
this)[2][1] * v[1]) + ((*
this)[2][2] * v[2]);
233 if (std::fabs(v) <= std::numeric_limits<double>::epsilon()) {
239 const unsigned int nbData = 9;
240 for (
unsigned int i = 0; i < nbData; ++i) {
249 if (std::fabs(v) <= std::numeric_limits<double>::epsilon()) {
255 const unsigned int nbData = 9;
256 for (
unsigned int i = 0; i < nbData; ++i) {
265 const unsigned int nbCols = 3, nbRows = 3;
266 for (
unsigned int i = 0; i < nbRows; ++i) {
267 for (
unsigned int j = 0; j < nbCols; ++j) {
268 (*this)[i][j] = H[i][j];
279 const unsigned int nbCols = 3, nbRows = 3;
284 for (
unsigned int i = 0; i < nbRows; ++i) {
285 for (
unsigned int j = 0; j < nbCols; ++j) {
286 (*this)[i][j] = H[i][j];
295 const unsigned int nbCols = 3, nbRows = 3;
297 for (
unsigned int i = 0; i < nbRows; ++i) {
298 for (
unsigned int j = 0; j < nbCols; ++j) {
315 void vpHomography::build()
317 const unsigned int nbCols = 3, nbRows = 3;
321 for (
unsigned int i = 0; i < nbRows; ++i) {
322 atb[i] = m_aMb[i][3];
323 for (
unsigned int j = 0; j < nbCols; ++j) {
324 aRb[i][j] = m_aMb[i][j];
330 double d = m_bP.
getD();
331 vpMatrix aHb = aRb - ((atb * n.
t()) / d);
335 for (
unsigned int i = 0; i < nbRows; ++i) {
336 for (
unsigned int j = 0; j < nbCols; ++j) {
337 (*this)[i][j] = aHb[i][j];
342 #ifndef DOXYGEN_SHOULD_SKIP_THIS
356 const unsigned int nbCols = 3, nbRows = 3;
360 for (
unsigned int i = 0; i < nbRows; ++i) {
362 for (
unsigned int j = 0; j < nbCols; ++j) {
363 aRb[i][j] = aMb[i][j];
369 double d = bP.
getD();
370 vpMatrix aHb_ = aRb - ((atb * n.
t()) / d);
374 for (
unsigned int i = 0; i < nbRows; ++i) {
375 for (
unsigned int j = 0; j < nbCols; ++j) {
376 aHb[i][j] = aHb_[i][j];
384 return ((((*
this)[0][0] * (((*
this)[1][1] * (*
this)[2][2]) - ((*
this)[1][2] * (*
this)[2][1]))) -
385 ((*
this)[0][1] * (((*
this)[1][0] * (*
this)[2][2]) - ((*
this)[1][2] * (*
this)[2][0])))) +
386 ((*
this)[0][2] * (((*
this)[1][0] * (*
this)[2][1]) - ((*
this)[1][1] * (*
this)[2][0]))));
391 const unsigned int nbCols = 3, nbRows = 3;
392 for (
unsigned int i = 0; i < nbRows; ++i) {
393 for (
unsigned int j = 0; j < nbCols; ++j) {
406 double xa = iPa.
get_u();
407 double ya = iPa.
get_v();
409 double z = (xa * bGa[2][0]) + (ya * bGa[2][1]) + bGa[2][2];
410 double xb = ((xa * bGa[0][0]) + (ya * bGa[0][1]) + bGa[0][2]) / z;
411 double yb = ((xa * bGa[1][0]) + (ya * bGa[1][1]) + bGa[1][2]) / z;
420 double xa = Pa.
get_x();
421 double ya = Pa.
get_y();
422 double z = (xa * bHa[2][0]) + (ya * bHa[2][1]) + bHa[2][2];
423 double xb = ((xa * bHa[0][0]) + (ya * bHa[0][1]) + bHa[0][2]) / z;
424 double yb = ((xa * bHa[1][0]) + (ya * bHa[1][1]) + bHa[1][2]) / z;
434 void vpHomography::robust(
const std::vector<double> &xb,
const std::vector<double> &yb,
const std::vector<double> &xa,
435 const std::vector<double> &ya,
vpHomography &aHb, std::vector<bool> &inliers,
436 double &residual,
double weights_threshold,
unsigned int niter,
bool normalization)
438 unsigned int n =
static_cast<unsigned int>(xb.size());
439 if ((yb.size() != n) || (xa.size() != n) || (ya.size() != n)) {
444 const unsigned int nbRequiredPoints = 4;
445 if (n < nbRequiredPoints) {
450 std::vector<double> xan, yan, xbn, ybn;
452 double xg1 = 0., yg1 = 0., coef1 = 0., xg2 = 0., yg2 = 0., coef2 = 0.;
457 vpHomography::hartleyNormalization(xb, yb, xbn, ybn, xg1, yg1, coef1);
458 vpHomography::hartleyNormalization(xa, ya, xan, yan, xg2, yg2, coef2);
467 unsigned int nbLinesA = 2;
471 vpMatrix W(nbLinesA * n, nbLinesA * n, 0);
479 for (
unsigned int i = 0; i < (nbLinesA * n); ++i) {
484 for (
unsigned int i = 0; i < n; ++i) {
485 A[nbLinesA * i][0] = xbn[i];
486 A[nbLinesA * i][1] = ybn[i];
487 A[nbLinesA * i][2] = 1;
488 A[nbLinesA * i][3] = 0;
489 A[nbLinesA * i][4] = 0;
490 A[nbLinesA * i][5] = 0;
491 A[nbLinesA * i][6] = -xbn[i] * xan[i];
492 A[nbLinesA * i][7] = -ybn[i] * xan[i];
494 A[(nbLinesA * i) + 1][0] = 0;
495 A[(nbLinesA * i) + 1][1] = 0;
496 A[(nbLinesA * i) + 1][2] = 0;
497 A[(nbLinesA * i) + 1][3] = xbn[i];
498 A[(nbLinesA * i) + 1][4] = ybn[i];
499 A[(nbLinesA * i) + 1][5] = 1;
500 A[(nbLinesA * i) + 1][6] = -xbn[i] * yan[i];
501 A[(nbLinesA * i) + 1][7] = -ybn[i] * yan[i];
503 Y[nbLinesA * i] = xan[i];
504 Y[(nbLinesA * i) + 1] = yan[i];
509 unsigned int iter = 0;
512 while (iter < niter) {
517 residu = Y - (A * X);
523 for (
unsigned int i = 0; i < (n * nbLinesA); ++i) {
527 for (
unsigned int i = 0; i < 8; ++i) {
535 unsigned int nbinliers = 0;
536 for (
unsigned int i = 0; i < n; ++i) {
537 if ((w[i * 2] < weights_threshold) && (w[(i * 2) + 1] < weights_threshold)) {
548 vpHomography::hartleyDenormalization(aHbn, aHb, xg1, yg1, coef1, xg2, yg2, coef2);
556 for (
unsigned int i = 0; i < n; ++i) {
567 residual += (a - c).sumSquare();
571 residual = sqrt(residual / nbinliers);
581 double u = ipb.
get_u();
582 double v = ipb.
get_v();
584 double u_a = ((*this)[0][0] * u) + ((*
this)[0][1] * v) + (*
this)[0][2];
585 double v_a = ((*this)[1][0] * u) + ((*
this)[1][1] * v) + (*
this)[1][2];
586 double w_a = ((*this)[2][0] * u) + ((*
this)[2][1] * v) + (*
this)[2][2];
588 if (std::fabs(w_a) > std::numeric_limits<double>::epsilon()) {
589 ipa.
set_u(u_a / w_a);
590 ipa.
set_v(v_a / w_a);
598 const unsigned int nbRows = 3, nbCols = 3;
600 for (
unsigned int i = 0; i < nbRows; ++i) {
601 for (
unsigned int j = 0; j < nbCols; ++j) {
602 M[i][j] = (*this)[i][j];
618 double h00 = (*this)[0][0], h01 = (*this)[0][1], h02 = (*this)[0][2];
619 double h10 = (*this)[1][0], h11 = (*this)[1][1], h12 = (*this)[1][2];
620 double h20 = (*this)[2][0], h21 = (*this)[2][1], h22 = (*this)[2][2];
622 double u0_one_over_px = u0 * one_over_px;
623 double v0_one_over_py = v0 * one_over_py;
625 double A = (h00 * one_over_px) - (h20 * u0_one_over_px);
626 double B = (h01 * one_over_px) - (h21 * u0_one_over_px);
627 double C = (h02 * one_over_px) - (h22 * u0_one_over_px);
628 double D = (h10 * one_over_py) - (h20 * v0_one_over_py);
629 double E = (h11 * one_over_py) - (h21 * v0_one_over_py);
630 double F = (h12 * one_over_py) - (h22 * v0_one_over_py);
640 H[0][2] = (A * u0) + (B * v0) + C;
641 H[1][2] = (D * u0) + (E * v0) + F;
642 H[2][2] = (h20 * u0) + (h21 * v0) + h22;
656 double h00 = (*this)[0][0], h01 = (*this)[0][1], h02 = (*this)[0][2];
657 double h10 = (*this)[1][0], h11 = (*this)[1][1], h12 = (*this)[1][2];
658 double h20 = (*this)[2][0], h21 = (*this)[2][1], h22 = (*this)[2][2];
660 double A = (h00 * px) + (u0 * h20);
661 double B = (h01 * px) + (u0 * h21);
662 double C = (h02 * px) + (u0 * h22);
663 double D = (h10 * py) + (v0 * h20);
664 double E = (h11 * py) + (v0 * h21);
665 double F = (h12 * py) + (v0 * h22);
667 H[0][0] = A * one_over_px;
668 H[1][0] = D * one_over_px;
669 H[2][0] = h20 * one_over_px;
671 H[0][1] = B * one_over_py;
672 H[1][1] = E * one_over_py;
673 H[2][1] = h21 * one_over_py;
675 double u0_one_over_px = u0 * one_over_px;
676 double v0_one_over_py = v0 * one_over_py;
678 H[0][2] = ((-A * u0_one_over_px) - (B * v0_one_over_py)) + C;
679 H[1][2] = ((-D * u0_one_over_px) - (E * v0_one_over_py)) + F;
680 H[2][2] = ((-h20 * u0_one_over_px) - (h21 * v0_one_over_py)) + h22;
Implementation of a generic 2D array used as base class for matrices and vectors.
unsigned int getCols() const
Type * data
Address of the first element of the data array.
unsigned int size() const
Return the number of elements of the 2D array.
unsigned int getRows() const
Generic class defining intrinsic camera parameters.
double get_px_inverse() const
double get_py_inverse() const
Implementation of column vector and the associated operations.
error that can be emitted by ViSP classes.
@ dimensionError
Bad dimension.
@ divideByZeroError
Division by zero.
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpHomogeneousMatrix & buildFrom(const vpTranslationVector &t, const vpRotationMatrix &R)
void insert(const vpRotationMatrix &R)
Implementation of an homography and operations on homographies.
vpHomography collineation2homography(const vpCameraParameters &cam) const
vpImagePoint projection(const vpImagePoint &ipb)
vpHomography inverse(double sv_threshold=1e-16, unsigned int *rank=nullptr) const
vpHomography & operator/=(double v)
void save(std::ofstream &f) const
vpHomography operator*(const vpHomography &H) const
vpHomography operator/(const double &v) const
vpHomography & operator=(const vpHomography &H)
vpHomography homography2collineation(const vpCameraParameters &cam) const
static vpImagePoint project(const vpCameraParameters &cam, const vpHomography &bHa, const vpImagePoint &iPa)
void load(std::ifstream &f)
static void robust(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, double weights_threshold=0.4, unsigned int niter=4, bool normalization=true)
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true)
vpHomography & buildFrom(const vpRotationMatrix &aRb, const vpTranslationVector &atb, const vpPlane &bP)
Construction from translation and rotation and a plane.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
error that can be emitted by the vpMatrix class and its derivatives
Implementation of a matrix and operations on matrices.
vpMatrix pseudoInverse(double svThreshold=1e-6) const
This class defines the container for a plane geometrical structure.
vpColVector getNormal() const
Class that defines a 3D point in the object frame and allows forward projection of a 3D point in the ...
double get_w() const
Get the point w coordinate in the image plane.
void set_x(double x)
Set the point x coordinate in the image plane.
double get_y() const
Get the point y coordinate in the image plane.
double get_x() const
Get the point x coordinate in the image plane.
void set_y(double y)
Set the point y coordinate in the image plane.
void set_w(double w)
Set the point w coordinate in the image plane.
Implementation of a pose vector and operations on poses.
Contains an M-estimator and various influence function.
@ TUKEY
Tukey influence function.
void MEstimator(const vpRobustEstimatorType method, const vpColVector &residues, vpColVector &weights)
Implementation of a rotation matrix and operations on such kind of matrices.
Implementation of a rotation vector as axis-angle minimal representation.
Class that consider the case of a translation vector.