深蓝学院自主泊车第3次作业-IPM

目录

  • 1 题目介绍
  • 2 求解

1 题目介绍

已知鱼眼相机的参数,

  1. image_width,表示图像的宽度
  2. image_height,表示图像的高度
  3. ξ \xi ξ,表示鱼眼相机参数
  4. k 1 k_1 k1 k 2 k_2 k2,表示径向相机参数
  5. p 1 p_1 p1 p 2 p_2 p2,表示切向相机参数
  6. f x f_x fx f y f_y fy,表示相机的焦距
  7. c x c_x cx c y c_y cy,表示相机的光心

已知相机坐标系到车体坐标系的变换矩阵,

  1. t t t,表示平移向量
  2. R R R,表示旋转矩阵

给出4组这样的参数及相应的图片,请求解最终的IPM图片。

2 求解

(1)设置最终IPM图像的尺寸为 1000 × 1000 1000\times 1000 1000×1000(用符号 i p m _ i m g _ h × i p m _ i m g _ w ipm\_img\_h\times ipm\_img\_w ipm_img_h×ipm_img_w表示),其中每个像素的长度和宽度为0.02米(用符号 p i x e l _ s c a l e _ pixel\_scale\_ pixel_scale_表示)。

(2)遍历IPM图像中的每个像素 ( u , v ) (u,v) (u,v),那么可以直到机体坐标系的点的坐标值为,
p v = [ − ( 0.5 ⋅ i p m _ i m g _ h − u ) ∗ p i x e l _ s c a l e 0.5 ⋅ ( i p m _ i m g _ w − v ) ⋅ p i x e l _ s c a l e 0 ] (1) p_v = \begin{bmatrix}-(0.5 \cdot ipm\_img\_h - u) * pixel\_scale \\ 0.5 \cdot (ipm\_img\_w - v) \cdot pixel\_scale \\ 0 \end{bmatrix} \tag{1} pv= (0.5ipm_img_hu)pixel_scale0.5(ipm_img_wv)pixel_scale0 (1)
(3)求得在相机坐标系下的坐标值为,
p c = R T ⋅ p v − R T ⋅ t (2) p_c = R^T \cdot p_v - R^T \cdot t \tag{2} pc=RTpvRTt(2)

p c p_c pc归一化操作,得到 p c _ n o r m p_{c\_norm} pc_norm

(4)此时,得到单位平面上的点 ( x 1 , y 1 ) (x_1,y_1) (x1,y1)
x 1 = p c _ n o r m [ 0 ] p c _ n o r m [ 2 ] + ξ y 1 = p c _ n o r m [ 1 ] p c _ n o r m [ 2 ] + ξ (3) \begin{align} x_1 = \frac{p_{c\_norm}[0]} { p_{c\_norm}[2] + \xi} \\ y_1 = \frac{p_{c\_norm}[1]} { p_{c\_norm}[2] + \xi} \end{align} \tag{3} x1=pc_norm[2]+ξpc_norm[0]y1=pc_norm[2]+ξpc_norm[1](3)

(5)得到畸变后的点 ( x 2 , y 2 ) (x_2,y_2) (x2,y2)
r = x 1 2 + y 1 2 x 2 = x 1 ( 1 + k 1 r 2 + k 2 r 4 ) + 2 p 1 x 1 y 1 + p 2 ( r 2 + 2 x 1 2 ) y 2 = y 1 ( 1 + k 1 r 2 + k 2 r 4 ) + p 1 ( r 2 + 2 y 1 2 ) + 2 p 2 x 1 y 1 (4) \begin{align} r &= \sqrt{x_1^2 + y_1^2} \\ x_2 &= x_1 (1 + k_1 r^2 + k_2 r^4) + 2 p_1 x_1 y_1 + p_2(r^2+2x_1^2) \\ y_2 &= y_1 (1 + k_1r^2+k_2r^4) + p_1(r^2+2y_1^2) + 2p_2x_1y_1 \end{align} \tag{4} rx2y2=x12+y12 =x1(1+k1r2+k2r4)+2p1x1y1+p2(r2+2x12)=y1(1+k1r2+k2r4)+p1(r2+2y12)+2p2x1y1(4)

