当前位置: 首页 > news >正文

鱼眼相机模型

鱼眼相机模型

  最近涉及鱼眼相机模型、标定使用等,作为记录,更新很久不曾更新的博客。

文章目录

  • 鱼眼相机模型
  • 1 相机成像
  • 2 鱼眼模型
  • 3 畸变
    • 3.1 适用针孔和MEI
    • 3.2 Kannala-Brandt鱼眼模型
  • 4 代码实现

1 相机成像

针孔相机:所有光线从一个孔(光心)透过,入射角θ\thetaθ = 出射角θd\theta_{d}θd。0-180°的光线汇聚的图像是无穷大的,所以针孔相机的视场角一般都很小。

鱼眼相机:类似于凸透镜成像,光线被聚集,入射角θ\thetaθ > 出射角θd\theta_{d}θd。光线汇聚的图像变小,所以鱼眼相机的视场角一般可以达到18-270°。

在这里插入图片描述

2 鱼眼模型

常见模型,注意,这里的θ\thetaθ是入射角!!θd\theta_{d}θd才是出射角。

在这里插入图片描述

VINSAVP-SLAM中采用的MEI模型--------

在这里插入图片描述

注意,常规鱼眼模型的去畸变和针孔相机不同,可以见opencv中解释;但是MEI模型经过变换后,可以直接套用针孔相机模型

3 畸变

