智能汽车实验二(视觉传感器标定)
实验二 视觉传感器标定(实验报告)
【实验目的】
1、了解开源图像处理库OpenCV的结构,掌握OpenCV的基本使用方法。
2、了解开源图像处理库OpenCV的基本模块功能,掌握常用图像处理方法。
3、掌握摄像机标定算法,学会使用OpenCV进行摄像机标定。
【实验性质】
验证性实验。
【实验要求】
1、C++集成开发环境(QT5或VS2015及以上)
2、OpenCV 4.x
3、单/双目摄像机
【实验内容】
1、掌握OpenCV开源图像库的基本使用方法
2、使用OpenCV进行单目摄像机标定
3、使用OpenCV进行双目摄像机标定
【实验步骤】
1、下载、安装、OpenCV 4.x
官网下载:https://opencv.org/opencv-4-6-0/
2、摄像机标定原理
摄像机标定的目标,是要建立三维世界坐标系与二维图像坐标系之间的对应关系。在单目视觉中,这种对应关系是一对多的,即二维图像中的一个像素点对应着三维空间中的一条直线;在双目视觉中,可以通过两幅二维图像上的对应像素点计算得到三维世界坐标系与二维图像坐标系的一一对应关系。由此便可以得到物体的三维坐标值。
摄像机安装位置参数为外部参数,摄像机镜头畸变参数为非线性模型内部参数。标定过程即是求出摄像机的内部参数和外部参数,从而得到上述坐标转换的旋转矩阵和平移向量。
图2-1 摄像机成像模型
图中,摄像机坐标系为OXcYcZc,而计算机图像坐标系O0uv与图像平面坐标系O1xy的转换关系为:
u = sux + u0
v = svy + v0
写成矩阵形式为:
uv1=su0u00svv0001xy1
其中,su、sv分别为x、y轴方向单位长度对应的像素点数;u0、v0为镜头光学中心位置,单位为mm。
请用矩阵形式写出计算机图像平面坐标系O0uv与世界坐标系的转换关系:
其中,Xw Zcuv1=su0u00svv0001xy1=su0u00svv0001f0000f000010XcYcZc1=su0u00svv0001f0000f000010RT01XwYwZw1 |
实际上,摄像机镜头成像并不是理想的透视成像,而是存在径向变形、偏心变形、薄棱镜变形等因素影响下产生不同程度的畸变。由于畸变因素作用,使空间点成像并不在线性模型描述的位置x,y,而是在受到镜头失真影响而偏移的平面坐标x',y'
。
x=x'+ ∆xy=y'+ ∆y
其中,∆x、∆y
为非线性畸变值,与像点在图像中的位置有关。一般镜头畸变同时存在径向畸变和切向畸变,切向畸变是由于透镜与摄像头传感器平面或图像平面不平行而产生的,多是由于透镜安装到镜头模组上的偏差导致,通常较小。实际应用中多只考虑径向畸变,径向畸变常用距图像中心径向距离的泰勒级数展开的前几项来表示:
∆x=x'-u0k1r2+k2r4+…∆y=y'-v0k1r2+k2r4+…
k1、k2
为非线性畸变参数,r2=x'-u02+y'-v02
。
摄像机的标定方法很多,大致可分为传统标定技术和自标定技术。
传统标定技术: 需要在摄像机前放置一个特定的标定物,并人为地提供一组已知坐标的特征基元,摄像机通过寻找这些已知特征的基元来实现标定
自标定技术: 比较灵活,不需要特定的参照物,它利用环境的刚体性,通过对比多幅图像中的对应点来计算摄像机模型
OpenCV采用介于传统标定方法和自标定方法之间的一种方法,由张正友提出。这种方法不需要知道摄像机运动的具体信息,比传统标定方法更灵活,同时仍需要一个特定的标定物以及一组已知的特征基元的坐标,这一点不如自标定灵活。它通过在至少3个不同的位置获取标定物的图像,计算出摄像机所有的内外参数。
标定算法描述参考知乎:https://zhuanlan.zhihu.com/p/36371959
OpenCV源码在其sample/data目录下面一个自带的棋盘图(chessboard.png),显示如下:
在标定的时候,算法要求提供的棋盘格的宽度与高度,还有他们的间隔距离。需要特别注意是这里的宽高是指他们的内部交叉点的个数,以上图为例,它的大小为7x7而不是8x8。间隔是指棋盘格之间的距离,可以用像素距离表示,也可以用实际毫米为单位表示。
3、标定常用函数
(1)findChessboardCorners()
bool findChessboardCorners( InputArray image, Size patternSize, OutputArray corners,
int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE );
函数功能: 确定输入图像是否是棋盘模式,并确定角点的位置。如果所有角点都被检测到且它们都被以一定顺序排布(一行一行地,每行从左到右),函数返回非零值,否则在函数不能发现所有角点或者记录它们地情况下,函数返回0
(2)cv::drawChessboardCorners()
drawChessboardCorners( InputOutputArray image, Size patternSize,
InputArray corners, bool patternWasFound );
函数功能: 用于标定摄像机时绘制被成功标定的角点
(3)find4QuadCornerSubpix()
find4QuadCornerSubpix(InputArray img, InputOutputArray corners, Size region_size );
函数功能: 查找棋盘角的亚像素精确位置。尝试近似分隔棋盘格字段(“四边形”)的线并返回这些线的交叉点。
(4)cornerSubPix()
void cornerSubPix( InputArray image, InputOutputArray corners, Size winSize,
Size zeroZone, TermCriteria criteria );
函数功能: 优化角点位置,获得棋盘格上的亚像素角点。
(5)calibrateCamera()
double calibrateCamera( InputArrayOfArrays objectPoints,
InputArrayOfArrays imagePoints,
Size imageSize,
InputOutputArray cameraMatrix,
InputOutputArray distCoeffs,
OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs,
int flags = 0,
TermCriteria criteria = TermCriteria(TermCriteria::COUNT +
TermCriteria::EPS, 30, DBL_EPSILON) );
函数功能: 通过多个视角的2D/3D对应,求解出该相机的内参数和每一个视角的外参数
(6)initUndistortRectifyMap()
void initUndistortRectifyMap(InputArray cameraMatrix,
InputArray distCoeffs,
InputArray R,
InputArray newCameraMatrix,
Size size,
int m1type,
OutputArray map1,
OutputArray map2)
函数功能: 这个函数使用于计算无畸变和修正转换关系。
4、单目摄像机标定
(1)打开标定配置参数文件default.xml,设置参数:
- 棋盘格的宽度和高度(两个方向的角点数量),根据实际情况设置。
<!-- Number of inner corners per a item row and column. (square, circle) -->
<BoardSize_Width>9</BoardSize_Width>
<BoardSize_Height>6</BoardSize_Height>
- 每格的宽度
单元格的宽度应设置为实际的毫米数。
<!-- The size of a square in some user defined metric system (pixel, millimeter)-->
<Square_Size>50</Square_Size>
- 选择输入方式
程序提供了3种输入方式。如果摄像机已连接电脑,可以使用input_camera方式。该方式只需要设置视频输入设备号,对于笔记本而言,通常0表示笔记本内置摄像头,1表示外置摄像头。
- 编译OpenCV标定程序
(2)标定程序将实现以下功能
- 确定失真矩阵
- 确定摄像机矩阵
- 摄像机、视频和图像文件列表的输入
- 从XML/YAML文件进行配置
- 将结果保存到XML/YAML文件中
- 计算重投影误差
程序只有一个参数。其配置文件的名称。如果没有,它将尝试打开一个名为“default.xml”。
(3)运行标定程序,摄像机将拍摄25幅图片并识别角点,如下图
(4)标定结果保存在程序中指定的结果文件中
请在实验报告中说明结果文件中各项数据的意义(阅读代码,并在网上查阅相关资料)
<nr_of_frames>25</nr_of_frames> 图像的宽和高度 <image_width>640</image_width> <image_height>480</image_height> 棋盘格的宽度11和高度8 <board_width>11</board_width> <board_height>8</board_height> 单元格的尺寸 <square_size>50.</square_size> 相机类型 <fisheye_model>0</fisheye_model> 尺寸自适应 <fix_aspect_ratio>1.</fix_aspect_ratio> 相机内部参数矩阵data为值 Rows 和 cols为行和列 Dt表示数据类新 <camera_matrix type_id="opencv-matrix"><rows>3</rows><cols>3</cols> <dt>d</dt> <data> 7.0111172389870558e+02 0. 3.1950000000000000e+02 0. 7.0111172389870558e+02 2.3950000000000000e+02 0. 0. 1. </data></camera_matrix> 畸变系数 Row和cols为维度 Data包含畸变系数实际的值 <avg_reprojection_error> 为平均投影误差值 <distortion_coefficients type_id="opencv-matrix"><rows>5</rows><cols>1</cols> <dt>d</dt> <data> 7.2399710954221264e-02 4.5114674802590399e-01 0. 0. -3.8163393536623835e+00</data></distortion_coefficients><avg_reprojection_error>4.1946356118960665e-01</avg_reprojection_error> <extrinsic_parameters type_id="opencv-matrix"><rows>25</rows><cols>6</cols> 数据类型为double <dt>d</dt> <data> 数据太长这里省略 </data> <image_points type_id="opencv-matrix"> <rows>25</rows><cols>88</cols> 数据类型为浮点 <dt>"2f"</dt> <data>1.96974991e+02 3.05226959e+02 2.15540726e+02 3.04309814e+02 2.34028198e+02 3.03369354e+02 2.52492340e+02 3.02424805e+02 2.70655762e+02 3.01588440e+02 2.88653290e+02 3.00733093e+02 3.06717133e+02 2.99980408e+02 3.24438385e+02 2.99227295e+02 3.42079742e+02 2.98437469e</data> 这里也是数据太长省略 <grid_points> 0. 0. 0. 50. 0. 0. 100. 0. 0. 150. 0. 0. 200. 0. 0. 250. 0. 0. 300. 0. 0. 350. 0. 0. 400. 0. 0. 450. 0. 0. 500. 0. 0. 0. 50. 0. 50. 50. 0. 100. 50. 0. 150. 50. 0. 200. 50. 0. 250. 50. 0. 300. 50. 0. 350. 50. 0. 400. 50. 0. 450. 50. 0. 500. 50. 0. 0. 100. 0. 50. 100. 0. 100. 100. 0. 150. 100. 0. 200. 100. 0. 250. 100. 0. 300. 100. 0. 350. 100. 0. 400. 100. 0. 450. 100. 0. 500. 100. 0. 0. 150. 0. 50. 150. 0. 100. 150. 0. 150. 150. 0. 200. 150. 0. 250. 150. 0. 300. 150. 0. 350. 150. 0. 400. 150. 0. 450. 150. 0. 500. 150. 0. 0. 200. 0. 50. 200. 0. 100. 200. 0. 150. 200. 0. 200. 200. 0. 250. 200. 0. 300. 200. 0. 350. 200. 0. 400. 200. 0. 450. 200. 0. 500. 200. 0. 0. 250. 0. 50. 250. 0. 100. 250. 0. 150. 250. 0. 200. 250. 0. 250. 250. 0. 300. 250. 0. 350. 250. 0. 400. 250. 0. 450. 250. 0. 500. 250. 0. 0. 300. 0. 50. 300. 0. 100. 300. 0. 150. 300. 0. 200. 300. 0. 250. 300. 0. 300. 300. 0. 350. 300. 0. 400. 300. 0. 450. 300. 0. 500. 300. 0. 0. 350. 0. 50. 350. 0. 100. 350. 0. 150. 350. 0. 200. 350. 0. 250. 350. 0. 300. 350. 0. 350. 350. 0. 400. 350. 0. 450. 350. 0. 500. 350. 0.</grid_points></opencv_storage> <grid_points> 这里面是相片的标定,坐标为像素点 |
相关文章:

