Calibration Library 1.0.0
A C++ library for camera calibration and vision-related geometric transformations
Loading...
Searching...
No Matches
planefit.cpp
Go to the documentation of this file.
2
3#include <Eigen/Geometry>
4#include <optional>
5#include <span>
6
7namespace {
8
9struct PlaneRansacEstimator final {
10 using Datum = Eigen::Vector3d;
11 using Model = Eigen::Vector4d;
12 static constexpr std::size_t k_min_samples = 3;
13
14 static auto fit(const std::vector<Datum>& data, std::span<const int> sample)
15 -> std::optional<Model> {
16 if (sample.size() < k_min_samples) {
17 return std::nullopt;
18 }
19 const Eigen::Vector3d& p0 = data[static_cast<std::size_t>(sample[0])];
20 const Eigen::Vector3d& p1 = data[static_cast<std::size_t>(sample[1])];
21 const Eigen::Vector3d& p2 = data[static_cast<std::size_t>(sample[2])];
22
23 const Eigen::Vector3d v1 = p1 - p0;
24 const Eigen::Vector3d v2 = p2 - p0;
25 Eigen::Vector3d normal = v1.cross(v2);
26 const double norm = normal.norm();
27 if (norm < 1e-12) {
28 return std::nullopt;
29 }
30 normal /= norm;
31 const double d = -normal.dot(p0);
32 return Model{normal.x(), normal.y(), normal.z(), d};
33 }
34
35 static auto residual(const Model& plane, const Datum& point) -> double {
36 const Eigen::Vector3d normal = plane.head<3>();
37 return std::abs(normal.dot(point) + plane[3]);
38 }
39
40 static auto refit(const std::vector<Datum>& data, std::span<const int> inliers)
41 -> std::optional<Model> {
42 if (inliers.size() < static_cast<std::ptrdiff_t>(k_min_samples)) {
43 return std::nullopt;
44 }
45 std::vector<Eigen::Vector3d> pts(inliers.size());
46 std::transform(inliers.begin(), inliers.end(), pts.begin(),
47 [&data](int idx) { return data[static_cast<std::size_t>(idx)]; });
48 return calib::fit_plane_svd(pts);
49 }
50
51 static auto is_degenerate(const std::vector<Datum>& data, std::span<const int> sample) -> bool {
52 if (sample.size() < k_min_samples) {
53 return true;
54 }
55 const Eigen::Vector3d& p0 = data[static_cast<std::size_t>(sample[0])];
56 const Eigen::Vector3d& p1 = data[static_cast<std::size_t>(sample[1])];
57 const Eigen::Vector3d& p2 = data[static_cast<std::size_t>(sample[2])];
58 const Eigen::Vector3d v1 = p1 - p0;
59 const Eigen::Vector3d v2 = p2 - p0;
60 return v1.cross(v2).norm() < 1e-12;
61 }
62};
63
64} // namespace
65
66namespace calib {
67
68auto fit_plane_svd(const std::vector<Eigen::Vector3d>& pts) -> Eigen::Vector4d {
69 if (pts.size() < 3) {
70 throw std::invalid_argument("Not enough points to fit a plane");
71 }
72
73 const Eigen::Vector3d centroid =
74 std::accumulate(pts.begin(), pts.end(), Eigen::Vector3d(Eigen::Vector3d::Zero())) /
75 static_cast<double>(pts.size());
76 Eigen::MatrixXd A(static_cast<Eigen::Index>(pts.size()), 3);
77 for (size_t i = 0; i < pts.size(); ++i) {
78 A.row(static_cast<Eigen::Index>(i)) = (pts[i] - centroid).transpose();
79 }
80 Eigen::JacobiSVD<Eigen::MatrixXd> svd(A, Eigen::ComputeFullV);
81 Eigen::Vector3d normal = svd.matrixV().col(2);
82 double d = -normal.dot(centroid);
83 const double nrm = normal.norm();
84 return {normal.x() / nrm, normal.y() / nrm, normal.z() / nrm, d / nrm};
85}
86
87auto fit_plane_ransac(const std::vector<Eigen::Vector3d>& pts, const RansacOptions& opts)
89 PlaneRansacResult result;
90 if (pts.size() < PlaneRansacEstimator::k_min_samples) {
91 return result;
92 }
93
94 auto ransac_res = ransac<PlaneRansacEstimator>(pts, opts);
95 if (!ransac_res.success) {
96 return result;
97 }
98
99 result.success = true;
100 result.plane = ransac_res.model;
101 result.inliers = std::move(ransac_res.inliers);
102 result.inlier_rms = ransac_res.inlier_rms;
103 return result;
104}
105
106} // namespace calib
Linear multi-camera extrinsics initialisation (DLT)
HomographyEstimator::Datum Datum
auto fit_plane_ransac(const std::vector< Eigen::Vector3d > &pts, const RansacOptions &opts={}) -> PlaneRansacResult
Definition planefit.cpp:87
HomographyEstimator::Model Model
auto fit_plane_svd(const std::vector< Eigen::Vector3d > &pts) -> Eigen::Vector4d
Definition planefit.cpp:68
Eigen::Vector4d plane
Definition planefit.h:16
std::vector< int > inliers
Definition planefit.h:17