智慧交通day03-车道线检测实现02-1:相机校正

1. 相机标定的意义

我们所处的世界是三维的,而照片是二维的,我们可以把相机认为是一个函数,输入量是一个场景,输出量是一幅灰度图。这个从三维到二维的过程的函数是不可逆的。

相机标定的一个目的是要找一个合适的数学模型,求出这个模型的参数,能够近似从三维到二维的过程,使这个三维到二维的过程的函数找到反函数。

这个逼近的过程就是相机标定,我们用简单的数学模型来表达复杂的成像过程。

由此可知,相机标定的一个目的就是建立像素坐标系和世界坐标系之间的关系。原理是根据摄像机的模型,由已知特征点的图像坐标求解摄像机的模型参数,并求出成像的反过程,从而从图像中恢复出空间点的三维坐标,达到三维重建的目的。

另外相机标定还可以进行图像校正,由于透镜的制造精度以及组装工艺的偏差会引入畸变,导致图形失真,所以我们可以求解畸变参数,对图像进行去畸变。

2. 成像原理

在介绍相机标定之前,我们首先来看下相机的成像模型。也就是,现实物体上的一个点在相机采集到的图像中所在的位置是怎么确定的。我们采用的模型是针孔模型,也就是小孔成像。

小孔成像是利用了光线直线传播的原理。比如说,远处有一棵大树,而我们有个盒子,在这个盒子的对着大树的那一面上用针尖戳一个小孔。我们任选这棵大树上的任何的一个点,它都会向四周去反射无数条光线。但是因为光线是直线传播的,所以这些光线要么没有一条能进入盒子中,要么就只有一条光线是进入到这个盒子里面的。进入到盒子中的光线会在盒子里的一面上形成一个光点。这个光点跟大树上的某个点是对应的,颜色也是一致的,这就建立了一对一的关系。如果我们把感光胶片或者感光的传感器放在盒子里,就可以做成一个针孔相机来得到大树的彩色图像了。如下图所示:

由于大树上每个点反射的无数条光线只有一条进入到盒子中,所以图像是很暗的。而加大孔径,虽然可以提高图像的亮度,却会使物体上的某一个点会反射一小束光进入到相机里。这一小束光会在感光传感器上形成一个光斑,而不是一个点;从而相机失去了物体与图像上的点的一一对应关系,进而导致图像模糊甚至无法成像。当然实际的针孔相机不可能是让每个点只有一条光线进入相机。因为光具有波粒二象性,是可以衍射的,所以很小的针孔,也会导致图像模糊。根据可见光的波长,理论计算的小孔最佳直径是 0.25mm 左右,相应的光圈值大概是 f/200。

所以用一个直径比针孔直径大许多的凸透镜来替代针孔。凸透镜可以把物体上的一个点所反射的那一小束通过透镜的光重新汇聚成一个点,这样,不但图像亮度增大了,而且物体和图像上点的又可以一一对应起来了。这就是我们现在常用的相机的基本工作原理。

3. 相机成像模型

现在我们看下相机的成像模型,我们从下图中直观感受下:

下面我们介绍下成像过程中的四大坐标系:

下面我们进行一系列的变换,引入多个参数矩阵,实现从世界坐标系到像素坐标的转换。已知一个现实世界中的物体点的在世界坐标系中的坐标为(Xw, Yw, Zw),经过相机拍摄得到图片,在图片上的像素坐标为(u , v )。假设在图像坐标系中的坐标为( x , y ),在相机坐标系中的坐标为(Xc, Yc, Zc)。各个坐标之间的转化流程如下图所示:

3.1. 世界坐标系与相机坐标系之间的转换

世界坐标系转换到相机坐标系时不会产生形变,所以将世界坐标系进行刚体变换就可转换为相机坐标系。三维空间中,当物体不发生形变时,而只进行旋转平移的运动,就是刚体变换。空间中的一个坐标系总可以通过刚体变换,即平移和旋转,就可以转换为另一个坐标系,如下图所示:

