通过matlab进行立体标定并导出为opencv可加载文件

本文参考、鸣谢:

Matlab的相机标定数据导入OpenCV - 知乎

相机标定与矫正opencv+MATLAB - 当年煮酒论英雄 - 博客园

Matlab标定_opencv立体校正_u011393762的博客-优快云博客

本文测试matlab版本为2020a

双目标定:

最新版本标定工具是以app方式出现的。打开matlab后,APP展开搜索 calibrator,会出现单目摄像机标定APP 和 立体摄像机标定APP,双目标定使用第二个。

 

打开app后,第一步加载标定图像

 需要将两个摄像机的标定图片分开两个文件夹存放,并保证文件数量相同并且拍摄时刻一一对应。选择文件夹选项下面,可以设置棋盘格边长和单位,如果需要后续视差数据生成点云图,需要按实际长度填写。如果只是看效果,使用默认即可。

加载完成后,标定图像会成对出现在工具左侧列表

 matlab会自动配对,可以逐一点击查看一下,如果有配对错误,请调整标定图片后重新加载。

加载完图片后,就可以直接点击标定了,为了取得较好的效果,需要对标定进行一点设置。

 INTRINSICS:内参设置

        单选框 分别是 计算内参矩阵 和 使用固定内参矩阵 。

OPTIONS:

      Radial Distortion:  "径向畸变",可以指定2(k1,k2)或3个(k1,k2,k3)径向失真系数。当光线在透镜边缘的弯曲程度大于在透镜光学中心的弯曲程度时,就会发生径向畸变。镜头越小,失真越大。通常,两个系数足以进行校准。对于严重失真,例如在广角镜头中,可以选择3个系数来包括k3。

        Skew:“计算扭曲”,选中“计算扭曲”复选框时,校准器将估计图像轴扭曲。一些相机传感器存在缺陷,导致图像的x轴和y轴不垂直。可以使用skew参数对此缺陷建模。如果未选中该复选框,则假定图像轴垂直,现代相机大多数摄像机是这样。        

        Tangential Distortion:当透镜和图像平面不平行时,会发生切向失真。切向畸变系数模拟了这种畸变。选中“计算切向失真”复选框时,校准器将估计切向失真系数。否则,校准器将切向畸变系数设置为零。切向畸变有D1,D2两个参数。

 设置好以后,点击标定:

标定完成后,校正结果满意的话,就可以将标定结果导出到 matlab命令行主界面了。

 

 

 工作区里的stereoParams_opencv结构,是我们导出的标定参数信息。里面的信息很丰富。

opencv立体校正需要6个矩阵,相机1内参M1、畸变系数D1、相机2内参M2,畸变系数D2,旋转矩阵R,平移矩阵T。

标定参数导出为xml格式。

我们通过脚本将这6个矩阵存储到opencv可以读取的xml格式文件里。

脚本文件export_stereoParams_to_Opencv.m如下:

function ExportStereoParamsOpenCV(stereoParams, file)
% ExportStereoParams2OpenCV(cameraParams, file)
% 功能:将双目相机标定的参数保存为OpenCV可读取的xml文件
% 输入:
%   stereoParams:双目相机标定数据的对象
%   file:输出的xml文件名
% xml文件是由一层层的节点组成的。
% 首先创建父节点 fatherNode,
% 然后创建子节点 childNode=docNode.createElement(childNodeName),
% 再将子节点添加到父节点 fatherNode.appendChild(childNode)

%创建xml文件对象,添加opencv存储标识
doc = com.mathworks.xml.XMLUtils.createDocument('opencv_storage');
docRootNode = doc.getDocumentElement; %获取根节点

M1 = (stereoParams.CameraParameters1.IntrinsicMatrix).'; % 右相机内参矩阵,需要装置为左乘的矩阵
RadialDistortion1 = stereoParams.CameraParameters1.RadialDistortion; % 右相机径向畸变参数向量1*3
TangentialDistortion1 =stereoParams.CameraParameters1.TangentialDistortion; % 右相机切向畸变向量1*2
D1 = zeros(1,5); % OpenCV的畸变参数矩阵最多可以有14个参数
D1(1:4) = [RadialDistortion1(1:2), TangentialDistortion1]; %构成opencv中的畸变系数向量[k1,k2,p1,p2,k3]
if (size(RadialDistortion1,2)>2 )
    D1(5) = RadialDistortion1(3);
end

