Calibration Library 1.0.0
A C++ library for camera calibration and vision-related geometric transformations
Loading...
Searching...
No Matches
planarpose.h
Go to the documentation of this file.
1
4#pragma once
5
6// std
7#include <algorithm>
8#include <cmath>
9#include <numeric>
10#include <stdexcept>
11#include <vector>
12
13// eigen
14#include <Eigen/Geometry>
15
19
20namespace calib {
21
23 Eigen::Vector2d object_xy; // Planar target coordinates (Z=0)
24 Eigen::Vector2d image_uv; // Corresponding pixel measurements
25};
26using PlanarView = std::vector<PlanarObservation>;
27
29
30// Decompose homography in normalized camera coords: H = [r1 r2 t]
31auto pose_from_homography_normalized(const Eigen::Matrix3d& hmtx) -> Eigen::Isometry3d;
32
33// Convenience: one-shot planar pose from pixels & kmtx
34auto estimate_planar_pose(PlanarView view, const CameraMatrix& intrinsics) -> Eigen::Isometry3d;
35
36// Generic overload: estimate planar pose for an arbitrary camera_model by
37// normalizing pixel coordinates via the camera's intrinsics.
38template <camera_model CameraT>
39auto estimate_planar_pose(PlanarView view, const CameraT& camera) -> Eigen::Isometry3d {
40 if (view.size() < 4) {
41 return Eigen::Isometry3d::Identity();
42 }
43
44 // Normalize image coordinates using the camera's intrinsics only
45 std::for_each(view.begin(), view.end(), [&camera](PlanarObservation& obs) {
46 obs.image_uv = camera.template apply_intrinsics<double>(obs.image_uv);
47 });
48
49 // Estimate a homography using a simple normalized DLT and recover pose
50 auto normalize_points_2d = [](const std::vector<Eigen::Vector2d>& pts,
51 std::vector<Eigen::Vector2d>& out) -> Eigen::Matrix3d {
52 out.resize(pts.size());
53 const Eigen::Vector2d centroid =
54 std::accumulate(pts.begin(), pts.end(), Eigen::Vector2d{0, 0}) /
55 std::max<size_t>(1, pts.size());
56 const double mean_dist = std::accumulate(pts.begin(), pts.end(), 0.0,
57 [&centroid](double sum, const Eigen::Vector2d& p) {
58 return sum + (p - centroid).norm();
59 }) /
60 static_cast<double>(std::max<size_t>(1, pts.size()));
61 const double sigma = (mean_dist > 0) ? std::sqrt(2.0) / mean_dist : 1.0;
62
63 Eigen::Matrix3d transform = Eigen::Matrix3d::Identity();
64 transform(0, 0) = sigma;
65 transform(1, 1) = sigma;
66 transform(0, 2) = -sigma * centroid.x();
67 transform(1, 2) = -sigma * centroid.y();
68
69 std::transform(pts.begin(), pts.end(), out.begin(),
70 [&transform](const Eigen::Vector2d& pt) -> Eigen::Vector2d {
71 Eigen::Vector3d hp(pt.x(), pt.y(), 1.0);
72 Eigen::Vector3d hn = transform * hp;
73 return hn.hnormalized();
74 });
75 return transform;
76 };
77
78 std::vector<Eigen::Vector2d> src_xy;
79 std::vector<Eigen::Vector2d> dst_uv;
80 src_xy.reserve(view.size());
81 dst_uv.reserve(view.size());
82 for (const auto& obs : view) {
83 src_xy.push_back(obs.object_xy);
84 dst_uv.push_back(obs.image_uv);
85 }
86
87 std::vector<Eigen::Vector2d> src_n, dst_n;
88 const Eigen::Matrix3d Tsrc = normalize_points_2d(src_xy, src_n);
89 const Eigen::Matrix3d Tdst = normalize_points_2d(dst_uv, dst_n);
90
91 const auto npts = static_cast<Eigen::Index>(src_n.size());
92 Eigen::MatrixXd A(2 * npts, 9);
93 for (Eigen::Index i = 0; i < npts; ++i) {
94 const double x = src_n[i].x();
95 const double y = src_n[i].y();
96 const double u = dst_n[i].x();
97 const double v = dst_n[i].y();
98 A.row(2 * i) << -x, -y, -1, 0, 0, 0, u * x, u * y, u;
99 A.row(2 * i + 1) << 0, 0, 0, -x, -y, -1, v * x, v * y, v;
100 }
101 Eigen::JacobiSVD<Eigen::MatrixXd> svd(A, Eigen::ComputeFullV);
102 Eigen::VectorXd h = svd.matrixV().col(8);
103 Eigen::Matrix3d Hnorm;
104 Hnorm << h(0), h(1), h(2), h(3), h(4), h(5), h(6), h(7), h(8);
105 Eigen::Matrix3d hmtx = Tdst.inverse() * Hnorm * Tsrc;
106 if (std::abs(hmtx(2, 2)) > 1e-15) {
107 hmtx /= hmtx(2, 2);
108 }
110}
111
112} // namespace calib
Linear multi-camera extrinsics initialisation (DLT)
auto estimate_planar_pose(PlanarView view, const CameraMatrix &intrinsics) -> Eigen::Isometry3d
static auto normalize_points_2d(const std::vector< Eigen::Vector2d > &pts, std::vector< Eigen::Vector2d > &out) -> Eigen::Matrix3d
std::vector< PlanarObservation > PlanarView
Definition planarpose.h:26
auto pose_from_homography_normalized(const Eigen::Matrix3d &hmtx) -> Eigen::Isometry3d
Eigen::Vector2d object_xy
Definition planarpose.h:23
Eigen::Vector2d image_uv
Definition planarpose.h:24