下面我们看下旋转矩阵的计算,现在假设坐标系沿着z轴旋转,如下图所示:

则有:(假设其中x’,y’表示世界坐标系,x,y是相机坐标系)

3.2. 相机坐标系到图像坐标系的转换

从相机坐标系到图像坐标系,是从3d到2d的过程,属于透射投影关系:

3.3. 图像坐标系到像素坐标系

像素坐标系和图像坐标系都在成像平面上,只是各自的原点和度量单位不一样。图像坐标系的原点为相机光轴与成像平面的交点,通常情况下是成像平面的中点。图像坐标系的单位是mm,属于物理单位,而像素坐标系的原点在图像的左上角,单位是pixel,也就是我们说的几行几列。如下图所示:

所以这二者之间的转换如下:

3.4. 总结

我们已经介绍了各个坐标系之间的转换过程,但是我们想知道的是如何从世界坐标系转换到像素坐标系,因此我们需要把上面介绍到的联系起来,将三者相乘,可以把这三个过程和在一起,写成一个矩阵:

4. 图像畸变

我们在相机坐标系到图像坐标系变换时谈到透视投影。相机拍照时通过透镜把实物投影到像平面上,但是透镜由于制造精度以及组装工艺的偏差会引入畸变,导致原始图像的失真。因此我们需要考虑成像畸变的问题。透镜的畸变主要分为径向畸变和切向畸变两类。

4.1. 径向畸变

顾名思义,径向畸变就是沿着透镜半径方向分布的畸变,产生原因是光线在原理透镜中心的地方比靠近中心的地方更加弯曲,这种畸变在普通的镜头中表现更加明显,径向畸变主要包括桶形畸变和枕形畸变两种。以下分别是枕形和桶形畸变示意图:(从左到右依次是:正常无畸变,桶形畸变和枕形畸变)

4.2. 切向畸变

切向畸变是由于透镜本身与相机传感器平面(像平面)或图像平面不平行而产生的,这种情况多是由于透镜被粘贴到镜头模组上的安装偏差导致。在相机传感器和镜头不平行的情况下,因为存在夹角,所以光透过镜头传到图像传感器上时,成像位置发生了变化,如下图所示:

下图显示某个透镜的切向畸变示意图,大体上畸变位移相对于左下—右上角的连线是对称的,这跟凸透镜与传感器之间的夹角有关:

径向畸变和切向畸变模型中一共有5个畸变参数:k1、k2、p1、p2、k3,得到这五个参数,就可以进行图像的去畸变。这些都属于相机的内参。

5.相机标定的分类

相机标定方法一般分为三类,分为传统的标定算法,自标定法和基于主动视觉的标定法。分别介绍如下:

  • 传统的标定算法:传统的相机标定算法就是基于标定物的相机标定算法,在进行相机标定时,要通过专门指定的标定物来完成,此类方法是利用标定物上构建的已确定的物点坐标和与之对应的图像点之间的联系,借助一些数学方法,得到相机的内部和外部参数。它对标定物的要求有:标定物的特征部分与周围环境存在较大的差别,特征容易分辨且提取方便,标定物具有较高的稳定性,也就是说它的特征不随着相机位置的变换产生畸变。常见模板有棋盘格,圆形,三角形等。

  •  代表算法有Tsai标定法和直接线性变换法(DLT)等。

  • 自标定法:该算法不使用标定物,而是依靠图像点之间存在的关系,直接计算相机的参数。该算法只计算相机的内部参数的约束,不考虑相机系统的外部场景,所以方法灵活,应用范围较广,但是算法鲁棒性较差,只适合精度要求较低的场合。

  • 基于主动视觉的标定法:该算法是控制相机做一些特定的动作,比如说平移,旋转,得到多张图片,以此计算相机参数。使用比较广泛的有两类:一类是在三维空间中,让相机作两组纯平移运动,进而求解相机的参数,第二类是控制相机绕光心轴旋转,获得相机的参数。此类方法优点是算法简单,往往能够获得线性解,故鲁棒性较高,缺点是系统的成本高、实验设备昂贵、实验条件要求高,而且不适合于运动参数未知或无法控制的场合。

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

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

