ADAS-CIS相机内外参模型与标定实战

前言

原文发表于我的公众号:ADAS之眼,链接原文连接

“ CIS可见光相机是ADAS的眼睛,而相机标定则是其应用的基础,本文为初学者讲述了相机标定的模型以及逻辑,最后使用opencv中自带的例程演示了相机标定的demo。”

01 相机模型

1.1 模型概述

初中物理我们便学习了基础的小孔成像原理,现实生活中的蜡烛经过小孔之后,在小孔背面形成了物体倒立的投影,如下所示:

在这里插入图片描述
本质上,相机模型与小孔成像原理一样,不同的是,在真实的相机应用中:

  • 由于镜头的畸变,使得投射到相机平面的光线会产生畸变,因此图像会存在平行于像面的径向畸变;
  • 由于相机水平以及垂直方向安装的误差,导致相机的光心并不是在相机的正中心;
  • 由于相机安装的角度的误差,导致相机并不是垂直于镜头安装的,因此相机存在切向畸变

1.2 数学模型

真实的物理世界中一点Pw,我们可通过(Xw,Yw,Zw)进行具体定位。而相对于真实物理世界而言,相机世界中有三个坐标系,相机世界坐标系、物理成像坐标系以及像素坐标系,而相机标定的本质是找到一个数据模型,完成下图的转变:

在这里插入图片描述相机世界三个坐标系的关系如下所示:

在这里插入图片描述
其中:

  • P是相机世界坐标系中的一点,坐标为(X,Y,Z);
  • O是针孔成像中的光心,也就是相机世界坐标系的原点(0,0,0);
  • P’是P经过针孔模型后在物理成像坐标系中投影的点,坐标为(X’,Y’);
  • f是焦距,即现实相机中镜头的焦距。

在不考虑畸变的理想情况下,P点以及P’点分别在世界坐标系以及物理成像坐标系形成了相似三角形:在这里插入图片描述根据相似三角形我们可以获取如下关系:

在这里插入图片描述
将上式整理可以得到P’点X’以及Y’的坐标值为:
在这里插入图片描述
这里完成了相机世界坐标系到物理成像坐标系的转换。现在在物理成像平面中有一个像素平面o-u-v,其中o是图像左上角原点,u、v分别与是物理成像坐标系的x、y轴平行。因此可以看出,o-u-v坐标系是经过物理成像坐标系X’-Y’缩放加平移过来的。
现在假设P’在像素平面的坐标为(u,v),u、v轴的缩放系数分别为α和β,原点平移了(cx,cy)的话,那么物理成像坐标系中P’点转化成像素坐标系的关系如下:
在这里插入图片描述
把X’和Y’带入,并把αf以及βf统一成fx以及fy可以得到:
在这里插入图片描述
将上式转换成矩阵的形式如下:
在这里插入图片描述
其中K是内参、T是外参,T的一般形式为:
[R, t]
至此,理想相机模型已经推导出来了。

1.3 畸变模型

在1.1中我们提到了真实相机存在各种各样的畸变以及安装误差。首先我们看由于镜头的不完美导致的径向畸变,它主要分为两种:桶形畸变以及枕形畸变,如下图所示:

在这里插入图片描述

在研究生课程数值分析中我们学习过非线性多项式拟合,而径向畸变刚好可以用多阶多项式进行拟合,经过校正的Xcorrect以及ycorrect拟合多项式可以如下表示:

在这里插入图片描述

可以看出,对于畸变比较小的中心区域,k1起到了主要作用,而对于畸变比较大的边缘区域,主要是k2在起作用。普通相机k1、k2便可以很好地校准畸变,对于畸变较大的鱼眼相机,往往还需要k3进行校正。
切向畸变来源于镜头、sensor安装的偏差,最直观来源的如下图所示:
在这里插入图片描述
对于切向畸变,我们可以使用另外两个参数p1以及p2进行校准,如下所示:

在这里插入图片描述
结合径向畸变以及切向畸变,可以得到最终的校准公式如下:
在这里插入图片描述
最终,我们将纠正的坐标通过内参矩阵进行计算,便可得到其在图像正确的位置:
在这里插入图片描述
至此,相机内参模型已经讲清楚。下面,我们使用opencv自带的历程,真实的跑一下相机标定的demo。

02 OpenCV标定demo

2.1 开发环境

软件开发环境:

ubuntu20.04
vs code
opencv
cmake
g++
make

软件安装:

sudo apt-get install make cmake gcc g++ git

opencv源码编译安装:

git clone https://github.com/opencv/opencv.git #拉最新源码
cd opencv
mkdir build
cd build/
cmake .. #等待漫长的下载以及配置
make -j12 #具体编译线程数按照自己电脑情况来,然后等待执行完毕
sudo make install

将./opencv/samples/cpp/tutorial_code/calib3d/camera_calibration/目录下面的所有文件复制到你的工作目录下面:

camera_calibration.cpp  in_VID5.xml  out_camera_data.yml  VID5.xml

在工作目录下新建build目录,然后复制./opencv/samples/data/left*.jpg图像到工作目录的build下。

2.2 编译运行demo

在工作目录下新建CMakeLists.txt,内容参考如下:

