MATLAB相机标定的使用并导出XML文件
前言
MATLAB的相机标定工具cameraCalibrator位于Computer Vision toolBox,在命令行输入cameraCalibrator,并回车即可启动GUI界面,可视化做得很友好,而且要比opencv中的相机标定准确度要高,运行速度要快(自己体会),下面介绍一下如何使用,以及如何将标定好的参数导出为XML文件,以供opencv读入。
目录
MATLAB相机标定的使用
准备工作
打印一种黑白棋盘图像,在MATLAB中的帮助文档中已经为我们准备好了一个pdf文件(MATLAB安装目录\MATLAB\R201xa(b)\help\toolbox\vision\examples\checkerboardPattern.pdf),这是一张黑白棋盘图像,我们找到它,打印即可。
下一步就是用相机进行拍照,从不同的角度进行拍照,为了达到较高的精度,图片的数目至少要20张左右。我用自己的手机拍了17张照片。(注意拍照时的分辨率要固定,且图片的尺寸要一致!)
相机标定
步骤:
启动:cameraCalibrator回车
add images
设置棋盘格的尺寸(mm),提前量一下。
设置参数。包括径向畸变参数的个数(2/3)、是否计算切向畸变。我的设置分别是3、是。
开始标定
参数导出,保存的参数是一种特殊的数据结构,里面包含了相机内参(IntrinsicMatrix)、径向畸变(RadialDistortion)、切向畸变(TangentialDistortion)、相机的外参(RotationMatrices,TranslationVectors)等。
上面是一张截图,右侧还可以将每一张图片对应的相机外参以三维立体图的形式展现。
导出XML文件
通过编写MATLAB函数向相机标定的内参和畸变参数保存为opencv可以读取的XML文件
function writeXML(cameraParams,file)
%writeXML(cameraParams,file)
%功能:将相机校正的参数保存为xml文件
%输入:
%cameraParams:相机校正数据结构
%file:xml文件名
%说明在xml文件是由一层层的节点组成的。
%首先创建父节点 fatherNode,
%然后创建子节点 childNode=docNode.createElement(childNodeName),
%再将子节点添加到父节点 fatherNode.appendChild(childNode)
docNode = com.mathworks.xml.XMLUtils.createDocument('opencv_storage'); %创建xml文件对象
docRootNode = docNode.getDocumentElement; %获取根节点
IntrinsicMatrix = (cameraParams.IntrinsicMatrix)'; %相机内参矩阵
RadialDistortion = cameraParams.RadialDistortion; %相机径向畸变参数向量1*3
TangentialDistortion =cameraParams.TangentialDistortion; %相机切向畸变向量1*2
Distortion = [RadialDistortion(1:2),TangentialDistortion,RadialDistortion(3)]; %构成opencv中的畸变系数向量[k1,k2,p1,p2,k3]
camera_matrix = docNode.createElement('camera-matrix'); %创建mat节点
camera_matrix.setAttribute('type_id','opencv-matrix'); %设置mat节点属性
rows = docNode.createElement('rows'); %创建行节点
rows.appendChild(docNode.createTextNode(sprintf('%d',3))); %创建文本节点,并作为行的子节点
camera_matrix.appendChild(rows); %将行节点作为mat子节点
cols = docNode.createElement('cols');
cols.appendChild(docNode.createTextNode(sprintf('%d',3)));
camera_matrix.appendChild(cols);
dt = docNode.createElement('dt');
dt.appendChild(docNode.createTextNode('d'));
camera_matrix.appendChild(dt);
data = docNode.createElement('data');
for i=1:3
for j=1:3
data.appendChild(docNode.createTextNode(sprintf('%.16f ',IntrinsicMatrix(i,j))));
end
data.appendChild(docNode.createTextNode(sprintf('\n')));
end
camera_matrix.appendChild(data);
docRootNode.appendChild(camera_matrix);
distortion = docNode.createElement('distortion');
distortion.setAttribute('type_id','opencv-matrix');
rows = docNode.createElement('rows');
rows.appendChild(docNode.createTextNode(sprintf('%d',5)));
distortion.appendChild(rows);
cols = docNode.createElement('cols');
cols.appendChild(docNode.createTextNode(sprintf('%d',1)));
distortion.appendChild(cols);
dt = docNode.createElement('dt');
dt.appendChild(docNode.createTextNode('d'));
distortion.appendChild(dt);
data = docNode.createElement('data');
for i=1:5
data.appendChild(docNode.createTextNode(sprintf('%.16f ',Distortion(i))));
end
distortion.appendChild(data);
docRootNode.appendChild(distortion);
xmlFileName = file;
xmlwrite(xmlFileName,docNode);
end
在命令行输入:
writeXML(cameraParams,'cameraParams.xml');
就完成了将相机内参和畸变参数保存问XML文件。
以下是导出到XML文件内容:
<?xml version="1.0" encoding="utf-8"?>
<opencv_storage>
<camera-matrix type_id="opencv-matrix">
<rows>3</rows>
<cols>3</cols>
<dt>d</dt>
<data>3099.7082447931371000 0.0000000000000000 1077.7535540640906000
0.0000000000000000 3086.4434775466948000 1826.5450377846478000
0.0000000000000000 0.0000000000000000 1.0000000000000000
</data>
</camera-matrix>
<distortion type_id="opencv-matrix">
<rows>5</rows>
<cols>1</cols>
<dt>d</dt>
<data>-0.0890744873306951 5.1317176243308209 -0.0051019418392772 -0.0021081150992697 -39.0645994879151530 </data>
</distortion>
</opencv_storage>
上面的函数只导出了相机内参和畸变参数,其它参数没有导出。
经过测试,可以从opencv中使用FileStorage读取。