众所周知,OpenCV封装了很多用于相机标定的函数,其输出的标定结果可以利用FileStorage
对象进行保存,存储为XML格式的参数文件。考虑到很多时候图像算法的开发会在MATLAB上进行,但如果此时标定结果是通过OpenCV输出的XML格式文件,那就需要将其转换为MATLAB下的标定参数项,用于实现物像间的相互投影。
如果您对于标定感兴趣,欢迎阅读我有关三维重建的其他帖子
一.OpenCV输出的相机标定结果
我的是双目场景,所以保存的相机标定文件如下:
1.系统内参
<?xml version="1.0"?>
<opencv_storage>
<M1 type_id="opencv-matrix">
<rows>3</rows>
<cols>3</cols>
<dt>d</dt>
<data>
3.9701338904272438e+03 0. 2.0500817357209139e+03 0.
3.9713734186383799e+03 1.5158522192251232e+03 0. 0. 1.</data></M1>
<D1 type_id="opencv-matrix">
<rows>1</rows>
<cols>14</cols>
<dt>d</dt>
<data>
-8.8331615813046951e-02 1.5627638628530921e-01 0. 0. 0. 0. 0.
1.7324943467730536e-01 0. 0. 0. 0. 0. 0.</data></D1>
<M2 type_id="opencv-matrix">
<rows>3</rows>
<cols>3</cols>
<dt>d</dt>
<data>
3.9720838692180810e+03 0. 2.0949942840707954e+03 0.
3.9695208961298167e+03 1.5360078062523207e+03 0. 0. 1.</data></M2>
<D2 type_id="opencv-matrix">
<rows>1</rows>
<cols>14</cols>
<dt>d</dt>
<data>
-9.0821946215952201e-02 1.0037847762123603e-01 0. 0. 0. 0. 0.
8.2862211035650470e-03 0. 0. 0. 0. 0. 0.</data></D2>
<RMS>4.9464698126500511e-01</RMS>
<AverageEpipolar>6.6617614369333522e-01</AverageEpipolar>
</opencv_storage>
2.左右相机位置关系
<?xml version="1.0"?>
<opencv_storage>
<R type_id="opencv-matrix">
<rows>3</rows>
<cols>3</cols>
<dt>d</dt>
<data>
9.9994570064493338e-01 3.5256714054780481e-04 1.0414963184031090e-02
-3.3996164319258492e-04 9.9999920765433969e-01
-1.2120712742900086e-03 -1.0415382268283526e-02
1.2084647716036874e-03 9.9994502820160136e-01</data></R>
<T type_id="opencv-matrix">
<rows>3</rows>
<cols>1</cols>
<dt>d</dt>
<data>
-1.8137611444601779e+02 6.2436256551722868e-01
-1.7895289626902058e+00</data></T>
<R1 type_id="opencv-matrix">
<rows>3</rows>
<cols>3</cols>
<dt>d</dt>
<data>
9.9978952374915520e-01 -3.0777026782043996e-03
2.0283883939276590e-02 3.0897783453807926e-03 9.9999506756326084e-01
-5.6402032383557265e-04 -2.0282048003441008e-02
6.2657431630820442e-04 9.9979410176966554e-01</data></R1>
<R2 type_id="opencv-matrix">
<rows>3</rows>
<cols>3</cols>
<dt>d</dt>
<data>
9.9994540663043718e-01 -3.4421758419939546e-03
9.8658595247731150e-03 3.4363017230338356e-03 9.9999390844821801e-01
6.1228826971087137e-04 -9.8679070302692823e-03
-5.7835277274689758e-04 9.9995114376599037e-01</data></R2>
<P1 type_id="opencv-matrix">
<rows>3</rows>
<cols>4</cols>
<dt>d</dt>
<data>
3.7838927439960389e+03 0. 1.9967377471923828e+03 0. 0.
3.7838927439960389e+03 1.5255002746582031e+03 0. 0. 0. 1. 0.</data></P1>
<P2 type_id="opencv-matrix">
<rows>3</rows>
<cols>4</cols>
<dt>d</dt>
<data>
3.7838927439960389e+03 0. 1.9967377471923828e+03
-6.8634523328545038e+05 0. 3.7838927439960389e+03
1.5255002746582031e+03 0. 0. 0. 1. 0.</data></P2>
<Q type_id="opencv-matrix">
<rows>4</rows>
<cols>4</cols>
<dt>d</dt>
<data>
1. 0. 0. -1.9967377471923828e+03 0. 1. 0. -1.5255002746582031e+03 0.
0. 0. 3.7838927439960389e+03 0. 0. 5.5131041354844253e-03 0.</data></Q>
</opencv_storage>
二.MATLAB加载OpenCV标定文件函数
函数可以读取路径下的内外参结果,并将数据整理成为MATLAB下标准的stereo calib的参数项,OpenCV利用FileStorage
对象保存的其他XML文件也可以用该函数中的方式去进行解析读取。
注:MATLAB下标准的内参矩阵与常规算术推导时用的内参矩阵恰好是转置的关系,如有疑问,建议尝试使用MATLAB Stereo Camera Calibrator App进行对比验证测试
function stereoParams = LoadOpenCVCameraP(In_Filename, Ex_Filename)
% 读取OpenCV下的标定文件
%
% INPUT: In_Filename 内参结果路径
% Ex_Filename 外参结果路径
%
% OUTPUT: stereoParams 双目系统标定参数
% ==============================================
intrinsicsDoc = xmlread(In_Filename);
extrinsicsDoc = xmlread(Ex_Filename);
% 左相机内参
M1xml=char(intrinsicsDoc.getElementsByTagName('data').item(0).getFirstChild.getData);
M1=str2double(strsplit(strtrim(M1xml)));
LeftcameraMat=reshape(M1,3,3);
% 左相机畸变参数
D1xml=char(intrinsicsDoc.getElementsByTagName('data').item(1).getFirstChild.getData);
LeftcameraD=str2double(strsplit(strtrim(D1xml)));
LeftcameraD(LeftcameraD==0)=[];
CameraParameters1=cameraParameters("IntrinsicMatrix",LeftcameraMat,"RadialDistortion",LeftcameraD,...
"NumRadialDistortionCoefficients",3);
% 右相机内参
M2xml=char(intrinsicsDoc.getElementsByTagName('data').item(2).getFirstChild.getData);
M2=str2double(strsplit(strtrim(M2xml)));
RightcameraMat=reshape(M2,3,3);
% 右相机畸变参数
D2xml=char(intrinsicsDoc.getElementsByTagName('data').item(3).getFirstChild.getData);
RightcameraD=str2double(strsplit(strtrim(D2xml)));
RightcameraD(RightcameraD==0)=[];
CameraParameters2=cameraParameters("IntrinsicMatrix",RightcameraMat,"RadialDistortion",RightcameraD,...
"NumRadialDistortionCoefficients",3);
% 读取旋转矩阵
Rxml=char(extrinsicsDoc.getElementsByTagName('data').item(0).getFirstChild.getData);
R=reshape(str2double(strsplit(strtrim(Rxml))),3,3);
% 读取平移向量
Txml=char(extrinsicsDoc.getElementsByTagName('data').item(1).getFirstChild.getData);
T=reshape(str2double(strsplit(strtrim(Txml))),1,3);
% 整理数据
stereoParams=stereoParameters(CameraParameters1,CameraParameters2,R,T);
end
三.结果展示
版权声明:本文为weixin_43560489原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。