智能汽车实验二(视觉传感器标定)
实验二 视觉传感器标定(实验报告) 【实验目的】 1、了解开源图像处理库OpenCV的结构,掌握OpenCV的基本使用方法。 2、了解开源图像处理库OpenCV的基本模块功能,掌握常用图像处理方法。 3、掌握摄像机标定算法,学会使用…...
计算机网络:HTTP
目录 HTTP 是什么?HTTP 常见的状态码有哪些HTTP 常见字段有哪些参考资料 HTTP 是什么? HTTP 是超文本传输协议,也就是HyperText Transfer Protocol。 1. 「协议」 「协」字,代表的意思是必须有两个以上的参与者。「议」字&…...
Go 语言接口
Go 语言接口 Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口。 实例 实例 /* 定义接口 */ type interface_name interface { method_name1 [return_type] method_name2…...
常用的intellij的快捷键
ctrlshiftspace(new 后面自动提示) ctrlshift/ (注释) itar后面tab (for循环) it后面ctrlj(很多智能代码生成) AltInsert(自动生成构造函数,get,set方法) ctrlaltt(自动生成try,catch) altenter(创建测试类和子类) ctrlshiftbackspace(最后编辑的地方) ctrl…...
Unity中的`SetPositionAndRotation()`
介绍 SetPositionAndRotation() 是Unity中的一个方法,用于同时设置物体的位置和旋转。它可以在不必分别调用 transform.position 和 transform.rotation 属性的情况下,直接设置物体的位置和旋转。 方法 以下是 SetPositionAndRotation() 方法的参数&a…...

API 接口的使用和功能
随着互联网的快速发展,API接口已经成为了现代开发中不可或缺的一部分。API接口可以让你的应用程序与其他应用程序、系统或服务进行数据交流和集成。如果你正在开发应用程序,那么最好的方法就是使用API接口来增强功能和性能。 我们的API接口是为您的应用…...
Vue插件
介绍 Vue插件是一种扩展Vue应用程序功能的方式。使用Vue插件,您可以在Vue应用程序中重复使用代码或添加新功能。更具体地说,Vue插件通常具有以下用途: 封装重复的功能或组件,以便在多个Vue组件中使用。 扩展Vue的核心功能并使其…...

C++好难(5):内存管理
这一节学完,我们 C嘎嘎 就算是正式入门了,但是之后的课还会更上一阶d(ŐдŐ๑) 继续坚持! 【本节目标】 1. C/C内存分布 2. C语言中动态内存管理方式 3. C中动态内存管理 4. operator new与operator delete函数 5. new和delete的实现原…...

vue-admin-template中vue动态路由不显示问题解决
使用的的是vue-admin-template,这是一个极简的 vue admin 管理后台,它只包含了 Element UI & axios & iconfont & permission control & lint,这些搭建后台必要的东西。需要根据自己的需求二次开发。 线上地址:vue-admin-tem…...

IP协议介绍
文章目录 一、IP协议的基本认识二、IP的协议头格式三、网段划分四、特殊的IP地址五、IP地址的数量限制六、私有IP地址和公网IP地址 一、IP协议的基本认识 IP在网络分层中属于网络层协议,传输层协议里的TCP协议解决的是可靠性问题,网络层协议里的IP协议能…...
将一个单体服务重构成微服务
将一个单体服务重构成微服务需要经过以下步骤: 1. 拆分服务:将单体服务拆分成多个小服务,每个服务只负责一个特定的功能。拆分的原则是将服务按照业务功能进行划分,每个服务都应该是相对独立的。 2. 设计API:为每个服务…...

SpringBoot项目如何打包成exe应用程序
准备 准备工作: 一个jar包,没有bug能正常启动的jar包 exe4j,一个将jar转换成exe的工具 链接: https://pan.baidu.com/s/1m1qA31Z8MEcWWkp9qe8AiA 提取码: f1wt inno setup,一个将依赖和exe一起打成一个安装程序的工具 链接:…...

一文读懂:客户管理系统平台是什么?有什么作用?
“客户管理系统平台是什么?” “客户管理系统平台有什么作用?在哪里可以应用?怎么用?” 经常可以听到企业内部关于客户管理系统平台的这些问题,本文将会为您一一解答: 一、客户管理系统平台是什么 顾名…...

Node.js 与 TypeScript
目录 1、什么是 TypeScript 2、运行TypeScript 3、TypeScript 在Node.js 生态中的情况 1、什么是 TypeScript TypeScript是一种流行的开源语言,由微软维护和开发。它受到了世界各地许多软件开发人员的喜爱和使用。 基本上,它是JavaScript的超集&…...

Python并发编程之进程理论
前言 本文将详细介绍进程相关概念。 进程和程序 计算机上的未运行的QQ、Wechat等都属于程序,但是一旦当这些程序运行起来的话,就可以被称为进程。因此可以如下定义程序和进程: 程序:就是存在硬盘上的一堆代码。 进程…...

超级详细的mysql数据库安装指南
MySql数据库 如果你的电脑是mac那么你看这位大佬的分享。 如果你的电脑是windows,参考下面的安装步骤。 一、下载mysql数据库? 进入MySQL官方网站(MySQL Community Downloads),按下图顺序点击 1、进入下载页面 2、…...

Java并发编程实践学习笔记(三)——共享对象之发布和异常
目录 1 公共静态变量逸出 2 非私有方法逸出私有变量 3 this引用逸出 4 构造函数中的可覆盖方法调用逸出 发布(publishing)一个对象的意思是:使对象能够在当前作用域之外的代码中使用。例如,将一个指向该对象的引用保存到其他代…...

Python学习之Image模块图片滤镜效果操作示例
前言 滤镜效果是图像处理中常用的一种技术,可以用来增强图像的视觉效果,实现不同的效果,比如增强对比度、饱和度、色彩等。滤镜效果可以帮助用户快速地调整图像的特性,从而使图像更加适合用户的需求。 Image模块对于图像处理的…...

Grafana 系列-统一展示-5-AWS Cloudwatch 仪表板
系列文章 Grafana 系列文章 👍️强烈推荐 强烈推荐使用 GitHub 上的 monitoringartist/grafana-aws-cloudwatch-dashboards 仪表板。该 repo 有一系列 AWS 资源的仪表板,包括但不限于: EC2EBSAPI GWAutoscalingBillingEKSLambdaLogsRDSS3…...

MySQL---控制流函数、窗口函数(序号函数、开窗聚合函数、分布函数、前后函数、头尾函数、其他函数)
1. 控制流函数 格式 解释 案例 IF(expr,v1,v2) 如果表达式 expr 成立,返回结果 v1;否则,返回结果 v2。 SELECT IF(1 > 0,正确,错误) ->正确 IFNULL(v1,v2) 如果 v1 的值不为 NULL,则返回 v1ÿ…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...

用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
Linux系统部署KES
1、安装准备 1.版本说明V008R006C009B0014 V008:是version产品的大版本。 R006:是release产品特性版本。 C009:是通用版 B0014:是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存:1GB 以上 硬盘…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...
API网关Kong的鉴权与限流:高并发场景下的核心实践
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中,API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关,Kong凭借其插件化架构…...
【WebSocket】SpringBoot项目中使用WebSocket
1. 导入坐标 如果springboot父工程没有加入websocket的起步依赖,添加它的坐标的时候需要带上版本号。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId> </dep…...