相关文章

把输入字符的小写转换成大写并输出

#include <stdio.h> #include <stdlib.h> #include <string.h> /******************************* *把小写字母转成大写字母 ********************************/ int main(void) { char *srcNULL;unsigned char i0;char *new_1NULL;char *new_2NULL;char *dN…

关于一些html和css2的知识点

前端开大语言三种:1)HTML(hypertext markup language)结构2)css(Cascading Style Sheets)样式 3)js(Javascript)行为 脚本语言 属性:属性值 用来描述标签的一些特征的关键词 关于css样式的引入方式 一共有三种 1)行间样式表(写在标签的开始标记上) 2)内部样式 写在<styl…

nginx服务无法启动,启动时报错1067以外终止

解决方法&#xff1a; 首先cmd命令打开&#xff0c;输入nginx -t测试配置文件是否能运行OK&#xff0c;如果报错bind() to 0.0.0.0:80 failed (10013: An attempt was made to access a …) 则说明配置文件中的端口0.0.0.0:80被占用 可使用下面两种方法解决&#xff1a; cmd输…

智慧交通day03-车道线检测实现02-2:张氏标定法+双目标定

6.张氏标定法 张氏标定法是张正友博士在1999年发表在国际顶级会议ICCV上的论文《Flexible Camera Calibration By Viewing a Plane From Unknown Orientations》中&#xff0c;提出的一种利用平面棋盘格进行相机标定的实用方法。 该方法介于传统标定法和自标定法之间&#xff…

指针的基本操作(10.1 Basic Pointer Operations)

[This section corresponds to K&R Sec. 5.1] The first things to do with pointers are to declare a pointer variable, set it to point somewhere, and finally manipulate the value that it points to. A simple pointer declaration looks like this: 对指针的第…

C/C++中的声明与定义

含义 声明(Declaration), 用于告诉编译器被声明的函数/变量的存在, 及它们的类型/调用格式信息, 以检查是否被正确调用. 声明不分配内存空间. 定义(Definition), 用于告诉编译器被声明的函数/变量的存在位置, 会分配内存空间. 变量/函数在被使用之前一定要被声明. 声明和定义可…

HTML animate()动画更改多个元素背景颜色但不同时生效问题

问题&#xff1a; 我想点击按钮时把页面中的body颜色和button中颜色【同时】改变 这个时候出现了body颜色先变化&#xff0c;而button颜色后变化&#xff0c;似乎是因为我的代码是这样有先后顺序的&#xff1a; $("html,body").animate({backgroundColor:BGC[rando…

plt.axis()用法详解

plt.axis(‘square’) 作图为正方形&#xff0c;并且x,y轴范围相同&#xff0c;即y m a x − y m i n x m a x − x m i n y_{max}-y_{min} x_{max}-x_{min}y plt.axis(‘equal’) x,y轴刻度等长 plt.axis(‘off’) 关闭坐标轴 官网上也贴出了其他的一些选项 plt.axis([a,…

工作队列

关于工作队列的详细API解释:http://blog.csdn.net/angle_birds/article/details/8448070 工作队列的使用:http://blog.csdn.net/zhenwenxian/article/details/17980231 下面是TP驱动中用到的工作队列:但是唤醒任务用的是queue_work函数 /** drivers/input/touchscreen/gt80…

python3列表生成式中的for循环与普通放在外面的for循环细微差异

python3列表生成式中的for循环与普通放在外面的for循环细微差异 实例&#xff1a; 给定列表alist [1,2,3,4,5,6,7]&#xff0c;k3 想要使用for循环达成输出[5,6,7,1,2,3,4] 1.用外面的for循环做&#xff1a; alist [1,2,3,4,5,6,7] k 3 for _ in range(k):alist[0:0] [ali…

struts2学习笔记之十一:struts2的类型转换器

