Visual Servoing Platform  version 3.6.1 under development (2024-02-13)
vpHomography.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Homography transformation.
32  */
33 
40 #include <stdio.h>
41 
42 #include <visp3/core/vpDebug.h>
43 #include <visp3/core/vpMatrix.h>
44 #include <visp3/core/vpRobust.h>
45 #include <visp3/vision/vpHomography.h>
46 
47 // Exception
48 #include <visp3/core/vpException.h>
49 #include <visp3/core/vpMatrixException.h>
50 
51 vpHomography::vpHomography() : vpArray2D<double>(3, 3), m_aMb(), m_bP() { eye(); }
52 
53 vpHomography::vpHomography(const vpHomography &H) : vpArray2D<double>(3, 3), m_aMb(), m_bP() { *this = H; }
54 
55 vpHomography::vpHomography(const vpHomogeneousMatrix &aMb, const vpPlane &bP) : vpArray2D<double>(3, 3), m_aMb(), m_bP()
56 {
57  buildFrom(aMb, bP);
58 }
59 
61  : vpArray2D<double>(3, 3), m_aMb(), m_bP()
62 {
63  buildFrom(tu, atb, p);
64 }
65 
67  : vpArray2D<double>(3, 3), m_aMb(), m_bP()
68 {
69  buildFrom(aRb, atb, p);
70 }
71 
72 vpHomography::vpHomography(const vpPoseVector &arb, const vpPlane &p) : vpArray2D<double>(3, 3), m_aMb(), m_bP()
73 {
74  buildFrom(arb, p);
75 }
76 
78 {
79  insert(aMb);
80  insert(bP);
81  build();
82 }
83 
85 {
86  insert(tu);
87  insert(atb);
88  insert(p);
89  build();
90 }
91 
93 {
94  insert(aRb);
95  insert(atb);
96  insert(p);
97  build();
98 }
99 
100 void vpHomography::buildFrom(const vpPoseVector &arb, const vpPlane &p)
101 {
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);
104  insert(p);
105  build();
106 }
107 
108 /*********************************************************************/
109 
110 void vpHomography::insert(const vpRotationMatrix &aRb) { m_aMb.insert(aRb); }
111 
112 void vpHomography::insert(const vpHomogeneousMatrix &M) { m_aMb = M; }
113 
114 void vpHomography::insert(const vpThetaUVector &tu)
115 {
116  vpRotationMatrix aRb(tu);
117  m_aMb.insert(aRb);
118 }
119 
120 void vpHomography::insert(const vpTranslationVector &atb) { m_aMb.insert(atb); }
121 
122 void vpHomography::insert(const vpPlane &bP) { m_bP = bP; }
123 
124 vpHomography vpHomography::inverse(double sv_threshold, unsigned int *rank) const
125 {
126  vpMatrix M = (*this).convert();
127  vpMatrix Minv;
128  unsigned int r = M.pseudoInverse(Minv, sv_threshold);
129  if (rank != nullptr) {
130  *rank = r;
131  }
132 
133  vpHomography H;
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];
139  }
140  }
141  return H;
142 }
143 
144 void vpHomography::inverse(vpHomography &bHa) const { bHa = inverse(); }
145 
146 void vpHomography::save(std::ofstream &f) const
147 {
148  if (!f.fail()) {
149  f << *this;
150  }
151  else {
152  throw(vpException(vpException::ioError, "Cannot write the homography to the output stream"));
153  }
154 }
155 
157 {
158  vpHomography Hp;
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) {
162  double s = 0.;
163  for (unsigned int k = 0; k < nbCols; ++k) {
164  s += (*this)[i][k] * H[k][j];
165  }
166  Hp[i][j] = s;
167  }
168  }
169  return Hp;
170 }
171 
173 {
174  const unsigned int requiredSize = 3;
175  if (b.size() != requiredSize) {
176  throw(vpException(vpException::dimensionError, "Cannot multiply an homography by a vector of dimension %d",
177  b.size()));
178  }
179 
180  vpColVector a(requiredSize);
181  for (unsigned int i = 0; i < requiredSize; ++i) {
182  a[i] = 0.;
183  for (unsigned int j = 0; j < requiredSize; ++j) {
184  a[i] += (*this)[i][j] * b[j];
185  }
186  }
187 
188  return a;
189 }
190 
191 vpHomography vpHomography::operator*(const double &v) const
192 {
193  const unsigned int nbData = 9; // cols x rows = 3 x 3
194  vpHomography H;
195 
196  for (unsigned int i = 0; i < nbData; ++i) {
197  H.data[i] = this->data[i] * v;
198  }
199 
200  return H;
201 }
202 
204 {
205  vpPoint a_P;
206  vpColVector v(3), v1(3);
207 
208  v[0] = b_P.get_x();
209  v[1] = b_P.get_y();
210  v[2] = b_P.get_w();
211 
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]);
215 
216  // v1 is equal to M v ;
217  a_P.set_x(v1[0]);
218  a_P.set_y(v1[1]);
219  a_P.set_w(v1[2]);
220 
221  return a_P;
222 }
223 
224 vpHomography vpHomography::operator/(const double &v) const
225 {
226  vpHomography H;
227  if (std::fabs(v) <= std::numeric_limits<double>::epsilon()) {
228  throw vpMatrixException(vpMatrixException::divideByZeroError, "Divide by zero in method /=(double v)");
229  }
230 
231  double vinv = 1 / v;
232 
233  const unsigned int nbData = 9; // cols x rows = 3 x 3
234  for (unsigned int i = 0; i < nbData; ++i) {
235  H.data[i] = this->data[i] * vinv;
236  }
237 
238  return H;
239 }
240 
242 {
243  if (std::fabs(v) <= std::numeric_limits<double>::epsilon()) {
244  throw vpMatrixException(vpMatrixException::divideByZeroError, "Divide by zero in method /=(double v)");
245  }
246 
247  double vinv = 1 / v;
248 
249  const unsigned int nbData = 9; // cols x rows = 3 x 3
250  for (unsigned int i = 0; i < nbData; ++i) {
251  data[i] *= vinv;
252  }
253 
254  return *this;
255 }
256 
258 {
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];
263  }
264  }
265 
266  m_aMb = H.m_aMb;
267  m_bP = H.m_bP;
268  return *this;
269 }
270 
272 {
273  const unsigned int nbCols = 3, nbRows = 3;
274  if ((H.getRows() != nbRows) || (H.getCols() != nbCols)) {
275  throw(vpException(vpException::dimensionError, "The matrix is not an homography"));
276  }
277 
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];
281  }
282  }
283 
284  return *this;
285 }
286 
287 void vpHomography::load(std::ifstream &f)
288 {
289  const unsigned int nbCols = 3, nbRows = 3;
290  if (!f.fail()) {
291  for (unsigned int i = 0; i < nbRows; ++i) {
292  for (unsigned int j = 0; j < nbCols; ++j) {
293  f >> (*this)[i][j];
294  }
295  }
296  }
297  else {
298  throw(vpException(vpException::ioError, "Cannot read the homography from the input stream"));
299  }
300 }
301 
309 void vpHomography::build()
310 {
311  const unsigned int nbCols = 3, nbRows = 3;
312  vpColVector n(nbRows);
313  vpColVector atb(nbRows);
314  vpMatrix aRb(nbRows, nbCols);
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];
319  }
320  }
321 
322  m_bP.getNormal(n);
323 
324  double d = m_bP.getD();
325  vpMatrix aHb = aRb - ((atb * n.t()) / d); // the d used in the equation is such as nX=d is the
326  // plane equation. So if the plane is described by
327  // Ax+By+Cz+D=0, d=-D
328 
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];
332  }
333  }
334 }
335 
344 void vpHomography::build(vpHomography &aHb, const vpHomogeneousMatrix &aMb, const vpPlane &bP)
345 {
346  const unsigned int nbCols = 3, nbRows = 3;
347  vpColVector n(nbRows);
348  vpColVector atb(nbRows);
349  vpMatrix aRb(nbRows, nbCols);
350  for (unsigned int i = 0; i < nbRows; ++i) {
351  atb[i] = aMb[i][3];
352  for (unsigned int j = 0; j < nbCols; ++j) {
353  aRb[i][j] = aMb[i][j];
354  }
355  }
356 
357  bP.getNormal(n);
358 
359  double d = bP.getD();
360  vpMatrix aHb_ = aRb - ((atb * n.t()) / d); // the d used in the equation is such as nX=d is the
361  // plane equation. So if the plane is described by
362  // Ax+By+Cz+D=0, d=-D
363 
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];
367  }
368  }
369 }
370 
371 double vpHomography::det() const
372 {
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])));
376 }
377 
379 {
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) {
383  if (i == j) {
384  (*this)[i][j] = 1.0;
385  }
386  else {
387  (*this)[i][j] = 0.0;
388  }
389  }
390  }
391 }
392 
394 {
395  double xa = iPa.get_u();
396  double ya = iPa.get_v();
397  vpHomography bGa = bHa.homography2collineation(cam);
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;
401 
402  vpImagePoint iPb(yb, xb);
403 
404  return iPb;
405 }
406 
408 {
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;
414 
415  vpPoint Pb;
416  Pb.set_x(xb);
417  Pb.set_y(yb);
418 
419  return Pb;
420 }
421 
422 
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)
426 {
427  unsigned int n = static_cast<unsigned int>(xb.size());
428  if ((yb.size() != n) || (xa.size() != n) || (ya.size() != n)) {
429  throw(vpException(vpException::dimensionError, "Bad dimension for robust homography estimation"));
430  }
431 
432  // 4 point are required
433  const unsigned int nbRequiredPoints = 4;
434  if (n < nbRequiredPoints) {
435  throw(vpException(vpException::fatalError, "There must be at least 4 matched points"));
436  }
437 
438  try {
439  std::vector<double> xan, yan, xbn, ybn;
440 
441  double xg1 = 0., yg1 = 0., coef1 = 0., xg2 = 0., yg2 = 0., coef2 = 0.;
442 
443  vpHomography aHbn;
444 
445  if (normalization) {
446  vpHomography::hartleyNormalization(xb, yb, xbn, ybn, xg1, yg1, coef1);
447  vpHomography::hartleyNormalization(xa, ya, xan, yan, xg2, yg2, coef2);
448  }
449  else {
450  xbn = xb;
451  ybn = yb;
452  xan = xa;
453  yan = ya;
454  }
455 
456  unsigned int nbLinesA = 2;
457  vpMatrix A(nbLinesA * n, 8);
458  vpColVector X(8);
459  vpColVector Y(nbLinesA * n);
460  vpMatrix W(nbLinesA * n, nbLinesA * n, 0); // Weight matrix
461 
462  vpColVector w(nbLinesA * n);
463 
464  // All the weights are set to 1 at the beginning to use a classical least
465  // square scheme
466  w = 1;
467  // Update the square matrix associated to the weights
468  for (unsigned int i = 0; i < (nbLinesA * n); ++i) {
469  W[i][i] = w[i];
470  }
471 
472  // build matrix A
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];
482 
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];
491 
492  Y[nbLinesA * i] = xan[i];
493  Y[(nbLinesA * i) + 1] = yan[i];
494  }
495 
496  vpMatrix WA;
497  vpMatrix WAp;
498  unsigned int iter = 0;
499  vpRobust r; // M-Estimator
500 
501  while (iter < niter) {
502  WA = W * A;
503 
504  X = WA.pseudoInverse(1e-26) * W * Y;
505  vpColVector residu;
506  residu = Y - (A * X);
507 
508  // Compute the weights using the Tukey biweight M-Estimator
509  r.MEstimator(vpRobust::TUKEY, residu, w);
510 
511  // Update the weights matrix
512  for (unsigned int i = 0; i < (n * nbLinesA); ++i) {
513  W[i][i] = w[i];
514  }
515  // Build the homography
516  for (unsigned int i = 0; i < 8; ++i) {
517  aHbn.data[i] = X[i];
518  }
519  aHbn[2][2] = 1;
520 
521  ++iter;
522  }
523  inliers.resize(n);
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)) {
527  inliers[i] = false;
528  }
529  else {
530  inliers[i] = true;
531  ++nbinliers;
532  }
533  }
534 
535  if (normalization) {
536  // H after denormalization
537  vpHomography::hartleyDenormalization(aHbn, aHb, xg1, yg1, coef1, xg2, yg2, coef2);
538  }
539  else {
540  aHb = aHbn;
541  }
542 
543  residual = 0;
544  vpColVector a(3), b(3), c(3);
545  for (unsigned int i = 0; i < n; ++i) {
546  if (inliers[i]) {
547  a[0] = xa[i];
548  a[1] = ya[i];
549  a[2] = 1;
550  b[0] = xb[i];
551  b[1] = yb[i];
552  b[2] = 1;
553 
554  c = aHb * b;
555  c /= c[2];
556  residual += (a - c).sumSquare();
557  }
558  }
559 
560  residual = sqrt(residual / nbinliers);
561  }
562  catch (...) {
563  throw(vpException(vpException::fatalError, "Cannot estimate an homography"));
564  }
565 }
566 
568 {
569  vpImagePoint ipa;
570  double u = ipb.get_u();
571  double v = ipb.get_v();
572 
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];
576 
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);
580  }
581 
582  return ipa;
583 }
584 
586 {
587  const unsigned int nbRows = 3, nbCols = 3;
588  vpMatrix M(nbRows, nbCols);
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];
592  }
593  }
594 
595  return M;
596 }
597 
599 {
600  vpHomography H;
601  double px = cam.get_px();
602  double py = cam.get_py();
603  double u0 = cam.get_u0();
604  double v0 = cam.get_v0();
605  double one_over_px = cam.get_px_inverse();
606  double one_over_py = cam.get_py_inverse();
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];
610 
611  double u0_one_over_px = u0 * one_over_px;
612  double v0_one_over_py = v0 * one_over_py;
613 
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);
620 
621  H[0][0] = A * px;
622  H[1][0] = D * px;
623  H[2][0] = h20 * px;
624 
625  H[0][1] = B * py;
626  H[1][1] = E * py;
627  H[2][1] = h21 * py;
628 
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;
632 
633  return H;
634 }
635 
637 {
638  vpHomography H;
639  double px = cam.get_px();
640  double py = cam.get_py();
641  double u0 = cam.get_u0();
642  double v0 = cam.get_v0();
643  double one_over_px = cam.get_px_inverse();
644  double one_over_py = cam.get_py_inverse();
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];
648 
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);
655 
656  H[0][0] = A * one_over_px;
657  H[1][0] = D * one_over_px;
658  H[2][0] = h20 * one_over_px;
659 
660  H[0][1] = B * one_over_py;
661  H[1][1] = E * one_over_py;
662  H[2][1] = h21 * one_over_py;
663 
664  double u0_one_over_px = u0 * one_over_px;
665  double v0_one_over_py = v0 * one_over_py;
666 
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;
670 
671  return H;
672 }
Implementation of a generic 2D array used as base class for matrices and vectors.
Definition: vpArray2D.h:125
unsigned int getCols() const
Definition: vpArray2D.h:274
Type * data
Address of the first element of the data array.
Definition: vpArray2D.h:138
unsigned int size() const
Return the number of elements of the 2D array.
Definition: vpArray2D.h:286
unsigned int getRows() const
Definition: vpArray2D.h:284
Generic class defining intrinsic camera parameters.
double get_px_inverse() const
double get_py_inverse() const
Implementation of column vector and the associated operations.
Definition: vpColVector.h:163
error that can be emitted by ViSP classes.
Definition: vpException.h:59
@ ioError
I/O error.
Definition: vpException.h:79
@ dimensionError
Bad dimension.
Definition: vpException.h:83
@ fatalError
Fatal error.
Definition: vpException.h:84
@ divideByZeroError
Division by zero.
Definition: vpException.h:82
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.
Definition: vpHomography.h:168
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)
double det() const
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
vpMatrix convert() 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)
Definition: vpHomography.h:403
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:82
double get_u() const
Definition: vpImagePoint.h:136
void set_u(double u)
Definition: vpImagePoint.h:330
void set_v(double v)
Definition: vpImagePoint.h:341
double get_v() const
Definition: vpImagePoint.h:147
error that can be emitted by the vpMatrix class and its derivatives
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:146
vpMatrix pseudoInverse(double svThreshold=1e-6) const
Definition: vpMatrix.cpp:2286
This class defines the container for a plane geometrical structure.
Definition: vpPlane.h:54
double getD() const
Definition: vpPlane.h:106
vpColVector getNormal() const
Definition: vpPlane.cpp:245
Class that defines a 3D point in the object frame and allows forward projection of a 3D point in the ...
Definition: vpPoint.h:77
double get_w() const
Get the point w coordinate in the image plane.
Definition: vpPoint.cpp:463
void set_x(double x)
Set the point x coordinate in the image plane.
Definition: vpPoint.cpp:500
double get_y() const
Get the point y coordinate in the image plane.
Definition: vpPoint.cpp:461
double get_x() const
Get the point x coordinate in the image plane.
Definition: vpPoint.cpp:459
void set_y(double y)
Set the point y coordinate in the image plane.
Definition: vpPoint.cpp:502
void set_w(double w)
Set the point w coordinate in the image plane.
Definition: vpPoint.cpp:504
Implementation of a pose vector and operations on poses.
Definition: vpPoseVector.h:189
Contains an M-estimator and various influence function.
Definition: vpRobust.h:83
@ TUKEY
Tukey influence function.
Definition: vpRobust.h:88
void MEstimator(const vpRobustEstimatorType method, const vpColVector &residues, vpColVector &weights)
Definition: vpRobust.cpp:136
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.
vpRowVector t() const