# cmake needs this line
cmake_minimum_required(VERSION 3.1)
# Define project name
project(opencv_example_project)
# Find OpenCV, you may need to set OpenCV_DIR variable
# to the absolute path to the directory containing OpenCVConfig.cmake file
# via the command line or GUI
find_package(OpenCV REQUIRED)
# If the package has been found, several variables will
# be set, you can find the full list with descriptions
# in the OpenCVConfig.cmake file.
# Print some message showing some of them
message(STATUS "OpenCV library status:")
message(STATUS "    config: ${OpenCV_DIR}")
message(STATUS "    version: ${OpenCV_VERSION}")
message(STATUS "    libraries: ${OpenCV_LIBS}")
message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")
# Declare the executable target built from your sources
add_executable(calibration camera_calibration.cpp)
# Link your application with OpenCV libraries
target_link_libraries(calibration PRIVATE ${OpenCV_LIBS})

然后在build目录下执行:

cmake ..
make

编译完毕之后,因为文件路径变动,因此需要修改VID5.xml以及in_VID5.xml文件,VID5.xml存储了需要标定哪些图像:

<?xml version="1.0"?>
<opencv_storage>
<images>
left01.jpg
left02.jpg
left03.jpg
left04.jpg
left05.jpg
left06.jpg
left07.jpg
left08.jpg
</images>
</opencv_storage>

in_VID5.xml主要修改点在于VID5.xml的位置

 <Calibrate_Pattern>"CHESSBOARD"</Calibrate_Pattern>

  <!-- The input to use for calibration. 
    To use an input camera -> give the ID of the camera, like "1"
    To use an input video  -> give the path of the input video, like "/tmp/x.avi"
    To use an image list   -> give the path to the XML or YAML file containing the list of the images, like "/tmp/circles_list.xml"
    -->
  <Input>"VID5.xml"</Input>
  <!--  If true (non-zero) we flip the input images around the horizontal axis.-->
  <Input_FlipAroundHorizontalAxis>0</Input_FlipAroundHorizontalAxis>

  <!-- Time delay between frames in case of camera. -->
  <Input_Delay>100</Input_Delay>

修改之后,运行demo如下:

./cabraition ./in_VID5.xml

此时运行便会提取图像中的角点进行校准,标定完毕之后会显示畸变校准后的图像:
在这里插入图片描述
在app目录下会生成out_camera_data.xml,其中相机参数如下:

<camera_matrix type_id="opencv-matrix">
  <rows>3</rows>
  <cols>3</cols>
  <dt>d</dt>
  <data>
    5.4340333589622401e+02 0. 3.1950000000000000e+02 0.
    5.4340333589622401e+02 2.3950000000000000e+02 0. 0. 1.</data></camera_matrix>
<distortion_coefficients type_id="opencv-matrix">
  <rows>5</rows>
  <cols>1</cols>
  <dt>d</dt>
  <data>
    -3.0200616231670130e-01 1.5646925098754344e-01 0. 0.
    -6.5880224677954125e-02</data></distortion_coefficients>

其中,camera_matrix 33即相机内参,distortion_coeffiecients 51即为相机畸变参数,至此相机demo演示完毕。

本文介绍了相机模型以及内外参数的含义,并使用opencv的demo做了一次标定的流程,如果想要直接可运行的源码可以后台私信,希望对使用相机的初学者有一定的帮助。

03 结束语

本文介绍了相机模型以及内外参数的含义,并使用opencv的demo做了一次标定的流程,如果想要直接可运行的源码可以后台私信,希望对使用相机的初学者有一定的帮助。

另外,欢迎关注我的公众号ADAS之眼,第一时间更新动态。
在这里插入图片描述

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
相机内外标定是通过对相机进行一系列实验和计算,得到相机的内部数(如焦距、主点坐标等)和外部数(如相机的旋转矩阵和平移矩阵),以便后续的图像处理和校正。在Matlab中,可以使用相机标定工具箱来进行相机内外数的标定。 首先,需要导入相机的图片数据。可以使用双目相机或单目相机的图片。在双目相机标定中,需要导入左右相机的图片。然后,通过点击相机标定工具箱中的相应按钮,开始进行标定。在标定过程中,会检测特征点(角点),计算平均重投影误差等。标定结束后,可以保存相机数。 在Matlab中,可以使用OpenCV中的stereoRectify函数来获得其他数矩阵,如校正旋转矩阵Rl、Rr、重投影矩阵Q、投影矩阵P等。这些数可以用于图像的校正和处理。 使用以上代码求出的相机数后,可以对使用相机拍摄的照片进行校正。可以使用Matlab自带的undistortImage函数来进行校正。校正之后的照片可以显示出更准确的图像。 总结起来,相机内外标定是通过实验和计算得到相机的内部数和外部数,以便后续的图像处理和校正。在Matlab中,可以使用相机标定工具箱进行标定,并使用OpenCV函数获得其他数矩阵。校正之后的照片可以使用Matlab自带的函数进行显示。 #### 引用[.reference_title] - *1* *3* [实验1:使用Matlab工具箱进行相机标定实验](https://blog.csdn.net/WKX_5/article/details/125810513)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [使用Matlab做相机标定(获取相机内外数矩阵)](https://blog.csdn.net/weixin_45718019/article/details/105823053)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值