(6)将点 ( x 2 , y 2 ) (x_2,y_2) (x2,y2)投影到图像坐标系,得到 ( u 1 , v 1 ) (u_1,v_1) (u1,v1)
u 1 = f x x 2 + c x v 1 = f y y 2 + c y (5) \begin{align} u_1 &= f_x x_2 + c_x \\ v_1 &= f_y y_2 + c_y \end{align} \tag{5} u1v1=fxx2+cx=fyy2+cy(5)
将鱼眼相机中的点 ( u 1 , v 1 ) (u_1,v_1) (u1,v1)的颜色赋给IPM图像中的 ( u . v ) (u.v) (u.v)坐标。

此处需要注意:

tip1: 获取颜色时需要四舍五入 u 1 u_1 u1 v 1 v_1 v1

tip2: 如果IPM图像中 ( u , v ) (u,v) (u,v)坐标已经被赋予了颜色信息,记录它的次数,那么最终的颜色值通过次数来加权平均,
c o l o r = t o t a l − 1 t o t a l ⋅ c o l o r + 1 t o t a l ⋅ n e w _ c o l o r (6) color = \frac{total-1}{total} \cdot color + \frac{1}{total} \cdot new\_color \tag{6} color=totaltotal1color+total1new_color(6)

最终的代码如下,

cv::Mat IPM::GenerateIPMImage(const std::vector<cv::Mat>& images) const {// Initialize a black IPM image with dimensions ipm_img_h_ x ipm_img_w_ and 3 channels (RGB)cv::Mat ipm_image = cv::Mat::zeros(ipm_img_h_, ipm_img_w_, CV_8UC3);std::vector<std::vector<int>> uv_cnt(ipm_img_h_, std::vector<int>(ipm_img_w_, 0)); // Check if the number of input images matches the number of camerasif (images.size() != cameras_.size()) {// If not, print an error message and return the initialized black IPM imagestd::cout << "IPM not init normaly !" << std::endl;return ipm_image;}// Iterate over each pixel in the IPM imagefor (int u = 0; u < ipm_img_w_; ++u) {for (int v = 0; v < ipm_img_h_; ++v) {// Calculate the point p_v in vehicle coordinates, p_v is corresponding to the current pixel (u, v).// Assume the height of the ipm_image in vehicle coordinate is 0.Eigen::Vector3d p_v(-(0.5 * ipm_img_h_ - u) * pixel_scale_,(0.5 * ipm_img_w_ - v) * pixel_scale_, 0);// Iterate over each camerafor (size_t i = 0; i < cameras_.size(); ++i) {// Project the vehile point p_v into the image plane uvTODO begin/////将vehicle系下的点转到camera系下Eigen::Vector3d p_c = cameras_[i].T_vehicle_cam_.inverse() * p_v;// Eigen::Maxtrix3d R1 = cameras_[i].T_vehicle_cam_.linear();// Eigen::Vector3d t1 = cameras_[i].translation();if (p_c[2] < 0.0) { //过滤z值小于0的点continue;}//将camera系下的点转到图像系下 Eigen::Vector3d norm_p_c = p_c.normalized();norm_p_c[2] += cameras_[i].xi_;//unit plane上的点(x1,y1)double x1 = norm_p_c[0] / norm_p_c[2];double y1 = norm_p_c[1] / norm_p_c[2];double r_2 = x1 * x1 + y1 * y1;//获取参数k1,k2,p1,p2double k1 = cameras_[i].D_.at<double>(0, 0);double k2 = cameras_[i].D_.at<double>(1, 0);double p1 = cameras_[i].D_.at<double>(2, 0);double p2 = cameras_[i].D_.at<double>(3, 0);//畸变后的点(x2,y2)double x2 = x1 * (1 + k1 * r_2 + k2 * r_2 * r_2) + 2.0 * p1 * x1 * y1 + p2 * (r_2 + 2 * x1 * x1);double y2 = y1 * (1 + k1 * r_2 + k2 * r_2 * r_2) + p1 * (r_2 + 2 * y1 * y1) + 2.0 * p2 * x1 * y1;//获取参数fx,fy,cx,cydouble fx = cameras_[i].K_.at<double>(0, 0);double fy = cameras_[i].K_.at<double>(1, 1);double cx = cameras_[i].K_.at<double>(0, 2);double cy = cameras_[i].K_.at<double>(1, 2);//图像坐标系下的点(u1,v1)double u1 = fx * x2 + cx;double v1 = fy * y2 + cy;//四舍五入,得到最终的uv0,uv1int uv0 = static_cast<int>(std::round(u1));int uv1 = static_cast<int>(std::round(v1)); TODO end/// (uv0, uv1) is the projected pixel from p_v to cameras_[i]// Skip this point if the projected coordinates are out of bounds of the camera imageif (uv0 < 0 || uv0 >= cameras_[i].width_ || uv1 < 0 ||uv1 >= cameras_[i].height_) {continue;}// Get the pixel color from the camera image and set it to the IPM image// If the IPM image pixel is still black (not yet filled), directly assign the colorif (ipm_image.at<cv::Vec3b>(v, u) == cv::Vec3b(0, 0, 0)) {ipm_image.at<cv::Vec3b>(v, u) = images[i].at<cv::Vec3b>(uv1, uv0);uv_cnt[v][u] += 1;} else {// Otherwise, average the existing color with the new coloruv_cnt[v][u] += 1;double total = 1.0 * uv_cnt[v][u]; ipm_image.at<cv::Vec3b>(v, u) = (total - 1.0) / total * ipm_image.at<cv::Vec3b>(v, u) + 1.0 / total * images[i].at<cv::Vec3b>(uv1, uv0); }}}}// Return the generated IPM imagereturn ipm_image;
}