畸变包括径向畸变(Radial Distortion)和切向畸变(Tangential Distortion

鱼眼相机本质是利用了相机的畸变获取无穷远处的投影,主要是径向畸变

在这里插入图片描述

3.1 适用针孔和MEI

首先来看下去畸变的本质,如图所示,一共是四步

① 相机坐标系下某一点,是投影到光心矢量射线(相机成像原理),与图像产生交点。归一化这个坐标(如果再乘以焦距就是图像坐标系上的坐标了),获取畸变的xy。(这里为什么不乘以f呢,本质是矫正这一条投影到光心的矢量射线,没有本质区别,归一化计算更简单)

② 计算成像半径r(相机成像半径r理论为r=f*tan(θd),3.2中有提到,也有图)

③ 基于畸变参数,计算去畸变后的xy,此时,该点再图像坐标系中的位置被矫正

④ 然后基于去畸变后的xy再变换到像素坐标系下,就可以获取一个矫正的像素坐标

在这里插入图片描述

但是实际上,我们只知道像素坐标,而非相机系坐标!所以实际中将像素坐标反变换到相机坐标系(归一化),然后就可以按照这里的去畸变流程处理了。

​ opencv中的MEI描述

3.2 Kannala-Brandt鱼眼模型

参考opencv,注意,通用模型不是上面哪些等距模型,和哪些完全没关系

相机系

Xc=RX+tXc = RX + t Xc=RX+t

把相机系坐标单独取出来

x=Xc1y=Xc2z=Xc3x = Xc_1\\ y = Xc_2\\ z = Xc_3 x=Xc1y=Xc2z=Xc3

归一化,计算成像半径、夹角

a=xzandb=yzr2=a2+b2θ=arctan⁡(r/1)a = \frac{x}{z} \quad \text{and} \quad b = \frac{y}{z} \quad r^2 = a^2 + b^2 \quad \theta = \arctan(r/1) a=zxandb=zyr2=a2+b2θ=arctan(r/1)

去畸变,注意这里的θdr\frac{\theta_d}{r}rθd实际代码是rdr\frac{r_d}{r}rrd获取的一个比例关系,opencv给出的公式有点误导,可以参考原始论文(成像半径rd=f∗tan(θd)≈f∗θdr_{d} = f*tan(\theta_{d}) ≈ f* \theta_{d}rd=ftan(θd)fθd,归一化,取f=1tanxx接近0时候约等于x

θd=θ(1+k1θ2+k2θ4+k3θ6+k4θ8)x′=(θdr)ay′=(θdr)b\theta_d = \theta (1 + k_1 \theta^2 + k_2 \theta^4 + k_3 \theta^6 + k_4 \theta^8) \\ x' = \left(\frac{\theta_d}{r}\right) a \\ y' = \left(\frac{\theta_d}{r}\right) b θd=θ(1+k1θ2+k2θ4+k3θ6+k4θ8)x=(rθd)ay=(rθd)b

获取去畸变后的像素坐标(α是偏斜系数,默认为0)

u=fx(x′+αy′)+cxv=fyy′+cyu = f_x (x' + \alpha y') + c_x \\ v = f_y y' + c_y u=fx(x+αy)+cxv=fyy+cy

注:通过上述模型,也就是棋盘格标定得到的去畸变图像,相对于原图,会小很多!距离中心越远的区域,拉伸会很严重,校正后会被切除

4 代码实现

可以参考opencv中映射矩阵来实现

bool UnDistortMap()
{if(is_init){return true;}// 畸变映射,每一张图像的畸变映射是一致的cv::fisheye::initUndistortRectifyMap(mK, mD, cv::Matx33d::eye(), mK,cv::Size(Width, Height), CV_16SC2, m_undistortMapX, m_undistortMapY);// 通过调整cx,cy来增大去畸变后的视野// cv::fisheye::initUndistortRectifyMap(mK, mD, cv::Matx33d::eye(), mK,//                                     cv::Size(mK.at<double>(0,2), mK.at<double>(1,2)), CV_16SC2, //                                    m_undistortMapX, m_undistortMapY);    // 或者直接把fxfy调小,缩小相机焦距,视野变大了(分辨率dx不变)                               if (m_undistortMapX.empty() || m_undistortMapY.empty()) {std::cerr << "Failed to compute undistort maps!" << std::endl;return false;}else{}is_init = true;return true;
}bool undistortImage(const cv::Mat& src, cv::Mat& dst)
{if(!is_init)return false;cv::remap(src, dst, m_undistortMapX, m_undistortMapY, cv::INTER_LINEAR); // 去畸变return true;
}
Computes undistortion and rectification maps for image transform by cv::remap(). If D is empty zero distortion is used, if R or P is empty identity matrixes are used.Parameters:
K – Camera matrix \f$K = \vecthreethree{f_x}{0}{c_x}{0}{f_y}{c_y}{0}{0}{_1}.
D – Input vector of distortion coefficients k_1, k_2, k_3, k_4).
R – Rectification transformation in the object space: 3x3 1-channel, or vector: 3x1/1x3 1-channel or 1x1 3-channel
P – New camera matrix (3x3) or new projection matrix (3x4)
size – Undistorted image size.
m1type – Type of the first output map that can be CV_32FC1 or CV_16SC2 . See convertMaps() for details.
map1 – The first output map.
map2 – The second output map.
http://www.xdnf.cn/news/1486459.html

相关文章:

  • JVM-默背版
  • 实验室服务器配置|通过Docker实现Linux系统多用户隔离与安全防控
  • Flink NetworkBufferPool核心原理解析
  • Android --- SystemUI 导入Android Studio及debug
  • 2025年体制内职业发展相关认证选择指南
  • 超越自动补全:将AI编码助手深度集成到你的开发工作流​​
  • 微信小程序中实现AI对话、生成3D图像并使用xr-frame演示
  • C++ 连接 Redis:redis-plus-plus 安装与使用入门指南
  • 关于npm的钩子函数
  • 【iOS】push,pop和present,dismiss
  • 上架商品合规流程有多条,有的长,有的短,有的需要审核,校验商品的合规性
  • RestTemplate使用 | RestTemplate设置http连接池参数
  • axios的两种异步方式对比
  • K8S-Pod(下)
  • 笔记本、平板如何成为电脑拓展屏?向日葵16成为副屏功能一键实现
  • python---静态方法和类方法
  • Python学习——安装配置python环境+入门
  • Onecode 可视化动作揭秘系列二:组件类型个性化配置技术协议
  • 嵌入式解谜日志之数据结构—基本概念
  • 插入排序与希尔排序
  • Python3使用Flask开发Web项目新手入门开发文档
  • JavaEE 进阶第三期:开启前端入门之旅(三)
  • 数据结构——排序
  • 内网后渗透攻击--linux系统(权限维持)
  • MySQL 8.0+ 内核剖析:架构、事务与数据管理
  • thinkphp和vue基于Workerman搭建Websocket服务实现用户实时聊天,完整前后端源码demo及数据表sql
  • 20250907_梳理异地备份每日自动巡检py脚本逻辑流程+安装Python+PyCharm+配置自动运行
  • 什么叫进件?在第三方支付行业里,这是一个非常专业的词汇。
  • Linux驱动开发(1)环境与代码框架
  • Linux —— 虚拟进程地址空间