34 #include <opencv2/calib3d.hpp>
38 namespace aruco_private
42 assert(_rvec.type() == CV_32F && _rvec.total() == 3);
43 assert(_tvec.type() == CV_32F && _tvec.total() == 3);
45 cv::Mat Matrix(4, 4, CV_32F);
46 float* rt_44 = Matrix.ptr<
float>(0);
49 float rx = _rvec.ptr<
float>(0)[0];
50 float ry = _rvec.ptr<
float>(0)[1];
51 float rz = _rvec.ptr<
float>(0)[2];
52 float tx = _tvec.ptr<
float>(0)[0];
53 float ty = _tvec.ptr<
float>(0)[1];
54 float tz = _tvec.ptr<
float>(0)[2];
55 float nsqa = rx * rx + ry * ry + rz * rz;
56 float a = std::sqrt(nsqa);
57 float i_a = a ? 1. / a : 0;
63 float _1_cos_a = 1. - cos_a;
64 rt_44[0] = cos_a + rnx * rnx * _1_cos_a;
65 rt_44[1] = rnx * rny * _1_cos_a - rnz * sin_a;
66 rt_44[2] = rny * sin_a + rnx * rnz * _1_cos_a;
68 rt_44[4] = rnz * sin_a + rnx * rny * _1_cos_a;
69 rt_44[5] = cos_a + rny * rny * _1_cos_a;
70 rt_44[6] = -rnx * sin_a + rny * rnz * _1_cos_a;
72 rt_44[8] = -rny * sin_a + rnx * rnz * _1_cos_a;
73 rt_44[9] = rnx * sin_a + rny * rnz * _1_cos_a;
74 rt_44[10] = cos_a + rnz * rnz * _1_cos_a;
76 rt_44[12] = rt_44[13] = rt_44[14] = 0;
83 assert(M.cols == M.rows && M.cols == 4);
84 assert(M.type() == CV_32F || M.type() == CV_64F);
87 cv::Mat r33 = cv::Mat(M, cv::Rect(0, 0, 3, 3));
89 cv::Mat Rpure = svd.u * svd.vt;
90 cv::Rodrigues(Rpure, R);
91 T.create(1, 3, M.type());
92 if (M.type() == CV_32F)
93 for (
int i = 0; i < 3; i++)
94 T.ptr<
float>(0)[i] = M.at<
float>(i, 3);
96 for (
int i = 0; i < 3; i++)
97 T.ptr<
double>(0)[i] = M.at<
double>(i, 3);
104 std::vector<cv::Point2f> prepj;
110 for (
size_t i = 0; i < prepj.size(); i++)
112 if (!std::isnan(objPoints[i].x))
114 sum += cv::norm(points2d[i] - prepj[i]);
118 return sum / double(nvalid);
126 const std::vector<cv::Point3f>& PDst, cv::Mat& RT_4x4)
130 Quaternion(
float q0,
float q1,
float q2,
float q3)
137 cv::Mat getRotation()
const
139 cv::Mat R(3, 3, CV_32F);
140 R.at<
float>(0, 0) = q[0] * q[0] + q[1] * q[1] - q[2] * q[2] - q[3] * q[3];
141 R.at<
float>(0, 1) = 2.
f * (q[1] * q[2] - q[0] * q[3]);
142 R.at<
float>(0, 2) = 2.
f * (q[1] * q[3] + q[0] * q[2]);
144 R.at<
float>(1, 0) = 2.
f * (q[1] * q[2] + q[0] * q[3]);
145 R.at<
float>(1, 1) = q[0] * q[0] + q[2] * q[2] - q[1] * q[1] - q[3] * q[3];
146 R.at<
float>(1, 2) = 2.
f * (q[2] * q[3] - q[0] * q[1]);
148 R.at<
float>(2, 0) = 2.
f * (q[1] * q[3] - q[0] * q[2]);
149 R.at<
float>(2, 1) = 2.
f * (q[2] * q[3] + q[0] * q[1]);
150 R.at<
float>(2, 2) = q[0] * q[0] + q[3] * q[3] - q[1] * q[1] - q[2] * q[2];
156 assert(POrg.size() == PDst.size());
158 cv::Mat _org(POrg.size(), 3, CV_32F, (
float*)&POrg[0]);
159 cv::Mat _dst(PDst.size(), 3, CV_32F, (
float*)&PDst[0]);
163 cv::Mat Mu_s = cv::Mat::zeros(1, 3, CV_32F);
164 cv::Mat Mu_m = cv::Mat::zeros(1, 3, CV_32F);
168 for (
int i = 0; i < _org.rows; i++)
170 Mu_s += _org(cv::Range(i, i + 1), cv::Range(0, 3));
171 Mu_m += _dst(cv::Range(i, i + 1), cv::Range(0, 3));
175 for (
int i = 0; i < 3; i++)
177 Mu_s.ptr<
float>(0)[i] /=
float(_org.rows);
178 Mu_m.ptr<
float>(0)[i] /=
float(_dst.rows);
184 cv::Mat Mu_st = Mu_s.t() * Mu_m;
186 cv::Mat Var_sm = cv::Mat::zeros(3, 3, CV_32F);
187 for (
int i = 0; i < _org.rows; i++)
188 Var_sm += (_org(cv::Range(i, i + 1), cv::Range(0, 3)).t() *
189 _dst(cv::Range(i, i + 1), cv::Range(0, 3))) -
192 for (
int i = 0; i < 3; i++)
193 for (
int j = 0; j < 3; j++)
194 Var_sm.at<
float>(i, j) /= float(_org.rows);
197 cv::Mat AA = Var_sm - Var_sm.t();
199 cv::Mat A(3, 1, CV_32F);
200 A.at<
float>(0, 0) = AA.at<
float>(1, 2);
201 A.at<
float>(1, 0) = AA.at<
float>(2, 0);
202 A.at<
float>(2, 0) = AA.at<
float>(0, 1);
204 cv::Mat Q_Var_sm(4, 4, CV_32F);
205 Q_Var_sm.at<
float>(0, 0) =
static_cast<float>(trace(Var_sm)[0]);
206 for (
int i = 1; i < 4; i++)
208 Q_Var_sm.at<
float>(0, i) = A.ptr<
float>(0)[i - 1];
209 Q_Var_sm.at<
float>(i, 0) = A.ptr<
float>(0)[i - 1];
211 cv::Mat q33 = Var_sm + Var_sm.t() - (trace(Var_sm)[0] * cv::Mat::eye(3, 3, CV_32F));
213 cv::Mat Q33 = Q_Var_sm(cv::Range(1, 4), cv::Range(1, 4));
216 cv::Mat eigenvalues, eigenvectors;
217 eigen(Q_Var_sm, eigenvalues, eigenvectors);
221 Quaternion rot(eigenvectors.at<
float>(0, 0), eigenvectors.at<
float>(0, 1),
222 eigenvectors.at<
float>(0, 2), eigenvectors.at<
float>(0, 3));
223 cv::Mat RR = rot.getRotation();
225 cv::Mat T = Mu_m.t() - RR * Mu_s.t();
228 RT_4x4 = cv::Mat::eye(4, 4, CV_32F);
229 cv::Mat r33 = RT_4x4(cv::Range(0, 3), cv::Range(0, 3));
231 for (
int i = 0; i < 3; i++)
232 RT_4x4.at<
float>(i, 3) = T.ptr<
float>(0)[i];
237 float* matrix = RT_4x4.ptr<
float>(0);
238 for (
size_t i = 0; i < POrg.size(); i++)
240 cv::Point3f org = POrg[i];
241 cv::Point3f dest_est;
242 dest_est.x = matrix[0] * org.x + matrix[1] * org.y + matrix[2] * org.z + matrix[3];
243 dest_est.y = matrix[4] * org.x + matrix[5] * org.y + matrix[6] * org.z + matrix[7];
244 dest_est.z = matrix[8] * org.x + matrix[9] * org.y + matrix[10] * org.z + matrix[11];
245 cv::Point3f dest_real = PDst[i];
246 err +=
static_cast<float>(cv::norm(dest_est - dest_real));
249 return err / float(POrg.size());
255 inline double hubber(
double e,
double _delta)
257 double dsqr = _delta * _delta;
266 double sqrte = sqrt(e);
267 return 2 * sqrte * _delta - dsqr;
280 return 4.895303872 * sqrt(e) - 5.991;
285 return sqrt(
hubberMono(Information * SqErr) / SqErr);
287 template <
typename T>
289 const std::vector<cv::Point2f>& p2d,
const cv::Mat& cam_matrix,
290 const cv::Mat& dist, cv::Mat& r_io, cv::Mat& t_io)
292 assert(r_io.type() == CV_32F);
293 assert(t_io.type() == CV_32F);
294 assert(t_io.total() == r_io.total());
295 assert(t_io.total() == 3);
296 auto toSol = [](
const cv::Mat& r,
const cv::Mat& t)
299 for (
int i = 0; i < 3; i++)
301 sol(i) = r.ptr<
float>(0)[i];
302 sol(i + 3) = t.ptr<
float>(0)[i];
308 r.create(1, 3, CV_32F);
309 t.create(1, 3, CV_32F);
310 for (
int i = 0; i < 3; i++)
312 r.ptr<
float>(0)[i] = sol(i);
313 t.ptr<
float>(0)[i] = sol(i + 3);
320 std::vector<cv::Point2f> p2d_rej;
323 cv::projectPoints(p3d, r, t, cam_matrix, dist, p2d_rej, Jacb);
324 err.resize(p3d.size() * 2);
326 for (
size_t i = 0; i < p3d.size(); i++)
328 cv::Point2f errP = p2d_rej[i] - p2d[i];
330 double SqErr = (errP.x * errP.x + errP.y * errP.y);
333 err(err_idx++) = robuse_weight * errP.x;
334 err(err_idx++) = robuse_weight * errP.y;
338 Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>& J)
341 J.resize(p3d.size() * 2, 6);
342 for (
size_t i = 0; i < p3d.size() * 2; i++)
344 double* jacb = Jacb.ptr<
double>(i);
345 for (
int j = 0; j < 6; j++)
355 auto err = solver.
solve(sol, err_f, jac_f);
357 fromSol(sol, r_io, t_io);
362 const std::vector<cv::Point2f>& p2d,
const cv::Mat& cam_matrix,
363 const cv::Mat& dist, cv::Mat& r_io, cv::Mat& t_io)
365 #ifdef DOUBLE_PRECISION_PNP
366 return __aruco_solve_pnp<double>(p3d, p2d, cam_matrix, dist, r_io, t_io);
368 return __aruco_solve_pnp<float>(p3d, p2d, cam_matrix, dist, r_io, t_io);
373 float _msize,
float minerrorRatio)
381 double errorRatio = solutions[1].second / solutions[0].second;
382 if (errorRatio < minerrorRatio)
414 const MarkerMap& msconf,
float markerSize)
419 throw cv::Exception(9001,
"Invalid camera parameters",
420 "MarkerMapPoseTracker::setParams", __FILE__, __LINE__);
422 throw cv::Exception(9001,
"You should indicate the markersize since the MarkerMap is in pixels",
423 "MarkerMapPoseTracker::setParams", __FILE__, __LINE__);
425 throw cv::Exception(9001,
"Invalid MarkerMap",
"MarkerMapPoseTracker::setParams",
434 for (
auto m : msconf)
435 _map_mm.insert(std::make_pair(m.id, m));
453 std::vector<Marker> mapMarkers;
454 for (
auto marker : v_m)
457 mapMarkers.push_back(marker);
460 if (mapMarkers.size() == 0)
473 cv::Mat pose_f2g_out;
476 std::vector<minfo> good_marker_locations;
477 std::vector<minfo> all_marker_locations;
479 for (
const Marker& marker : mapMarkers)
486 mi.err = mpi[0].second;
487 mi.rt_f2m = mpi[0].first;
488 all_marker_locations.push_back(mi);
490 good_marker_locations.push_back(mi);
491 mi.rt_f2m = mpi[1].first;
492 mi.err = mpi[1].second;
493 all_marker_locations.push_back(mi);
497 if (mapMarkers.size() >= 2)
500 std::vector<cv::Point2f> markerPoints2d;
501 std::vector<cv::Point3f> markerPoints3d;
502 for (
const Marker& marker : mapMarkers)
504 markerPoints2d.insert(markerPoints2d.end(), marker.begin(), marker.end());
505 auto p3d =
_map_mm[marker.id].points;
506 markerPoints3d.insert(markerPoints3d.end(), p3d.begin(), p3d.end());
510 for (
auto& ml : all_marker_locations)
517 std::sort(all_marker_locations.begin(), all_marker_locations.end(),
518 [](
const minfo& a,
const minfo& b) { return a.err < b.err; });
520 auto& best = all_marker_locations.front();
521 pose_f2g_out = best.rt_f2m *
marker_m2g[best.id];
524 if (pose_f2g_out.empty() && good_marker_locations.size() > 0)
526 std::sort(good_marker_locations.begin(), good_marker_locations.end(),
527 [](
const minfo& a,
const minfo& b) { return a.err < b.err; });
528 auto best = good_marker_locations[0];
531 pose_f2g_out = best.rt_f2m *
marker_m2g[best.id];
538 std::vector<cv::Point2f> p2d;
539 std::vector<cv::Point3f> p3d;
540 for (
auto marker : v_m)
545 for (
auto p : marker)
547 for (
auto p :
_map_mm[marker.id].points)
566 if (InitialPose.empty())