双目摄像头在SLAM中很常见,良好的标定结果能进一步提高SLAM的性能。本文基于MATLAB双目标定工具箱和普通的USB双目摄像头,进行了双目标定,并记录了整个过程及结果。
软件准备
MATLAB2019A
需要自行安装matlab USB摄像头驱动包,可以在MATLAB官网注册登录下载,也可以在本博客附件中下载。
双目摄像头
实验室翻出的蒙尘已久的双目摄像头,迷你小巧如下
视频流获取图片
win_info = imaqhwinfo('winvideo')
可以得到如下信息
由DeviceIDs字段可以知道总共有三个相机(双目包含两个相机,笔记本电脑自带一个前置相机)
进一步,分别查看三个相机的详细信息
从DeviceName字段可以知道,双目相机的DeviceID分别为2和3,这里选取格式是MJPG_320x240
根据上述信息编写获取双目相机图像并保存成jpg的matlab程序如下
clc;
clear all;
close all;
m_right = 320; %视频尺寸总宽度大小
n_right = 240; %视频尺寸总高度大小
vid_format_right = 'MJPG_320x240'; %视频格式
vid_right = videoinput('winvideo', 2, vid_format_right);
set(vid_right,'ReturnedColorSpace','rgb'); %设置视频颜色空间为RGB
vidRes_right=get(vid_right,'VideoResolution'); %取得视频分辨率大小
nBands_right=get(vid_right,'NumberOfBands'); %取得视频波段
h1_right = figure('Name', '右摄像头', 'NumberTitle', 'Off', 'ToolBar', 'None', 'MenuBar', 'None'); %获得窗口1 的句柄
hImage_right=image(zeros(vidRes_right(2),vidRes_right(1),nBands_right));
preview(vid_right,hImage_right); %在窗口1输出视频
m_left = 320; %视频尺寸总宽度大小
n_left = 240; %视频尺寸总高度大小
vid_format_left = 'MJPG_320x240'; %视频格式
vid_left = videoinput('winvideo', 3, vid_format_left);
set(vid_left,'ReturnedColorSpace','rgb'); %设置视频颜色空间为RGB
vidRes_left=get(vid_left,'VideoResolution'); %取得视频分辨率大小
nBands_left=get(vid_left,'NumberOfBands'); %取得视频波段
h1_left = figure('Name', '左摄像头', 'NumberTitle', 'Off', 'ToolBar', 'None', 'MenuBar', 'None'); %获得窗口1 的句柄
hImage_left=image(zeros(vidRes_left(2),vidRes_left(1),nBands_left));
preview(vid_left,hImage_left); %在窗口2输出视频
for k = 1 : 50 %拍摄图片的数量
w = waitforbuttonpress; %监控键盘输入
if w
while(~strcmpi(get(gcf, 'CurrentCharacter'),13))
frame_left = getsnapshot(vid_left); %获取视频快照
frame_right = getsnapshot(vid_right); %获取视频快照
% h2 = figure('Position',[0, 0, 100, 100]); %获得窗口2句柄
% imshow(frame_left); %窗口2显示左视频
% h3 = figure('Position',[0, 0, 100, 100]); %获得窗口3句柄
% imshow(frame_right); %窗口3显示右视频
name1 = strcat('left0',num2str(k),'.jpg'); %设置左图像名字
name2 = strcat('right0',num2str(k),'.jpg'); %设置右图像名字
imwrite(frame_left,name1,'jpg');% 保存帧
imwrite(frame_right,name2,'jpg');% 保存帧
break;
end
end
end
标定板及拍照
出于节约资源的考虑,本次标定使用显示器替代传统的纸质标定板。
首先制作一个电子黑白棋盘格,制作程序基于MATLAB编写。
下面的程序用于生成棋盘格,并将生成的图片保存只当前目录下,命名为:ChessBoard.bmp
本次标定使用PPT作为显示软件,因此将小方块的数目设定为16x9,PPT按照100%比例显示效果时候如下
取消PPT中选定后,就可以运行之前的MATLAB程序进行双目拍照。
(值得注意的是,MATLAB用于监测按键的函数似乎只能在自己是活动窗口的情况下才能正常保存图片,因此最好使用双显示器进行标定工作)
clc
clear all
% 每个方块的像素数
pixelPerBlock = 100;
% 棋盘上的小方块个数
boardSize.height = 9;
boardSize.width = 16;
% 整个棋盘的像素数
resolution.height = boardSize.height*pixelPerBlock;
resolution.width = boardSize.width*pixelPerBlock;
basisHeight = (resolution.height - pixelPerBlock*boardSize.height) / 2;
basisWidth = (resolution.width - pixelPerBlock*boardSize.width) / 2;
if basisHeight<0 || basisWidth<0
disp('Resolution is inappropriate ');
return
end
ChessBoard = 255*ones(resolution.height, resolution.width);
for j=1:1:boardSize.height
for i=1:1:boardSize.width
if mod(i+j,2)==0
ChessBoard((j-1)*pixelPerBlock+1:j*pixelPerBlock,(i-1)*pixelPerBlock+1:i*pixelPerBlock) = 0;
end
end
end
imshow(ChessBoard)
imwrite(ChessBoard,'ChessBoard.bmp')
运行标定工具箱
直接运行stereoCameraCalibrator命令,会打开该工具箱界面,依据左边提示,建立文件夹分别保存左相机和右相机所拍摄的图片,并输入目录,修改 Size of checkerboard square 为 25, 如下图
Size of checkerboard square = 25 是在PPT放映时,用刻度尺在屏幕上量取的
启动,稍等一小会儿后得到如下结果,我们共获取了49对棋盘的照片,经检查后全部被成功标记棋盘格的位置和并正确识别格点。
而后,修改上方标签栏中的OPTIONS选项,选定 Radial Distortion 中的 3 Coefficients 和 Compute中的 Tangential Distortion, 界面如下图所示
点击绿色的 Calibrate 按钮,执行标定任务,用鼠标向下拖动左下方柱状图里的水平红线,减小outlier的影响。经过调整,我们将 Overall Mean Error 降低至 0.09 pixels,对应的左边误差不满足条件的图片对会被自动选中,鼠标右键将其删除,再来一次标定
点击 Show Rectified 按钮,可以显示矫正前后的效果,可以看到经过校正后,水平线可以连接左右相机的相同特征,如下图所示
点击 Export Camera Parameters 按钮,可以将标定参数导出至 workspace
标定结果
有坑预警:
- 标定出来的相机内参不能直接使用,需要将其进行转置,得到如下形式
- 畸变参数的排放顺序,即K1,K2,P1,P2,K3
左相机内参
stereoParams.CameraParameters1.IntrinsicMatrix
左相机径向畸变(K1, K2, K3)
stereoParams.CameraParameters1.RadialDistortion
左相机切向畸变(P1, P2)
stereoParams.CameraParameters1.TangentialDistortion
右相机内参
stereoParams.CameraParameters2.IntrinsicMatrix
右相机径向畸变(K1, K2, K3)
stereoParams.CameraParameters2.RadialDistortion
右相机切向畸变(P1, P2)
stereoParams.CameraParameters2.TangentialDistortion
两个摄像头的旋转参数
stereoParams.RotationOfCamera2
两个摄像头的平移参数
stereoParams.TranslationOfCamera2
至此,获得了所有的标定结果。