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>
61 :
vpArray2D<double>(3, 3), m_aMb(), m_bP()
67 :
vpArray2D<double>(3, 3), m_aMb(), m_bP()
102 double tx = arb[0], ty = arb[1], tz = arb[2], tux = arb[3], tuy = arb[4], tuz = arb[5];
103 m_aMb.
buildFrom(tx, ty, tz, tux, tuy, tuz);
122 void vpHomography::insert(
const vpPlane &bP) { m_bP = bP; }
129 if (rank !=
nullptr) {
134 unsigned int nbRows = H.
getRows();
135 unsigned int nbCols = H.
getCols();
136 for (
unsigned int i = 0; i < nbRows; ++i) {
137 for (
unsigned int j = 0; j < nbCols; ++j) {
138 H[i][j] = Minv[i][j];
159 const unsigned int nbCols = 3, nbRows = 3;
160 for (
unsigned int i = 0; i < nbRows; ++i) {
161 for (
unsigned int j = 0; j < nbCols; ++j) {
163 for (
unsigned int k = 0; k < nbCols; ++k) {
164 s += (*this)[i][k] * H[k][j];
174 const unsigned int requiredSize = 3;
175 if (b.
size() != requiredSize) {
181 for (
unsigned int i = 0; i < requiredSize; ++i) {
183 for (
unsigned int j = 0; j < requiredSize; ++j) {
184 a[i] += (*this)[i][j] * b[j];
193 const unsigned int nbData = 9;
196 for (
unsigned int i = 0; i < nbData; ++i) {
212 v1[0] = ((*this)[0][0] * v[0]) + ((*
this)[0][1] * v[1]) + ((*
this)[0][2] * v[2]);
213 v1[1] = ((*this)[1][0] * v[0]) + ((*
this)[1][1] * v[1]) + ((*
this)[1][2] * v[2]);
214 v1[2] = ((*this)[2][0] * v[0]) + ((*
this)[2][1] * v[1]) + ((*
this)[2][2] * v[2]);
227 if (std::fabs(v) <= std::numeric_limits<double>::epsilon()) {
233 const unsigned int nbData = 9;
234 for (
unsigned int i = 0; i < nbData; ++i) {
243 if (std::fabs(v) <= std::numeric_limits<double>::epsilon()) {
249 const unsigned int nbData = 9;
250 for (
unsigned int i = 0; i < nbData; ++i) {
259 const unsigned int nbCols = 3, nbRows = 3;
260 for (
unsigned int i = 0; i < nbRows; ++i) {
261 for (
unsigned int j = 0; j < nbCols; ++j) {
262 (*this)[i][j] = H[i][j];
273 const unsigned int nbCols = 3, nbRows = 3;
278 for (
unsigned int i = 0; i < nbRows; ++i) {
279 for (
unsigned int j = 0; j < nbCols; ++j) {
280 (*this)[i][j] = H[i][j];
289 const unsigned int nbCols = 3, nbRows = 3;
291 for (
unsigned int i = 0; i < nbRows; ++i) {
292 for (
unsigned int j = 0; j < nbCols; ++j) {
309 void vpHomography::build()
311 const unsigned int nbCols = 3, nbRows = 3;
315 for (
unsigned int i = 0; i < nbRows; ++i) {
316 atb[i] = m_aMb[i][3];
317 for (
unsigned int j = 0; j < nbCols; ++j) {
318 aRb[i][j] = m_aMb[i][j];
324 double d = m_bP.
getD();
325 vpMatrix aHb = aRb - ((atb * n.
t()) / d);
329 for (
unsigned int i = 0; i < nbRows; ++i) {
330 for (
unsigned int j = 0; j < nbCols; ++j) {
331 (*this)[i][j] = aHb[i][j];
346 const unsigned int nbCols = 3, nbRows = 3;
350 for (
unsigned int i = 0; i < nbRows; ++i) {
352 for (
unsigned int j = 0; j < nbCols; ++j) {
353 aRb[i][j] = aMb[i][j];
359 double d = bP.
getD();
360 vpMatrix aHb_ = aRb - ((atb * n.
t()) / d);
364 for (
unsigned int i = 0; i < nbRows; ++i) {
365 for (
unsigned int j = 0; j < nbCols; ++j) {
366 aHb[i][j] = aHb_[i][j];
373 return ((((*
this)[0][0] * (((*
this)[1][1] * (*
this)[2][2]) - ((*
this)[1][2] * (*
this)[2][1]))) -
374 ((*
this)[0][1] * (((*
this)[1][0] * (*
this)[2][2]) - ((*
this)[1][2] * (*
this)[2][0])))) +
375 ((*
this)[0][2] * (((*
this)[1][0] * (*
this)[2][1]) - ((*
this)[1][1] * (*
this)[2][0]))));
380 const unsigned int nbCols = 3, nbRows = 3;
381 for (
unsigned int i = 0; i < nbRows; ++i) {
382 for (
unsigned int j = 0; j < nbCols; ++j) {
395 double xa = iPa.
get_u();
396 double ya = iPa.
get_v();
398 double z = (xa * bGa[2][0]) + (ya * bGa[2][1]) + bGa[2][2];
399 double xb = ((xa * bGa[0][0]) + (ya * bGa[0][1]) + bGa[0][2]) / z;
400 double yb = ((xa * bGa[1][0]) + (ya * bGa[1][1]) + bGa[1][2]) / z;
409 double xa = Pa.
get_x();
410 double ya = Pa.
get_y();
411 double z = (xa * bHa[2][0]) + (ya * bHa[2][1]) + bHa[2][2];
412 double xb = ((xa * bHa[0][0]) + (ya * bHa[0][1]) + bHa[0][2]) / z;
413 double yb = ((xa * bHa[1][0]) + (ya * bHa[1][1]) + bHa[1][2]) / z;
423 void vpHomography::robust(
const std::vector<double> &xb,
const std::vector<double> &yb,
const std::vector<double> &xa,
424 const std::vector<double> &ya,
vpHomography &aHb, std::vector<bool> &inliers,
425 double &residual,
double weights_threshold,
unsigned int niter,
bool normalization)
427 unsigned int n =
static_cast<unsigned int>(xb.size());
428 if ((yb.size() != n) || (xa.size() != n) || (ya.size() != n)) {
433 const unsigned int nbRequiredPoints = 4;
434 if (n < nbRequiredPoints) {
439 std::vector<double> xan, yan, xbn, ybn;
441 double xg1 = 0., yg1 = 0., coef1 = 0., xg2 = 0., yg2 = 0., coef2 = 0.;
446 vpHomography::hartleyNormalization(xb, yb, xbn, ybn, xg1, yg1, coef1);
447 vpHomography::hartleyNormalization(xa, ya, xan, yan, xg2, yg2, coef2);
456 unsigned int nbLinesA = 2;
460 vpMatrix W(nbLinesA * n, nbLinesA * n, 0);
468 for (
unsigned int i = 0; i < (nbLinesA * n); ++i) {
473 for (
unsigned int i = 0; i < n; ++i) {
474 A[nbLinesA * i][0] = xbn[i];
475 A[nbLinesA * i][1] = ybn[i];
476 A[nbLinesA * i][2] = 1;
477 A[nbLinesA * i][3] = 0;
478 A[nbLinesA * i][4] = 0;
479 A[nbLinesA * i][5] = 0;
480 A[nbLinesA * i][6] = -xbn[i] * xan[i];
481 A[nbLinesA * i][7] = -ybn[i] * xan[i];
483 A[(nbLinesA * i) + 1][0] = 0;
484 A[(nbLinesA * i) + 1][1] = 0;
485 A[(nbLinesA * i) + 1][2] = 0;
486 A[(nbLinesA * i) + 1][3] = xbn[i];
487 A[(nbLinesA * i) + 1][4] = ybn[i];
488 A[(nbLinesA * i) + 1][5] = 1;
489 A[(nbLinesA * i) + 1][6] = -xbn[i] * yan[i];
490 A[(nbLinesA * i) + 1][7] = -ybn[i] * yan[i];
492 Y[nbLinesA * i] = xan[i];
493 Y[(nbLinesA * i) + 1] = yan[i];
498 unsigned int iter = 0;
501 while (iter < niter) {
506 residu = Y - (A * X);
512 for (
unsigned int i = 0; i < (n * nbLinesA); ++i) {
516 for (
unsigned int i = 0; i < 8; ++i) {
524 unsigned int nbinliers = 0;
525 for (
unsigned int i = 0; i < n; ++i) {
526 if ((w[i * 2] < weights_threshold) && (w[(i * 2) + 1] < weights_threshold)) {
537 vpHomography::hartleyDenormalization(aHbn, aHb, xg1, yg1, coef1, xg2, yg2, coef2);
545 for (
unsigned int i = 0; i < n; ++i) {
556 residual += (a - c).sumSquare();
560 residual = sqrt(residual / nbinliers);
570 double u = ipb.
get_u();
571 double v = ipb.
get_v();
573 double u_a = ((*this)[0][0] * u) + ((*
this)[0][1] * v) + (*
this)[0][2];
574 double v_a = ((*this)[1][0] * u) + ((*
this)[1][1] * v) + (*
this)[1][2];
575 double w_a = ((*this)[2][0] * u) + ((*
this)[2][1] * v) + (*
this)[2][2];
577 if (std::fabs(w_a) > std::numeric_limits<double>::epsilon()) {
578 ipa.
set_u(u_a / w_a);
579 ipa.
set_v(v_a / w_a);
587 const unsigned int nbRows = 3, nbCols = 3;
589 for (
unsigned int i = 0; i < nbRows; ++i) {
590 for (
unsigned int j = 0; j < nbCols; ++j) {
591 M[i][j] = (*this)[i][j];
607 double h00 = (*this)[0][0], h01 = (*this)[0][1], h02 = (*this)[0][2];
608 double h10 = (*this)[1][0], h11 = (*this)[1][1], h12 = (*this)[1][2];
609 double h20 = (*this)[2][0], h21 = (*this)[2][1], h22 = (*this)[2][2];
611 double u0_one_over_px = u0 * one_over_px;
612 double v0_one_over_py = v0 * one_over_py;
614 double A = (h00 * one_over_px) - (h20 * u0_one_over_px);
615 double B = (h01 * one_over_px) - (h21 * u0_one_over_px);
616 double C = (h02 * one_over_px) - (h22 * u0_one_over_px);
617 double D = (h10 * one_over_py) - (h20 * v0_one_over_py);
618 double E = (h11 * one_over_py) - (h21 * v0_one_over_py);
619 double F = (h12 * one_over_py) - (h22 * v0_one_over_py);
629 H[0][2] = (A * u0) + (B * v0) + C;
630 H[1][2] = (D * u0) + (E * v0) + F;
631 H[2][2] = (h20 * u0) + (h21 * v0) + h22;
645 double h00 = (*this)[0][0], h01 = (*this)[0][1], h02 = (*this)[0][2];
646 double h10 = (*this)[1][0], h11 = (*this)[1][1], h12 = (*this)[1][2];
647 double h20 = (*this)[2][0], h21 = (*this)[2][1], h22 = (*this)[2][2];
649 double A = (h00 * px) + (u0 * h20);
650 double B = (h01 * px) + (u0 * h21);
651 double C = (h02 * px) + (u0 * h22);
652 double D = (h10 * py) + (v0 * h20);
653 double E = (h11 * py) + (v0 * h21);
654 double F = (h12 * py) + (v0 * h22);
656 H[0][0] = A * one_over_px;
657 H[1][0] = D * one_over_px;
658 H[2][0] = h20 * one_over_px;
660 H[0][1] = B * one_over_py;
661 H[1][1] = E * one_over_py;
662 H[2][1] = h21 * one_over_py;
664 double u0_one_over_px = u0 * one_over_px;
665 double v0_one_over_py = v0 * one_over_py;
667 H[0][2] = ((-A * u0_one_over_px) - (B * v0_one_over_py)) + C;
668 H[1][2] = ((-D * u0_one_over_px) - (E * v0_one_over_py)) + F;
669 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.
void 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
void buildFrom(const vpRotationMatrix &aRb, const vpTranslationVector &atb, const vpPlane &bP)
Construction from translation and rotation and a plane.
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)
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.