最终的IPM图像如下,

在这里插入图片描述

给出的参考IPM图像如下,

在这里插入图片描述

本方法得到的IPM图像有更清晰的停车位线!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/22463.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中兴G7615AV5

参考文献&#xff1a; G7615AV5 光猫新版固件通过修改备份配置文件固化Telnet 中兴7615AV5光猫配置指南 前言&#xff1a;&#xff08;不如咸鱼30远程全权搞定&#xff0c;花小钱办大事&#xff09;截至2025年2月22号&#xff0c;这个设备开启Telnet只能去咸鱼找别人远程开&…

记录:Docker 安装记录

今天在安装 ollama 时发现无法指定安装目录&#xff0c;而且它的命令行反馈内容很像 docker &#xff0c;而且它下载的模型也是放在 C 盘&#xff0c;那么如果我 C 盘空间不足&#xff0c;就装不了 deepseek-r1:70b &#xff0c;于是想起来之前安装 Docker 的时候也遇到过类似问…

大数据学习之任务流调度系统Azkaban、Superset可视化系统

一.任务流调度系统Azkaban 1.课程介绍 2.为什么需要工作流调度系统 3.AZKABAN是什么 4.AZKABAN下载 5.制作安装包 6.tar包准备 7.MYSQL配置AZKABAN 8.配置EXECUTOR SERVER 9.配置WEBSERVER 10.单作业实战_yaml语言(今天稍晚更新) 11.单作业实战 12.多作业依赖实战 13.失败自动重…

PiscTrace的开发者版

基于 PiscTrace 架构的视图处理的纯开发板&#xff0c;支持静态图片、实时视频流、摄像头视频流和网络视频流的处理。与 PiscTrace 应用版相比&#xff0c;开发者版通过直接的代码开发&#xff0c;提供了更高的灵活性和可定制性&#xff0c;适用于需要深度定制和复杂处理的应用…

excel中VBA宏的使用方法?

先编写宏代码&#xff1a;&#xff08;随便新建打开一个记事本文档 或者 word文档&#xff09; 然后&#xff1a;

selenium爬取苏宁易购平台某产品的评论

目录 selenium的介绍 1、 selenium是什么&#xff1f; 2、selenium的工作原理 3、如何使用selenium&#xff1f; webdriver浏览器驱动设置 关键步骤 代码 运行结果 注意事项 selenium的介绍 1、 selenium是什么&#xff1f; 用于Web应用程序测试的工具。可以驱动浏览…

USC安防平台之元数据检索

平台基于深度学习技术&#xff0c;支持CPU和NVIDIA GPU推理&#xff0c;支持周界和违法行为实时分析&#xff0c;并存储元数据到流式视频数据库中&#xff0c;可以根据不同的条件搜索&#xff0c;从而提供更强大的安全防范策略和事后调查手段。 平台根据用户自定义规则来检测异…

基于VirtualBox虚拟机部署完全分布式Hadoop环境

搭建 一、Ubuntu系统搭建 系统搭建 二、host配置 首先创建一个新用户hadoop并且分配权限&#xff0c;切换到hadoop用户下 成功切换 然后可以先克隆一下另一个虚拟机&#xff0c;为了之后的相互通信 直接点击虚拟机右键克隆即可 但是这里有一个问题&#xff0c;就是在…

正则表达式–断言