Struts2的类型转换器如何实现Struts2的类型转换器&#xff1f;* 继承StrutsTypeConverter* 覆盖convertFromString和convertToString注册类型转换器* 局部类型转换器&#xff0c;局部类型转换器只对当前Action起作用&#xff0c;需要提供如下配置文件&#xff1a;MyActionName-…

【Pytorch神经网络基础理论篇】 01 从零开始介绍深度学习算法和代码实现

同学你好&#xff01;本文章于2021年末编写&#xff0c;已与实际存在较大的偏差&#xff01; 故在2022年末对本系列进行填充与更新&#xff0c;欢迎大家订阅最新的专栏&#xff0c;获取基于Pytorch1.10版本的理论代码(2023版)实现&#xff0c; Pytorch深度学习理论篇(2023版)…

不让系统进休眠(调试时有时会用到)

关于android的锁机制&#xff0c;可以查看&#xff1a;http://blog.csdn.net/sfrysh/article/details/6608118 不让android进入休眠可以在kernel里加上三行代码。一直保管着这个锁。系统就不会进入休眠。如下&#xff1a; static struct wake_lock wqf_charge_display_lock; /…

【Pytorch神经网络基础理论篇】 02 pytorch环境的安装

同学你好&#xff01;本文章于2021年末编写&#xff0c;已与实际存在较大的偏差&#xff01; 故在2022年末对本系列进行填充与更新&#xff0c;欢迎大家订阅最新的专栏&#xff0c;获取基于Pytorch1.10版本的理论代码(2023版)实现&#xff0c; Pytorch深度学习理论篇(2023版)…

JavaScript (If...Else和Switch和循环遍历) 语句以及常用消息框

If...Else 语句 JavaScript中if...else语句和Java中的语法和使用方法是一样的。 只是在JavaScript中要使用小写字母。使用大写的 IF 会出错&#xff01; 至于if...else...else if...和Java中的都是一样的。 例&#xff1a; var d new Date() var time d.getHours()if (time&l…

numpy中两个array数值比较,在IDE中显示完全相同,但是bool判断两个array是否相等却返回False

numpy踩坑&#xff1a;两个array中数值分别比较&#xff0c;在IDE显示相同&#xff0c;但是bool判断两个array是否相等值却是False 在numpy数据比较时&#xff0c;在IDE显示完全相同但是比较是否相等却有时候返回False&#xff1f; 原因出在了精度显示上面&#xff0c;在代码开…

C两个小例子(数组与指针)

大端模式 所谓的大端模式&#xff0c;是指数据的高位&#xff0c;保存在内存的低地址中&#xff0c;而数据的低位&#xff0c;保存在内存的高地址中&#xff0c;这样的存储模式有点儿类似于把数据当作字符串顺序处理&#xff1a;地址由小向大增加&#xff0c;而数据从高位往低位…

智慧交通day03-车道线检测实现03:相机校正和图像校正的实现

1.相机标定 根据张正友校正算法&#xff0c;利用棋盘格数据校正对车载相机进行校正&#xff0c;计算其内参矩阵&#xff0c;外参矩阵和畸变系数。 标定的流程是&#xff1a; 准备棋盘格数据&#xff0c;即用于标定的图片对每一张图片提取角点信息在棋盘上绘制提取到的角点&a…

win10编辑js文件报错,错误','

在filezilla中编辑js文件报错&#xff0c;在本地可以使用文本编辑&#xff0c;但需重新上传覆盖&#xff0c;很不方便 在win10默认应用中修改为文本编辑即可&#xff0c;在FTP编辑&#xff1a; 直接可以打开编辑

智慧交通day03-车道线检测实现04:车道线提取原理+代码实现+效果图

我们基于图像的梯度和颜色特征&#xff0c;定位车道线的位置。 在这里选用Sobel边缘提取算法&#xff0c;Sobel相比于Canny的优秀之处在于&#xff0c;它可以选择横向或纵向的边缘进行提取。从车道的拍摄图像可以看出&#xff0c;我们关心的正是车道线在横向上的边缘突变。Ope…