Visual Servoing Platform  version 3.6.1 under development (2024-12-03)
vpHomography.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2024 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 BEGIN_VISP_NAMESPACE
52 
53 vpHomography::vpHomography() : vpArray2D<double>(3, 3), m_aMb(), m_bP() { eye(); }
54 
55 vpHomography::vpHomography(const vpHomography &H) : vpArray2D<double>(3, 3), m_aMb(), m_bP() { *this = H; }
56 
57 vpHomography::vpHomography(const vpHomogeneousMatrix &aMb, const vpPlane &bP) : vpArray2D<double>(3, 3), m_aMb(), m_bP()
58 {
59  buildFrom(aMb, bP);
60 }
61 
63  : vpArray2D<double>(3, 3), m_aMb(), m_bP()
64 {
65  buildFrom(tu, atb, p);
66 }
67 
69  : vpArray2D<double>(3, 3), m_aMb(), m_bP()
70 {
71  buildFrom(aRb, atb, p);
72 }
73 
74 vpHomography::vpHomography(const vpPoseVector &arb, const vpPlane &p) : vpArray2D<double>(3, 3), m_aMb(), m_bP()
75 {
76  buildFrom(arb, p);
77 }
78 
80 {
81  insert(aMb);
82  insert(bP);
83  build();
84  return *this;
85 }
86 
88 {
89  insert(tu);
90  insert(atb);
91  insert(p);
92  build();
93  return *this;
94 }
95 
97 {
98  insert(aRb);
99  insert(atb);
100  insert(p);
101  build();
102  return *this;
103 }
104 
106 {
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);
109  insert(p);
110  build();
111  return *this;
112 }
113 
114 /*********************************************************************/
115 
116 void vpHomography::insert(const vpRotationMatrix &aRb) { m_aMb.insert(aRb); }
117 
118 void vpHomography::insert(const vpHomogeneousMatrix &M) { m_aMb = M; }
119 
120 void vpHomography::insert(const vpThetaUVector &tu)
121 {
122  vpRotationMatrix aRb(tu);
123  m_aMb.insert(aRb);
124 }
125 
126 void vpHomography::insert(const vpTranslationVector &atb) { m_aMb.insert(atb); }
127 
128 void vpHomography::insert(const vpPlane &bP) { m_bP = bP; }
129 
130 vpHomography vpHomography::inverse(double sv_threshold, unsigned int *rank) const
131 {
132  vpMatrix M = (*this).convert();
133  vpMatrix Minv;
134  unsigned int r = M.pseudoInverse(Minv, sv_threshold);
135  if (rank != nullptr) {
136  *rank = r;
137  }
138 
139  vpHomography H;
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];
145  }
146  }
147  return H;
148 }
149 
150 void vpHomography::inverse(vpHomography &bHa) const { bHa = inverse(); }
151 
152 void vpHomography::save(std::ofstream &f) const
153 {
154  if (!f.fail()) {
155  f << *this;
156  }
157  else {
158  throw(vpException(vpException::ioError, "Cannot write the homography to the output stream"));
159  }
160 }
161 
163 {
164  vpHomography Hp;
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) {
168  double s = 0.;
169  for (unsigned int k = 0; k < nbCols; ++k) {
170  s += (*this)[i][k] * H[k][j];
171  }
172  Hp[i][j] = s;
173  }
174  }
175  return Hp;
176 }
177 
179 {
180  const unsigned int requiredSize = 3;
181  if (b.size() != requiredSize) {
182  throw(vpException(vpException::dimensionError, "Cannot multiply an homography by a vector of dimension %d",
183  b.size()));
184  }
185 
186  vpColVector a(requiredSize);
187  for (unsigned int i = 0; i < requiredSize; ++i) {
188  a[i] = 0.;
189  for (unsigned int j = 0; j < requiredSize; ++j) {
190  a[i] += (*this)[i][j] * b[j];
191  }
192  }
193 
194  return a;
195 }
196 
197 vpHomography vpHomography::operator*(const double &v) const
198 {
199  const unsigned int nbData = 9; // cols x rows = 3 x 3
200  vpHomography H;
201 
202  for (unsigned int i = 0; i < nbData; ++i) {
203  H.data[i] = this->data[i] * v;
204  }
205 
206  return H;
207 }
208 
210 {
211  vpPoint a_P;
212  vpColVector v(3), v1(3);
213 
214  v[0] = b_P.get_x();
215  v[1] = b_P.get_y();
216  v[2] = b_P.get_w();
217 
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]);
221 
222  // v1 is equal to M v ;
223  a_P.set_x(v1[0]);
224  a_P.set_y(v1[1]);
225  a_P.set_w(v1[2]);
226 
227  return a_P;
228 }
229 
230 vpHomography vpHomography::operator/(const double &v) const
231 {
232  vpHomography H;
233  if (std::fabs(v) <= std::numeric_limits<double>::epsilon()) {
234  throw vpMatrixException(vpMatrixException::divideByZeroError, "Divide by zero in method /=(double v)");
235  }
236 
237  double vinv = 1 / v;
238 
239  const unsigned int nbData = 9; // cols x rows = 3 x 3
240  for (unsigned int i = 0; i < nbData; ++i) {
241  H.data[i] = this->data[i] * vinv;
242  }
243 
244  return H;
245 }
246 
248 {
249  if (std::fabs(v) <= std::numeric_limits<double>::epsilon()) {
250  throw vpMatrixException(vpMatrixException::divideByZeroError, "Divide by zero in method /=(double v)");
251  }
252 
253  double vinv = 1 / v;
254 
255  const unsigned int nbData = 9; // cols x rows = 3 x 3
256  for (unsigned int i = 0; i < nbData; ++i) {
257  data[i] *= vinv;
258  }
259 
260  return *this;
261 }
262 
264 {
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];
269  }
270  }
271 
272  m_aMb = H.m_aMb;
273  m_bP = H.m_bP;
274  return *this;
275 }
276 
278 {
279  const unsigned int nbCols = 3, nbRows = 3;
280  if ((H.getRows() != nbRows) || (H.getCols() != nbCols)) {
281  throw(vpException(vpException::dimensionError, "The matrix is not an homography"));
282  }
283 
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];
287  }
288  }
289 
290  return *this;
291 }
292 
293 void vpHomography::load(std::ifstream &f)
294 {
295  const unsigned int nbCols = 3, nbRows = 3;
296  if (!f.fail()) {
297  for (unsigned int i = 0; i < nbRows; ++i) {
298  for (unsigned int j = 0; j < nbCols; ++j) {
299  f >> (*this)[i][j];
300  }
301  }
302  }
303  else {
304  throw(vpException(vpException::ioError, "Cannot read the homography from the input stream"));
305  }
306 }
307 
315 void vpHomography::build()
316 {
317  const unsigned int nbCols = 3, nbRows = 3;
318  vpColVector n(nbRows);
319  vpColVector atb(nbRows);
320  vpMatrix aRb(nbRows, nbCols);
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];
325  }
326  }
327 
328  m_bP.getNormal(n);
329 
330  double d = m_bP.getD();
331  vpMatrix aHb = aRb - ((atb * n.t()) / d); // the d used in the equation is such as nX=d is the
332  // plane equation. So if the plane is described by
333  // Ax+By+Cz+D=0, d=-D
334 
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];
338  }
339  }
340 }
341 
342 #ifndef DOXYGEN_SHOULD_SKIP_THIS
354 void vpHomography::build(vpHomography &aHb, const vpHomogeneousMatrix &aMb, const vpPlane &bP)
355 {
356  const unsigned int nbCols = 3, nbRows = 3;
357  vpColVector n(nbRows);
358  vpColVector atb(nbRows);
359  vpMatrix aRb(nbRows, nbCols);
360  for (unsigned int i = 0; i < nbRows; ++i) {
361  atb[i] = aMb[i][3];
362  for (unsigned int j = 0; j < nbCols; ++j) {
363  aRb[i][j] = aMb[i][j];
364  }
365  }
366 
367  bP.getNormal(n);
368 
369  double d = bP.getD();
370  vpMatrix aHb_ = aRb - ((atb * n.t()) / d); // the d used in the equation is such as nX=d is the
371  // plane equation. So if the plane is described by
372  // Ax+By+Cz+D=0, d=-D
373 
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];
377  }
378  }
379 }
380 #endif
381 
382 double vpHomography::det() const
383 {
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]))));
387 }
388 
390 {
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) {
394  if (i == j) {
395  (*this)[i][j] = 1.0;
396  }
397  else {
398  (*this)[i][j] = 0.0;
399  }
400  }
401  }
402 }
403 
405 {
406  double xa = iPa.get_u();
407  double ya = iPa.get_v();
408  vpHomography bGa = bHa.homography2collineation(cam);
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;
412 
413  vpImagePoint iPb(yb, xb);
414 
415  return iPb;
416 }
417 
419 {
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;
425 
426  vpPoint Pb;
427  Pb.set_x(xb);
428  Pb.set_y(yb);
429 
430  return Pb;
431 }
432 
433 
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)
437 {
438  unsigned int n = static_cast<unsigned int>(xb.size());
439  if ((yb.size() != n) || (xa.size() != n) || (ya.size() != n)) {
440  throw(vpException(vpException::dimensionError, "Bad dimension for robust homography estimation"));
441  }
442 
443  // 4 point are required
444  const unsigned int nbRequiredPoints = 4;
445  if (n < nbRequiredPoints) {
446  throw(vpException(vpException::fatalError, "There must be at least 4 matched points"));
447  }
448 
449  try {
450  std::vector<double> xan, yan, xbn, ybn;
451 
452  double xg1 = 0., yg1 = 0., coef1 = 0., xg2 = 0., yg2 = 0., coef2 = 0.;
453 
454  vpHomography aHbn;
455 
456  if (normalization) {
457  vpHomography::hartleyNormalization(xb, yb, xbn, ybn, xg1, yg1, coef1);
458  vpHomography::hartleyNormalization(xa, ya, xan, yan, xg2, yg2, coef2);
459  }
460  else {
461  xbn = xb;
462  ybn = yb;
463  xan = xa;
464  yan = ya;
465  }
466 
467  unsigned int nbLinesA = 2;
468  vpMatrix A(nbLinesA * n, 8);
469  vpColVector X(8);
470  vpColVector Y(nbLinesA * n);
471  vpMatrix W(nbLinesA * n, nbLinesA * n, 0); // Weight matrix
472 
473  vpColVector w(nbLinesA * n);
474 
475  // All the weights are set to 1 at the beginning to use a classical least
476  // square scheme
477  w = 1;
478  // Update the square matrix associated to the weights
479  for (unsigned int i = 0; i < (nbLinesA * n); ++i) {
480  W[i][i] = w[i];
481  }
482 
483  // build matrix A
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];
493 
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];
502 
503  Y[nbLinesA * i] = xan[i];
504  Y[(nbLinesA * i) + 1] = yan[i];
505  }
506 
507  vpMatrix WA;
508  vpMatrix WAp;
509  unsigned int iter = 0;
510  vpRobust r; // M-Estimator
511 
512  while (iter < niter) {
513  WA = W * A;
514 
515  X = WA.pseudoInverse(1e-26) * W * Y;
516  vpColVector residu;
517  residu = Y - (A * X);
518 
519  // Compute the weights using the Tukey biweight M-Estimator
520  r.MEstimator(vpRobust::TUKEY, residu, w);
521 
522  // Update the weights matrix
523  for (unsigned int i = 0; i < (n * nbLinesA); ++i) {
524  W[i][i] = w[i];
525  }
526  // Build the homography
527  for (unsigned int i = 0; i < 8; ++i) {
528  aHbn.data[i] = X[i];
529  }
530  aHbn[2][2] = 1;
531 
532  ++iter;
533  }
534  inliers.resize(n);
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)) {
538  inliers[i] = false;
539  }
540  else {
541  inliers[i] = true;
542  ++nbinliers;
543  }
544  }
545 
546  if (normalization) {
547  // H after denormalization
548  vpHomography::hartleyDenormalization(aHbn, aHb, xg1, yg1, coef1, xg2, yg2, coef2);
549  }
550  else {
551  aHb = aHbn;
552  }
553 
554  residual = 0;
555  vpColVector a(3), b(3), c(3);
556  for (unsigned int i = 0; i < n; ++i) {
557  if (inliers[i]) {
558  a[0] = xa[i];
559  a[1] = ya[i];
560  a[2] = 1;
561  b[0] = xb[i];
562  b[1] = yb[i];
563  b[2] = 1;
564 
565  c = aHb * b;
566  c /= c[2];
567  residual += (a - c).sumSquare();
568  }
569  }
570 
571  residual = sqrt(residual / nbinliers);
572  }
573  catch (...) {
574  throw(vpException(vpException::fatalError, "Cannot estimate an homography"));
575  }
576 }
577 
579 {
580  vpImagePoint ipa;
581  double u = ipb.get_u();
582  double v = ipb.get_v();
583 
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];
587 
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);
591  }
592 
593  return ipa;
594 }
595 
597 {
598  const unsigned int nbRows = 3, nbCols = 3;
599  vpMatrix M(nbRows, nbCols);
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];
603  }
604  }
605 
606  return M;
607 }
608 
610 {
611  vpHomography H;
612  double px = cam.get_px();
613  double py = cam.get_py();
614  double u0 = cam.get_u0();
615  double v0 = cam.get_v0();
616  double one_over_px = cam.get_px_inverse();
617  double one_over_py = cam.get_py_inverse();
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];
621 
622  double u0_one_over_px = u0 * one_over_px;
623  double v0_one_over_py = v0 * one_over_py;
624 
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);
631 
632  H[0][0] = A * px;
633  H[1][0] = D * px;
634  H[2][0] = h20 * px;
635 
636  H[0][1] = B * py;
637  H[1][1] = E * py;
638  H[2][1] = h21 * py;
639 
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;
643 
644  return H;
645 }
646 
648 {
649  vpHomography H;
650  double px = cam.get_px();
651  double py = cam.get_py();
652  double u0 = cam.get_u0();
653  double v0 = cam.get_v0();
654  double one_over_px = cam.get_px_inverse();
655  double one_over_py = cam.get_py_inverse();
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];
659 
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);
666 
667  H[0][0] = A * one_over_px;
668  H[1][0] = D * one_over_px;
669  H[2][0] = h20 * one_over_px;
670 
671  H[0][1] = B * one_over_py;
672  H[1][1] = E * one_over_py;
673  H[2][1] = h21 * one_over_py;
674 
675  double u0_one_over_px = u0 * one_over_px;
676  double v0_one_over_py = v0 * one_over_py;
677 
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;
681 
682  return H;
683 }
684 
685 END_VISP_NAMESPACE
Implementation of a generic 2D array used as base class for matrices and vectors.
Definition: vpArray2D.h:145
unsigned int getCols() const
Definition: vpArray2D.h:337
Type * data
Address of the first element of the data array.
Definition: vpArray2D.h:148
unsigned int size() const
Return the number of elements of the 2D array.
Definition: vpArray2D.h:349
unsigned int getRows() const
Definition: vpArray2D.h:347
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:191
error that can be emitted by ViSP classes.
Definition: vpException.h:60
@ ioError
I/O error.
Definition: vpException.h:67
@ dimensionError
Bad dimension.
Definition: vpException.h:71
@ fatalError
Fatal error.
Definition: vpException.h:72
@ divideByZeroError
Division by zero.
Definition: vpException.h:70
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.
Definition: vpHomography.h:174
vpHomography collineation2homography(const vpCameraParameters &cam) const
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:409
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 ...
Definition: vpImagePoint.h:82
double get_u() const
Definition: vpImagePoint.h:136
void set_u(double u)
Definition: vpImagePoint.h:335
void set_v(double v)
Definition: vpImagePoint.h:346
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:169
vpMatrix pseudoInverse(double svThreshold=1e-6) const
This class defines the container for a plane geometrical structure.
Definition: vpPlane.h:57
double getD() const
Definition: vpPlane.h:106
vpColVector getNormal() const
Definition: vpPlane.cpp:258
Class that defines a 3D point in the object frame and allows forward projection of a 3D point in the ...
Definition: vpPoint.h:79
double get_w() const
Get the point w coordinate in the image plane.
Definition: vpPoint.cpp:428
void set_x(double x)
Set the point x coordinate in the image plane.
Definition: vpPoint.cpp:468
double get_y() const
Get the point y coordinate in the image plane.
Definition: vpPoint.cpp:426
double get_x() const
Get the point x coordinate in the image plane.
Definition: vpPoint.cpp:424
void set_y(double y)
Set the point y coordinate in the image plane.
Definition: vpPoint.cpp:470
void set_w(double w)
Set the point w coordinate in the image plane.
Definition: vpPoint.cpp:472
Implementation of a pose vector and operations on poses.
Definition: vpPoseVector.h:203
Contains an M-estimator and various influence function.
Definition: vpRobust.h:84
@ TUKEY
Tukey influence function.
Definition: vpRobust.h:89
void MEstimator(const vpRobustEstimatorType method, const vpColVector &residues, vpColVector &weights)
Definition: vpRobust.cpp:130
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