【三维重建】相机模型以及坐标转换
理论内容:立体视觉入门指南(1):坐标系与相机参数
代码出处
练习作业
- 世界坐标系到相机坐标系的转换 W2C
- 相机坐标系到世界坐标系的转换 C2W
- 相机坐标系到图像坐标系的转换 C2I
- 世界坐标系到图像坐标系的转换 W2I
- 有深度作为参数,图像坐标系到相机坐标系的转换I2C
- 有深度作为参数,图像坐标系到世界坐标系的转换I2W
照着代码抄了一下,其中比如RT_
转置矩阵,相机坐标系转换到世界坐标系
感觉原代码不对,自己按照自己的理解做了更正。
#ifndef SV3D_CAMERA_H
#define SV3D_CAMERA_H
#include "eigen_defs.h"
namespace sv3d
{
class Camera
{
public:
Mat3 K_; // 内参矩阵
Mat3 R_; // 旋转矩阵
Vec3 t_; // 平移矩阵
Mat34 P_; // 投影矩阵
Mat3 KI_; // 内参矩阵的逆矩阵
Mat3 RT_; // 旋转矩阵的转置矩阵
public:
inline Camera() = default;
inline ~Camera() = default;
// 通过K、R、t来构造相机,注意用了移动语义避免复制操作,传入的参数在执行构造函数后内存销毁
inline Camera(Mat3 K, Mat3 R, Vec3 t) : K_(std::move(K)), R_(std::move(R)), t_(std::move(t))
{
KI_ = K_.inverse();
RT_ = R_.transpose();
P_ << K_ * R_, K_ * t_;
}
// 相机坐标系转换到世界坐标系
inline Vec3 TransformPointC2W(const Vec3 &X) const
{
return R_.inverse() * (X - t_);
}
// 世界坐标系转换到相机坐标系
inline Vec3 TransformPointW2C(const Vec3 &X) const
{
return R_ * X + t_;
}
// 相机坐标系转到影像坐标系
inline Vec2 TransformPointC2I(const Vec3 &X) const
{
auto I = Vec3(K_ * X);
return Vec2(I[0] / I[2], I[1] / I[2]); // 归一化
}
// 世界坐标系到影像坐标系
inline Vec2 TransformPointW2I(const Vec3 &X) const
{
return TransformPointC2I(TransformPointW2C(X));
}
// 影像坐标系转换到相机坐标系(深度已知 X[2])
inline Vec3 TransformPointI2C(const Vec3 &X) const
{
auto Xt = X;
Xt[0] *= Xt[2];
Xt[1] *= Xt[2];
return KI_ * Xt;
}
// 影像坐标系转换到世界坐标系(深度已知:X[2])
inline Vec3 TransformPointI2W(const Vec3 &X) const
{
return TransformPointC2W(TransformPointI2C(X));
}
}
}
#endif
eigen_defs.h
/* -*-c++-*- StereoV3D - Copyright (C) 2021.
* Author : Ethan Li<ethan.li.whu@gmail.com>
* https://github.com/ethan-li-coding/StereoV3DCode
*/
#ifndef SV3D_EIGEN_DEFS_H
#define SV3D_EIGEN_DEFS_H
#include <Eigen/Core>
#include <Eigen/Dense>
using namespace Eigen;
namespace sv3d
{
// 3d 矢量 (double类型)
using Vec2 = Eigen::Vector2d;
/// 2d 矢量 (float类型)
using Vec2f = Eigen::Vector2f;
// 3d 矢量 (double类型)
using Vec3 = Eigen::Vector3d;
// 3d 矢量 (float类型)
using Vec3f = Eigen::Vector3f;
/// 4d 矢量
using Vec4 = Eigen::Vector4d;
// 9d 矢量
using Vec9 = Eigen::Matrix<double, 9, 1>;
// 3x3 矩阵 (double类型)
using Mat3 = Eigen::Matrix<double, 3, 3>;
// 3x4 矩阵 (double类型)
using Mat34 = Eigen::Matrix<double, 3, 4>;
// 3x3 矩阵 (double类型)(行主序)
using RMat3 = Eigen::Matrix<double, 3, 3, Eigen::RowMajor>;
// 3x4 矩阵 (double类型)
using RMat34 = Eigen::Matrix<double, 3, 4, Eigen::RowMajor>;
// 4x4 矩阵 (double类型)
using Mat4 = Eigen::Matrix<double, 4, 4>;
// 2xN 矩阵 (double类型)
using Mat2X = Eigen::Matrix<double, 2, Eigen::Dynamic>;
// 3xN 矩阵 (double类型)
using Mat3X = Eigen::Matrix<double, 3, Eigen::Dynamic>;
// Nx9 矩阵 (double类型)
using MatX9 = Eigen::Matrix<double, Eigen::Dynamic, 9>;
// Nx9 矩阵 (double类型)(行主序)
using RMatX9 = Eigen::Matrix<double, Eigen::Dynamic, 9, Eigen::RowMajor>;
// NxM 矩阵 (double类型)
using MatXX = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>;
// NxM 矩阵 (double类型)(行主序)
using RMatXX = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
}
#endif
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!