原文地址&#xff1a;正则表达式–断言 – 无敌牛 欢迎参观我的个人博客&#xff1a;正则表达式特殊字符 – 无敌牛 断言assertions 1、(?...)&#xff1a;正向预查&#xff08;positive lookahead&#xff09;&#xff0c;表示某个字符串后面应该跟着什么。但这个字符串本身…

【DeepSeek-R1背后的技术】系列九:MLA(Multi-Head Latent Attention,多头潜在注意力)

【DeepSeek背后的技术】系列博文&#xff1a; 第1篇&#xff1a;混合专家模型&#xff08;MoE&#xff09; 第2篇&#xff1a;大模型知识蒸馏&#xff08;Knowledge Distillation&#xff09; 第3篇&#xff1a;强化学习&#xff08;Reinforcement Learning, RL&#xff09; 第…

UE_C++ —— Gameplay Classes

目录 一&#xff0c;Adding Classes 二&#xff0c;Class Headers Class Declaration Class Specifiers Metadata Specifiers 三&#xff0c;Class Implementation Class Constructor 引擎中每个游戏类都由一个类头文件&#xff08;.h&#xff09;和一个类源文件&#x…

使用AI创建流程图和图表的 3 种简单方法

你可能已经尝试过使用 LLMs 生成图像&#xff0c;但你有没有想过用它们来创建 流程图和图表&#xff1f;这些可视化工具对于展示流程、工作流和系统架构至关重要。 通常&#xff0c;在在线工具上手动绘制图表可能会耗费大量时间。但你知道吗&#xff1f;你可以使用 LLMs 通过简…

二叉树(中等题)

1、先序&#xff0c;中序遍历确定二叉树 105 方法一、 前提 ① 必须不能有重复元素② 只有先序&#xff0b;中序和后序&#xff0b;中序才能实现唯一树 思考要点&#xff1a; 不要想着用for循环&#xff0c;递归一定更好解决输入是vector&#xff0c;递归就得考虑传入索…

蓝思科技赋能灵伴科技:AI眼镜产能与供应链双升级

2月22日&#xff0c;蓝思科技宣布与AI交互领军企业杭州灵伴科技&#xff08;Rokid&#xff09;达成深度战略合作&#xff0c;通过整机组装与全产业链整合&#xff0c;为2025年全球AI眼镜出货量爆发式增长&#xff08;预计达400万-1200万台&#xff09;提供核心支撑。 双方合作通…

【C/C++】分隔链表 (leetcode T86)

核心考点预览&#xff1a;链表 &#xff08;双指针&#xff09; 技巧&#xff1a;虚拟头结点 题目描述&#xff1a; 给你一个链表的头节点 head 和一个特定值 x &#xff0c;请你对链表进行分隔&#xff0c;使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 你应…

Lineageos 22.1(Android 15)Launcer简单调整初始化配置

一、前言 Launcer的初始化配置主要在如下的xml文件夹下&#xff0c;默认读取的5x5 这里我们把device_profiles调整一下&#xff0c;然后新建一个default_workspace_my.xml作为我们自己的配置就行。 二、配置 注意Lineageos 的Launcer是在lineageos/packages/apps/Trebuchet…

量子计算的基本运算:Hadamard 门、CNOT 门、Pauli 门详解

量子计算是现代计算科学的前沿领域,它与经典计算机在处理信息的方式上有着本质的区别。量子计算机利用量子比特(qubit)的叠加态和量子纠缠等特性来进行计算,从而在某些特定任务上超越传统计算机。量子计算的核心运算单元是量子门,它们通过作用于量子比特来操控量子状态。本…

Java 大视界 -- 国际竞争与合作:Java 大数据在全球市场的机遇与挑战(94)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

游戏引擎学习第113天

仓库:https://gitee.com/mrxiao_com/2d_game_2 黑板&#xff1a;优化的基本过程 在游戏编程中&#xff0c;优化是一个非常重要的学习内容&#xff0c;尤其是想要成为专业开发者时。优化的核心是理解代码的执行速度&#xff0c;以及如何提升其性能。在这个阶段&#xff0c;已经…

教师教学技能大赛流程方案及细则

为了适应高等教育的改革和我校的生存发展&#xff0c;进一步提升教师教学技能和教育教学能力&#xff0c;促进教师专业发展&#xff0c;提高教师综合素质&#xff0c;加强我校教师队伍建设&#xff0c;提高教育教学质量&#xff0c;举办青年教师教学技能大赛&#xff0c;特制订…