M2 = (stereoParams.CameraParameters2.IntrinsicMatrix).'; % 右相机内参矩阵,需要装置为左乘的矩阵
RadialDistortion2 = stereoParams.CameraParameters2.RadialDistortion; % 右相机径向畸变参数向量1*3
TangentialDistortion2 =stereoParams.CameraParameters2.TangentialDistortion; % 右相机切向畸变向量1*2
D2 = zeros(1,5);
D2(1:4) = [RadialDistortion2(1:2), TangentialDistortion2]; %构成opencv中的畸变系数向量[k1,k2,p1,p2,k3]
if (size(RadialDistortion1,2)>2 )
    D2(5) = RadialDistortion2(3);
end

R = (stereoParams.RotationOfCamera2).';
T = (stereoParams.TranslationOfCamera2).';
sizeImage = stereoParams.CameraParameters1.ImageSize;

AddMat(sizeImage, 'size', doc, docRootNode);
AddMat(M1, 'M1', doc, docRootNode);
AddMat(D1, 'D1', doc, docRootNode);
AddMat(M2, 'M2', doc, docRootNode);
AddMat(D2, 'D2', doc, docRootNode);
AddMat(R, 'R', doc, docRootNode);
AddMat(T, 'T', doc, docRootNode);

xmlwrite(file, doc);

end

function AddMat(A, name, doc, docRootNode)

mat = doc.createElement(name); %创建mat节点

mat.setAttribute('type_id','opencv-matrix'); %设置mat节点属性

rows = doc.createElement('rows'); %创建行节点
rows.appendChild(doc.createTextNode(sprintf('%d',size(A,1)))); %创建文本节点,并作为行的子节点
mat.appendChild(rows); %将行节点作为mat子节点

cols = doc.createElement('cols');
cols.appendChild(doc.createTextNode(sprintf('%d',size(A,2))));
mat.appendChild(cols);

dt = doc.createElement('dt');
dt.appendChild(doc.createTextNode('d'));
mat.appendChild(dt);

data = doc.createElement('data');
for i=1:size(A,1)
    for j=1:size(A,2)
        data.appendChild(doc.createTextNode(sprintf('%.15f ',A(i,j))));
    end
    data.appendChild(doc.createTextNode(sprintf('\n')));
end
mat.appendChild(data);
docRootNode.appendChild(mat);

end

切换matlab目录到export_stereoParams_to_Opencv.m所在路径,拷贝文件到当前目录。

在命令行执行

 export_stereoParams_to_Opencv(stereoParams_opencv, "matlabStereoParam.yml")

 得到matlabStereoParam.yml文件,可直接通过opencv读取。

<?xml version="1.0" encoding="utf-8"?>
<opencv_storage>
   <size type_id="opencv-matrix">
      <rows>1</rows>
      <cols>2</cols>
      <dt>d</dt>
      <data>640.000000000000000 480.000000000000000 
</data>
   </size>
   <M1 type_id="opencv-matrix">
      <rows>3</rows>
      <cols>3</cols>
      <dt>d</dt>
      <data>247.436791595622651 0.000000000000000 206.269175103342491 
0.000000000000000 252.130614650075444 331.280927054414292 
0.000000000000000 0.000000000000000 1.000000000000000 
</data>
   </M1>
   <D1 type_id="opencv-matrix">
      <rows>1</rows>
      <cols>5</cols>
      <dt>d</dt>
      <data>-0.239509548357768 0.034758655044619 -0.001295109814602 0.001841176318709 0.000000000000000 
</data>
   </D1>
   <M2 type_id="opencv-matrix">
      <rows>3</rows>
      <cols>3</cols>
      <dt>d</dt>
      <data>246.298543520481644 0.000000000000000 187.776278041563415 
0.000000000000000 252.018371898686297 311.080030357984640 
0.000000000000000 0.000000000000000 1.000000000000000 
</data>
   </M2>
   <D2 type_id="opencv-matrix">
      <rows>1</rows>
      <cols>5</cols>
      <dt>d</dt>
      <data>-0.240170028528280 0.035205469383591 -0.000624101429000 0.003366535858464 0.000000000000000 
</data>
   </D2>
   <R type_id="opencv-matrix">
      <rows>3</rows>
      <cols>3</cols>
      <dt>d</dt>
      <data>0.996084341727677 0.009050071748308 0.087943620384255 
-0.008791440516103 0.999955817302695 -0.003327764437357 
-0.087969851304815 0.002541582941630 0.996119895202159 
</data>
   </R>
   <T type_id="opencv-matrix">
      <rows>3</rows>
      <cols>1</cols>
      <dt>d</dt>
      <data>-24.416826406087150 
0.371078172361293 
1.036212681563079 
</data>
   </T>
</opencv_storage>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

蜡笔小心点

你的鼓励是我创造的动力

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

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

打赏作者

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

抵扣说明:

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

余额充值