点击上方“3D视觉工坊”,选择“星标”
干货第一时间送达
本文转载自uanheng
MEI模型是一个常见的鱼眼相机模型,下面试图解析VinsFusion使用的camera_models中的MEI模型.源码链接:CataCamera
(本文公式较多,建议在电脑端打开!!!)
(本文公式较多,建议在电脑端打开!!!)
(本文公式较多,建议在电脑端打开!!!)
MEI模型

对于此模型来说,核心就是在轴添加了一个偏移,这样可以使得水平摄入的光线也可以投影到图像的像素区域内,下面介绍三维世界中的点如何映射到像素坐标中,上图中的变量含义可以在下文中看到.
假定真实世界的点
对坐标进行归一化处理(映射到归一化球面坐标系中),坐标原点为.
对坐标原点在轴添加一个偏移,坐标原点为,新坐标为
对当前点进行坐标的归一化,由图可见此时归一化平面为,结果为
剩下的就是普通的针孔相机模型了,加上径向及切向畸变,畸变公式如下,其中下式中的为上一步的,为上一步的,也就是对归一化平面的坐标加上畸变.
最后将加了畸变模型的坐标通过相机内参投影到像素坐标系中,其中为相机在的焦距,为主点的坐标(像素坐标系原点相对于归一化平面原点的偏移).
spacetoplane函数解析
/**
* \brief Project a 3D point (\a x,\a y,\a z) to the image plane in (\a u,\a v)
*
* \param P 3D point coordinates
* \param p return value, contains the image point coordinates
*/
void
CataCamera::spaceToPlane(const Eigen::Vector3d& P, Eigen::Vector2d& p) const
{
Eigen::Vector2d p_u, p_d;
// 投影到归一化平面
double z = P(2) + mParameters.xi() * P.norm();
p_u << P(0) / z, P(1) / z;
if (m_noDistortion)
{
p_d = p_u;
}
else
{
// 使用畸变模型修正
Eigen::Vector2d d_u;
distortion(p_u, d_u);
p_d = p_u + d_u;
}
// 使用内参矩阵投影到像素坐标系
p << mParameters.gamma1() * p_d(0) + mParameters.u0(),
mParameters.gamma2() * p_d(1) + mParameters.v0();
}
可以看到,代码的操作与上述的流程基本一致,先将点的坐标变换到归一化平面,然后加上畸变模型,最后投影到相机坐标系.
liftSphere函数解析
已知的是像素坐标,要求的是归一化球面坐标系中的坐标(未偏移,坐标原点为).
那么首先根据相机内参将像素坐标变换为归一化平面坐标,然后对比归一化球面坐标系中的坐标与归一化平面坐标有
对于轴来说,差了一个系数,轴则是差了一个系数.所以理论上,只要求出既可结算出归一化球面坐标.
下面来求解
由上式有:
所以有:
然后进行恒等变换,如下所示:
解得的正根为:
在求解出之后,可以对归一化平面的坐标乘以就会得到归一化球面坐标(原点为),再对轴添加偏移即可得到归一化球面坐标(原点为)
乘以减去
/**
* \brief Lifts a point from the image plane to the unit sphere
*
* \param p image coordinates
* \param P coordinates of the point on the sphere
*/
void
CataCamera::liftSphere(const Eigen::Vector2d& p, Eigen::Vector3d& P) const
{
double mx_d, my_d,mx2_d, mxy_d, my2_d, mx_u, my_u;
double rho2_d, rho4_d, radDist_d, Dx_d, Dy_d, inv_denom_d;
double lambda;
// 投影到归一化平面
mx_d = m_inv_K11 * p(0) + m_inv_K13;
my_d = m_inv_K22 * p(1) + m_inv_K23;
if (m_noDistortion)
{
mx_u = mx_d;
my_u = my_d;
}
else
{
// 使用畸变模型修正
// Recursive distortion model
int n = 6;
Eigen::Vector2d d_u;
distortion(Eigen::Vector2d(mx_d, my_d), d_u);
// Approximate value
mx_u = mx_d - d_u(0);
my_u = my_d - d_u(1);
for (int i = 1; i < n; ++i)
{
distortion(Eigen::Vector2d(mx_u, my_u), d_u);
mx_u = mx_d - d_u(0);
my_u = my_d - d_u(1);
}
}
// 将归一化平面的点投影到归一化球坐标系中
double xi = mParameters.xi();
if (xi == 1.0)
{
lambda = 2.0 / (mx_u * mx_u + my_u * my_u + 1.0);
P << lambda * mx_u, lambda * my_u, lambda - 1.0;
}
else
{
lambda = (xi + sqrt(1.0 + (1.0 - xi * xi) * (mx_u * mx_u + my_u * my_u))) / (1.0 + mx_u * mx_u + my_u * my_u);
P << lambda * mx_u, lambda * my_u, lambda - xi;
}
}
liftproject函数
由上面可得
由于求的是射线,这里设定,并取
同时存在尺度相似性(两者的坐标差了一个系数),此射线上的所有点的归一化平面坐标均为,仿照上面对归一化平面坐标乘以并对偏移有:
也就是说
因此所求坐标为
/**
* \brief Lifts a point from the image plane to its projective ray
*
* \param p image coordinates
* \param P coordinates of the projective ray
*/
void
CataCamera::liftProjective(const Eigen::Vector2d& p, Eigen::Vector3d& P) const
{
double mx_d, my_d,mx2_d, mxy_d, my2_d, mx_u, my_u;
double rho2_d, rho4_d, radDist_d, Dx_d, Dy_d, inv_denom_d;
//double lambda;
// 投影到归一化平面
mx_d = m_inv_K11 * p(0) + m_inv_K13;
my_d = m_inv_K22 * p(1) + m_inv_K23;
if (m_noDistortion)
{
mx_u = mx_d;
my_u = my_d;
}
else
{
// 使用畸变模型修正
// Recursive distortion model
int n = 8;
Eigen::Vector2d d_u;
distortion(Eigen::Vector2d(mx_d, my_d), d_u);
// Approximate value
mx_u = mx_d - d_u(0);
my_u = my_d - d_u(1);
for (int i = 1; i < n; ++i)
{
distortion(Eigen::Vector2d(mx_u, my_u), d_u);
mx_u = mx_d - d_u(0);
my_u = my_d - d_u(1);
}
}
// 求射线的坐标
double xi = mParameters.xi();
if (xi == 1.0)
{
P << mx_u, my_u, (1.0 - mx_u * mx_u - my_u * my_u) / 2.0;
}
else
{
rho2_d = mx_u * mx_u + my_u * my_u;
P << mx_u, my_u, 1.0 - xi * (rho2_d + 1.0) / (xi + sqrt(1.0 + (1.0 - xi * xi) * rho2_d));
}
}
到此,我们已经通过相机内参,模型参数成功实现了三维点到像素坐标变换以及像素坐标到归一化球面,射线坐标变换.
本文仅做学术分享,如有侵权,请联系删文。
3D视觉精品课程推荐:
1.面向自动驾驶领域的多传感器数据融合技术
2.彻底搞透视觉三维重建:原理剖析、代码讲解、及优化改进
3.国内首个面向工业级实战的点云处理课程
4.激光-视觉-IMU-GPS融合SLAM算法梳理和代码讲解
5.彻底搞懂视觉-惯性SLAM:基于VINS-Fusion正式开课啦
6.彻底搞懂基于LOAM框架的3D激光SLAM: 源码剖析到算法优化
7.彻底剖析室内、室外激光SLAM关键算法原理、代码和实战(cartographer+LOAM +LIO-SAM)
干货领取:
1. 在「3D视觉工坊」公众号后台回复:3D视觉,即可下载 3D视觉相关资料干货,涉及相机标定、三维重建、立体视觉、SLAM、深度学习、点云后处理、多视图几何等方向。
2. 在「3D视觉工坊」公众号后台回复:3D视觉github资源汇总,即可下载包括结构光、标定源码、缺陷检测源码、深度估计与深度补全源码、点云处理相关源码、立体匹配源码、单目、双目3D检测、基于点云的3D检测、6D姿态估计源码汇总等。
3. 在「3D视觉工坊」公众号后台回复:相机标定,即可下载独家相机标定学习课件与视频网址;后台回复:立体匹配,即可下载独家立体匹配学习课件与视频网址。
重磅!3DCVer-学术论文写作投稿 交流群已成立
扫码添加小助手微信,可申请加入3D视觉工坊-学术论文写作与投稿 微信交流群,旨在交流顶会、顶刊、SCI、EI等写作与投稿事宜。
同时也可申请加入我们的细分方向交流群,目前主要有3D视觉、CV&深度学习、SLAM、三维重建、点云后处理、自动驾驶、多传感器融合、CV入门、三维测量、VR/AR、3D人脸识别、医疗影像、缺陷检测、行人重识别、目标跟踪、视觉产品落地、视觉竞赛、车牌识别、硬件选型、学术交流、求职交流、ORB-SLAM系列源码交流、深度估计等微信群。
一定要备注:研究方向+学校/公司+昵称,例如:”3D视觉 + 上海交大 + 静静“。请按照格式备注,可快速被通过且邀请进群。原创投稿也请联系。
▲长按加微信群或投稿
▲长按关注公众号
3D视觉从入门到精通知识星球:针对3D视觉领域的视频课程(三维重建系列三维点云系列结构光系列、手眼标定、相机标定、orb-slam3知识点汇总、入门进阶学习路线、最新paper分享、疑问解答五个方面进行深耕,更有各类大厂的算法工程人员进行技术指导。与此同时,星球将联合知名企业发布3D视觉相关算法开发岗位以及项目对接信息,打造成集技术与就业为一体的铁杆粉丝聚集区,近2000星球成员为创造更好的AI世界共同进步,知识星球入口:
学习3D视觉核心技术,扫描查看介绍,3天内无条件退款
圈里有高质量教程资料、答疑解惑、助你高效解决问题
觉得有用,麻烦给个赞和在看~