28 fx = cam_intrinsic(0, 0);
29 fy = cam_intrinsic(1, 1);
30 cx = cam_intrinsic(0, 2);
31 cy = cam_intrinsic(1, 2);
32 init_inverse_parameters();
41 init_inverse_parameters();
47 if (cameraMatrix.depth() == CV_32F)
48 init_camera_parameters<float>(cameraMatrix);
50 init_camera_parameters<double>(cameraMatrix);
51 init_inverse_parameters();
55 cv::Mat&
R, cv::Mat& tvec,
const cv::Mat& opoints,
const cv::Mat& ipoints)
57 double rotation_matrix[3][3], translation[3];
58 std::vector<double>
points;
59 if (opoints.depth() == ipoints.depth())
61 if (opoints.depth() == CV_32F)
62 extract_points<cv::Point3f, cv::Point2f>(opoints, ipoints,
points);
64 extract_points<cv::Point3d, cv::Point2d>(opoints, ipoints,
points);
66 else if (opoints.depth() == CV_32F)
67 extract_points<cv::Point3f, cv::Point2d>(opoints, ipoints,
points);
69 extract_points<cv::Point3d, cv::Point2f>(opoints, ipoints,
points);
76 cv::Mat(3, 1, CV_64F, translation).copyTo(tvec);
77 cv::Mat(3, 3, CV_64F, rotation_matrix).copyTo(
R);
84 Eigen::Ref<Eigen::Matrix3d>
R, Eigen::Ref<Eigen::Vector3d>
t,
85 Eigen::MatrixXd obj_pts, Eigen::MatrixXd img_pts)
87 double rotation_matrix[3][3], translation[3];
88 std::vector<double>
points;
89 extract_points(obj_pts, img_pts,
points);
101 double R[3][3],
double t[3],
double mu0,
double mv0,
double X0,
double Y0,
102 double Z0,
double mu1,
double mv1,
double X1,
double Y1,
double Z1,
103 double mu2,
double mv2,
double X2,
double Y2,
double Z2,
double mu3,
104 double mv3,
double X3,
double Y3,
double Z3)
106 double Rs[4][3][3], ts[4][3];
109 Rs, ts, mu0, mv0, X0, Y0, Z0, mu1, mv1, X1, Y1, Z1, mu2, mv2, X2, Y2,
112 if (
n == 0)
return false;
115 double min_reproj = 0;
116 for (
int i = 0; i <
n; i++)
119 Rs[i][0][0] * X3 + Rs[i][0][1] * Y3 + Rs[i][0][2] * Z3 + ts[i][0];
121 Rs[i][1][0] * X3 + Rs[i][1][1] * Y3 + Rs[i][1][2] * Z3 + ts[i][1];
123 Rs[i][2][0] * X3 + Rs[i][2][1] * Y3 + Rs[i][2][2] * Z3 + ts[i][2];
124 double mu3p = cx + fx * X3p / Z3p;
125 double mv3p = cy + fy * Y3p / Z3p;
127 (mu3p - mu3) * (mu3p - mu3) + (mv3p - mv3) * (mv3p - mv3);
128 if (i == 0 || min_reproj > reproj)
135 for (
int i = 0; i < 3; i++)
137 for (
int j = 0; j < 3; j++)
R[i][j] = Rs[ns][i][j];
145 double R[4][3][3],
double t[4][3],
double mu0,
double mv0,
double X0,
146 double Y0,
double Z0,
double mu1,
double mv1,
double X1,
double Y1,
147 double Z1,
double mu2,
double mv2,
double X2,
double Y2,
double Z2)
149 double mk0, mk1, mk2;
152 mu0 = inv_fx * mu0 - cx_fx;
153 mv0 = inv_fy * mv0 - cy_fy;
154 norm = sqrt(mu0 * mu0 + mv0 * mv0 + 1);
159 mu1 = inv_fx * mu1 - cx_fx;
160 mv1 = inv_fy * mv1 - cy_fy;
161 norm = sqrt(mu1 * mu1 + mv1 * mv1 + 1);
166 mu2 = inv_fx * mu2 - cx_fx;
167 mv2 = inv_fy * mv2 - cy_fy;
168 norm = sqrt(mu2 * mu2 + mv2 * mv2 + 1);
175 (X1 - X2) * (X1 - X2) + (Y1 - Y2) * (Y1 - Y2) + (Z1 - Z2) * (Z1 - Z2));
177 (X0 - X2) * (X0 - X2) + (Y0 - Y2) * (Y0 - Y2) + (Z0 - Z2) * (Z0 - Z2));
179 (X0 - X1) * (X0 - X1) + (Y0 - Y1) * (Y0 - Y1) + (Z0 - Z1) * (Z0 - Z1));
183 cosines[0] = mu1 * mu2 + mv1 * mv2 + mk1 * mk2;
184 cosines[1] = mu0 * mu2 + mv0 * mv2 + mk0 * mk2;
185 cosines[2] = mu0 * mu1 + mv0 * mv1 + mk0 * mk1;
187 double lengths[4][3];
188 int n = solve_for_lengths(lengths, distances, cosines);
190 int nb_solutions = 0;
191 for (
int i = 0; i <
n; i++)
195 M_orig[0][0] = lengths[i][0] * mu0;
196 M_orig[0][1] = lengths[i][0] * mv0;
197 M_orig[0][2] = lengths[i][0] * mk0;
199 M_orig[1][0] = lengths[i][1] * mu1;
200 M_orig[1][1] = lengths[i][1] * mv1;
201 M_orig[1][2] = lengths[i][1] * mk1;
203 M_orig[2][0] = lengths[i][2] * mu2;
204 M_orig[2][1] = lengths[i][2] * mv2;
205 M_orig[2][2] = lengths[i][2] * mk2;
208 M_orig, X0, Y0, Z0, X1, Y1, Z1, X2, Y2, Z2,
R[nb_solutions],
234 double lengths[4][3],
double distances[3],
double cosines[3])
236 double p = cosines[0] * 2;
237 double q = cosines[1] * 2;
238 double r = cosines[2] * 2;
240 double inv_d22 = 1. / (distances[2] * distances[2]);
241 double a = inv_d22 * (distances[0] * distances[0]);
242 double b = inv_d22 * (distances[1] * distances[1]);
244 double a2 =
a *
a,
b2 =
b *
b, p2 =
p *
p, q2 =
q *
q, r2 =
r *
r;
245 double pr =
p *
r, pqr =
q * pr;
248 if (p2 + q2 + r2 - pqr - 1 == 0)
return 0;
250 double ab =
a *
b, a_2 = 2 *
a;
252 double A = -2 *
b +
b2 +
a2 + 1 + ab * (2 - r2) - a_2;
255 if (
A == 0)
return 0;
260 q * (-2 * (ab +
a2 + 1 -
b) + r2 * ab + a_4) + pr * (
b -
b2 + ab);
261 double C = q2 +
b2 * (r2 + p2 - 2) -
b * (p2 + pqr) - ab * (r2 + pqr) +
262 (
a2 - a_2) * (2 + q2) + 2;
264 pr * (ab -
b2 +
b) +
q * ((p2 - 2) *
b + 2 * (ab -
a2) + a_4 - 2);
265 double E = 1 + 2 * (
b -
a - ab) +
b2 -
b * p2 +
a2;
267 double temp = (p2 * (
a - 1 +
b) + r2 * (
a - 1 -
b) + pqr -
a * pqr);
268 double b0 =
b * temp * temp;
270 if (
b0 == 0)
return 0;
272 double real_roots[4];
274 A, B, C, D, E, real_roots[0], real_roots[1], real_roots[2],
277 if (
n == 0)
return 0;
279 int nb_solutions = 0;
280 double r3 = r2 *
r, pr2 =
p * r2, r3q = r3 *
q;
281 double inv_b0 = 1. /
b0;
284 for (
int i = 0; i <
n; i++)
286 double x = real_roots[i];
289 if (
x <= 0)
continue;
294 ((1 -
a -
b) * x2 + (
q *
a -
q) *
x + 1 -
a +
b) *
295 (((r3 * (
a2 + ab * (2 - r2) - a_2 +
b2 - 2 *
b + 1)) *
x +
297 (r3q * (2 * (
b -
a2) + a_4 + ab * (r2 - 2) - 2) +
298 pr2 * (1 +
a2 + 2 * (ab -
a -
b) + r2 * (
b -
b2) +
b2))) *
301 (r3 * (q2 * (1 - 2 *
a +
a2) + r2 * (
b2 - ab) - a_4 +
303 r * p2 * (
b2 + 2 * (ab -
b -
a) + 1 +
a2) +
304 pr2 *
q * (a_4 + 2 * (
b - ab -
a2) - 2 - r2 *
b)) *
307 2 * r3q * (a_2 -
b -
a2 + ab - 1) +
308 pr2 * (q2 - a_4 + 2 * (
a2 -
b2) + r2 *
b + q2 * (
a2 - a_2) + 2) +
309 p2 * (
p * (2 * (ab -
a -
b) +
a2 +
b2 + 1) +
310 2 *
q *
r * (
b + a_2 -
a2 - ab - 1)));
313 if (
b1 <= 0)
continue;
315 double y = inv_b0 *
b1;
316 double v = x2 +
y *
y -
x *
y *
r;
318 if (
v <= 0)
continue;
320 double Z = distances[2] / sqrt(
v);
324 lengths[nb_solutions][0] = X;
325 lengths[nb_solutions][1] = Y;
326 lengths[nb_solutions][2] = Z;
335 double M_end[3][3],
double X0,
double Y0,
double Z0,
double X1,
double Y1,
336 double Z1,
double X2,
double Y2,
double Z2,
double R[3][3],
double T[3])
339 double C_start[3], C_end[3];
340 for (
int i = 0; i < 3; i++)
341 C_end[i] = (M_end[0][i] + M_end[1][i] + M_end[2][i]) / 3;
342 C_start[0] = (X0 + X1 + X2) / 3;
343 C_start[1] = (Y0 + Y1 + Y2) / 3;
344 C_start[2] = (Z0 + Z1 + Z2) / 3;
348 for (
int j = 0; j < 3; j++)
351 (X0 * M_end[0][j] + X1 * M_end[1][j] + X2 * M_end[2][j]) / 3 -
352 C_end[j] * C_start[0];
354 (Y0 * M_end[0][j] + Y1 * M_end[1][j] + Y2 * M_end[2][j]) / 3 -
355 C_end[j] * C_start[1];
357 (Z0 * M_end[0][j] + Z1 * M_end[1][j] + Z2 * M_end[2][j]) / 3 -
358 C_end[j] * C_start[2];
361 double Qs[16], evs[4], U[16];
363 Qs[0 * 4 + 0] =
s[0 * 3 + 0] +
s[1 * 3 + 1] +
s[2 * 3 + 2];
364 Qs[1 * 4 + 1] =
s[0 * 3 + 0] -
s[1 * 3 + 1] -
s[2 * 3 + 2];
365 Qs[2 * 4 + 2] =
s[1 * 3 + 1] -
s[2 * 3 + 2] -
s[0 * 3 + 0];
366 Qs[3 * 4 + 3] =
s[2 * 3 + 2] -
s[0 * 3 + 0] -
s[1 * 3 + 1];
368 Qs[1 * 4 + 0] = Qs[0 * 4 + 1] =
s[1 * 3 + 2] -
s[2 * 3 + 1];
369 Qs[2 * 4 + 0] = Qs[0 * 4 + 2] =
s[2 * 3 + 0] -
s[0 * 3 + 2];
370 Qs[3 * 4 + 0] = Qs[0 * 4 + 3] =
s[0 * 3 + 1] -
s[1 * 3 + 0];
371 Qs[2 * 4 + 1] = Qs[1 * 4 + 2] =
s[1 * 3 + 0] +
s[0 * 3 + 1];
372 Qs[3 * 4 + 1] = Qs[1 * 4 + 3] =
s[2 * 3 + 0] +
s[0 * 3 + 2];
373 Qs[3 * 4 + 2] = Qs[2 * 4 + 3] =
s[2 * 3 + 1] +
s[1 * 3 + 2];
375 jacobi_4x4(Qs, evs, U);
379 double ev_max = evs[i_ev];
380 for (
int i = 1; i < 4; i++)
381 if (evs[i] > ev_max) ev_max = evs[i_ev = i];
385 for (
int i = 0; i < 4; i++)
q[i] = U[i * 4 + i_ev];
387 double q02 =
q[0] *
q[0], q12 =
q[1] *
q[1], q22 =
q[2] *
q[2],
389 double q0_1 =
q[0] *
q[1], q0_2 =
q[0] *
q[2], q0_3 =
q[0] *
q[3];
390 double q1_2 =
q[1] *
q[2], q1_3 =
q[1] *
q[3];
391 double q2_3 =
q[2] *
q[3];
393 R[0][0] = q02 + q12 - q22 - q32;
394 R[0][1] = 2. * (q1_2 - q0_3);
395 R[0][2] = 2. * (q1_3 + q0_2);
397 R[1][0] = 2. * (q1_2 + q0_3);
398 R[1][1] = q02 + q22 - q12 - q32;
399 R[1][2] = 2. * (q2_3 - q0_1);
401 R[2][0] = 2. * (q1_3 - q0_2);
402 R[2][1] = 2. * (q2_3 + q0_1);
403 R[2][2] = q02 + q32 - q12 - q22;
405 for (
int i = 0; i < 3; i++)
406 T[i] = C_end[i] - (
R[i][0] * C_start[0] +
R[i][1] * C_start[1] +
407 R[i][2] * C_start[2]);
415 double Id[16] = {1., 0., 0., 0., 0., 1., 0., 0.,
416 0., 0., 1., 0., 0., 0., 0., 1.};
418 memcpy(U, Id, 16 *
sizeof(
double));
424 memcpy(D, B, 4 *
sizeof(
double));
425 memset(Z, 0, 4 *
sizeof(
double));
427 for (
int iter = 0; iter < 50; iter++)
429 double sum = fabs(
A[1]) + fabs(
A[2]) + fabs(
A[3]) + fabs(
A[6]) +
430 fabs(
A[7]) + fabs(
A[11]);
432 if (
sum == 0.0)
return true;
434 double tresh = (iter < 3) ? 0.2 *
sum / 16. : 0.0;
435 for (
int i = 0; i < 3; i++)
437 double* pAij =
A + 5 * i + 1;
438 for (
int j = i + 1; j < 4; j++)
441 double eps_machine = 100.0 * fabs(Aij);
443 if (iter > 3 && fabs(D[i]) + eps_machine == fabs(D[i]) &&
444 fabs(D[j]) + eps_machine == fabs(D[j]))
446 else if (fabs(Aij) > tresh)
448 double hh = D[j] - D[i],
t;
449 if (fabs(hh) + eps_machine == fabs(hh))
453 double theta = 0.5 * hh / Aij;
454 t = 1.0 / (fabs(theta) + sqrt(1.0 + theta * theta));
455 if (theta < 0.0)
t = -
t;
465 double c = 1.0 / sqrt(1 +
t *
t);
467 double tau =
s / (1.0 +
c);
468 for (
int k = 0; k <= i - 1; k++)
470 double g =
A[k * 4 + i], h =
A[k * 4 + j];
471 A[k * 4 + i] =
g -
s * (h +
g * tau);
472 A[k * 4 + j] = h +
s * (
g - h * tau);
474 for (
int k = i + 1; k <= j - 1; k++)
476 double g =
A[i * 4 + k], h =
A[k * 4 + j];
477 A[i * 4 + k] =
g -
s * (h +
g * tau);
478 A[k * 4 + j] = h +
s * (
g - h * tau);
480 for (
int k = j + 1; k < 4; k++)
482 double g =
A[i * 4 + k], h =
A[j * 4 + k];
483 A[i * 4 + k] =
g -
s * (h +
g * tau);
484 A[j * 4 + k] = h +
s * (
g - h * tau);
486 for (
int k = 0; k < 4; k++)
488 double g = U[k * 4 + i], h = U[k * 4 + j];
489 U[k * 4 + i] =
g -
s * (h +
g * tau);
490 U[k * 4 + j] = h +
s * (
g - h * tau);
497 for (
int i = 0; i < 4; i++) B[i] += Z[i];
498 memcpy(D, B, 4 *
sizeof(
double));
499 memset(Z, 0, 4 *
sizeof(
double));
bool solve(cv::Mat &R, cv::Mat &tvec, const cv::Mat &opoints, const cv::Mat &ipoints)
Function to compute pose by P3P using OpenCV.
GLdouble GLdouble GLdouble GLdouble q
bool jacobi_4x4(double *A, double *D, double *U)
Function used to compute the SVD.
GLsizei const GLfloat * points
double inv_fy
Inverse of focal length x.
bool align(double M_start[3][3], double X0, double Y0, double Z0, double X1, double Y1, double Z1, double X2, double Y2, double Z2, double R[3][3], double T[3])
int solve_for_lengths(double lengths[4][3], double distances[3], double cosines[3])
Helper function to solve()
CONTAINER::Scalar sum(const CONTAINER &v)
Computes the sum of all the elements.
double cy_fy
Inverse of image center point x.
int solve_deg4(double a, double b, double c, double d, double e, double &x0, double &x1, double &x2, double &x3)
Reference : Eric W.
void init_inverse_parameters()
Function to compute inverse parameters of camera intrinsic matrix.
p3p(double fx, double fy, double cx, double cy)
Constructor for p3p class using C.
GLdouble GLdouble GLdouble r
double cx_fx
Inverse of focal length y.
GLubyte GLubyte GLubyte a
double inv_fx
Image center y.
CONTAINER::Scalar norm(const CONTAINER &v)
P3P Pose estimation Algorithm - Eigen Implementation.
void memcpy(void *dest, size_t destSize, const void *src, size_t copyCount) noexcept
An OS and compiler independent version of "memcpy".