无人驾驶小车调试笔记(七)-- 相机校准

本文详细介绍了如何在ROS环境下使用OpenCV进行摄像头校准,以解决图像变形问题。通过棋盘格辅助,利用cv2.findChessboardCorners、cv2.cornerSubPix等函数获取内角点信息,然后使用cv2.calibrateCamera计算相机内参和畸变系数,最终通过cv2.undistort实现图像去畸变。此外,还讲述了如何保存和上传校准参数到小车,确保后续图像处理的准确性。

        简介:在第五节的内容中,我们学习了使用rqt工具集观看摄像头视频流的方法,细心的同学应该会发现camera_node发布的视频数据中的图像有变形现象,图像变形会导致直线不直,部分区域变大,部分区域缩小,导致无法准确计算出我们需要的数据,为了解决这个问题,我们需要先校准相机,另外在虚拟仿真的学习过程中,我们了解到在后续的图像处理过程中,我们还需要知道相机的内参矩阵,以及投影变换矩阵,在这一章节中,我们详细介绍这些参数的求取过程。

        在求取参数过程中,我们需要借助棋盘格来辅助完成相机的校准,我们使用的棋盘格大小是一张标准的A3纸的尺寸,样式如下图:

        棋盘格也标示了车辆的坐标系统。x轴向前正,y轴向左为正,如果你手上没有标准的棋盘格需要自制的话,有以下几个参数需要注意:

1、棋盘格为6(行)*8(列),我们实际使用的是内角点,所以后续配置参数为5*7

2、每个棋盘格中的小方块是标准的31mm,不能缩放

3、以车辆坐标为参考,棋盘格右下角坐标为(160mm,-124mm)

        未校准情况下,摄像头中的棋盘格如下图,明显存在变形,而我们需要的是横平竖直,格子大小相等的图像。

        在虚拟仿真环境中我们是通过虚拟仿真环境截取了一些棋盘格图像然后计算相关参数的,在真实环境中,我们可以手动来获取这些图像,然后统一加载图像再计算相关参数,为了减少工作量,我们通过编程实现一次性完成图像采集和参数的计算,具体流程如下:


        目录

1、创建工作空间以及功能包

2、主要功能函数说明

2.1 cv2.findChessboardCorners 查找图像中棋盘格角点信息

2.2 cv2.cornerSubPix 亚像素角点检测

2.3 cv2.drawChessboardCorners 绘制标定的角点

2.4 cv2.calibrateCamera 计算相机内参系数

2.5 cv2.getOptimalNewCameraMatrix 获取视场调节参数

2.6 cv2.undistort 图像去畸变

3、编程实现图像校准,计算校准参数

4、上传校准参数


1、创建工作空间以及功能包

由于需要采集图像,我们需要在ROS平台上完成以下功能,先创建新的ROS工作空间

$ cd ~
$ mkdir -p duckietown/catkin_ws/src
$ cd duckietown/catkin_ws/src
$ catkin_init_workspace
$ cd ..
$ catkin_make

新建摄像头校准功能包,并新建源码文件

$ cd src
$ catkin_create_pkg calibrate rospy sensor_msgs
$ touch calibrate/src/calibrate_node.py

修改编译配置文件如下图:

$ gedit calibrate/CMakeLists.txt


2、主要功能函数说明

2.1 cv2.findChessboardCorners 查找图像中棋盘格角点信息

retval, corners = cv.findChessboardCorners(image, patternSize[, corners[, flags]])

第一个参数Image,传入拍摄的棋盘图Mat图像,必须是8位的灰度或者彩色图像;

第二个参数patternSize,每个棋盘图上内角点的行列数,一般情况下,行列数不要相同,便于后续标定程序识别标定板的方向;

第三个参数corners,用于存储检测到的内角点图像坐标位置,一般是数组形式;

第四个参数flage:用于定义棋盘图上内角点查找的不同处理方式,有默认值。

返回值corners中包含了检测到的角点信息

2.2 cv2.cornerSubPix 亚像素角点检测

        为了提高标定精度,需要在初步提取的角点信息上进一步提取亚像素信息,降低相机标定偏差,常用的方法是cornerSubPix函数:

cv2.cornerSubPix(image, corners, winSize, zeroZone, criteria)

第一个参数image,输入图像的像素矩阵,最好是8位灰度图像,检测效率更高;

第二个参数corners,初始的角点坐标向量,同时作为亚像素坐标位置的输出,所以需要是浮点型数据;

第三个参数winSize,大小为搜索窗口的一半;

第四个参数zeroZone,死区的一半尺寸,死区为不对搜索区的中央位置做求和运算的区域。它是用来避免自相关矩阵出现某些可能的奇异性。当值为(-1,-1)时表示没有死区;

第五个参数criteria,定义求角点的迭代过程的终止条件,可以为迭代次数和角点精度两者的组合;

2.3 cv2.drawChessboardCorners 绘制标定的角点

        找到角点信息后,我们可以用 drawChessboardCorners函数用绘制被成功标定的角点:

cv2.drawChessboardCorners(image, patternSize, corners, patternWasFound)

第一个参数image,8位灰度或者彩色图像;

第二个参数patternSize,每张标定棋盘上内角点的行列数;

第三个参数corners,初始的角点坐标向量,同时作为亚像素坐标位置的输出,所以需要是浮点型数据;

第四个参数patternWasFound,标志位,用来指示定义的棋盘内角点是否被完整的探测到,true表示别完整的探测到,函数会用直线依次连接所有的内角点,作为一个整体,false表示有未被探测到的内角点,这时候函数会以(红色)圆圈标记处检测到的内角点;

2.4 cv2.calibrateCamera 计算相机内参系数

        获取到棋盘标定图的内角点图像坐标之后,就可以使用calibrateCamera函数进行标定,计算相机内参系数:

retval, cameraMatrix, distCoeffs, rvecs, tvecs = cv2.calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs[, rvecs[, tvecs[, flags[, criteria]]]])

第一个参数objectPoints,为世界坐标系中的三维点。需要依据棋盘上单个黑白矩阵的大小,计算出(初始化)每一个内角点的世界坐标;

第二个参数imagePoints,为每一个内角点对应的图像坐标点;

第三个参数imageSize,为图像的像素尺寸大小,在计算相机的内参和畸变矩阵时需要使用到该参数;

第四个参数cameraMatrix为相机的内参矩阵;

第五个参数distCoeffs为畸变矩阵;

第六个参数rvecs为旋转向量;

第七个参数tvecs为位移向量;

第八个参数flags为标定时所采用的算法。有如下几个参数:

CV_CALIB_USE_INTRINSIC_GUESS:使用该参数时,在cameraMatrix矩阵中应该有fx,fy,u0,v0的估计值。否则的话,将初始化(u0,v0)图像的中心点,使用最小二乘估算出fx,fy。

CV_CALIB_FIX_PRINCIPAL_POINT:在进行优化时会固定光轴点。当CV_CALIB_USE_INTRINSIC_GUESS参数被设置,光轴点将保持在中心或者某个输入的值。

CV_CALIB_FIX_ASPECT_RATIO:固定fx/fy的比值,只将fy作为可变量,进行优化计算。当CV_CALIB_USE_INTRINSIC_GUESS没有被设置,fx和fy将会被忽略。只有fx/fy的比值在计算中会被用到。

CV_CALIB_ZERO_TANGENT_DIST:设定切向畸变参数(p1,p2)为零。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

溪风沐雪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值