一、Matlab标定双目相机
% Auto-generated by stereoCalibrator app on 08-Jun-2022
%-------------------------------------------------------
%%%%%%%修改图像路径以及保存文件路径%%%%%%%%%%%%%%%
% Define images to process
%%01读取图像
imageFileNames1 = {'C:\Users\kurn\Desktop\mycamera\3D\photo\left\134502.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\left\134519.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\left\134534.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\left\134544.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\left\134553.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\left\134610.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\left\134627.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\left\134651.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\left\134708.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\left\134730.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\left\134743.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\left\134855.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\left\134915.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\left\135005.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\left\135029.bmp',...
};
imageFileNames2 = {'C:\Users\kurn\Desktop\mycamera\3D\photo\right\134502.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\right\134519.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\right\134534.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\right\134544.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\right\134553.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\right\134610.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\right\134627.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\right\134651.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\right\134708.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\right\134730.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\right\134743.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\right\134855.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\right\134915.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\right\135005.bmp',...
'C:\Users\kurn\Desktop\mycamera\3D\photo\right\135029.bmp',...
};
% Detect checkerboards in images
%%02标定相机
[imagePoints, boardSize, imagesUsed] = detectCheckerboardPoints(imageFileNames1, imageFileNames2);
% Generate world coordinates of the checkerboard keypoints
squareSize = 20; % in units of 'millimeters'
worldPoints = generateCheckerboardPoints(boardSize, squareSize);
% Read one of the images from the first stereo pair
I1 = imread(imageFileNames1{1});
[mrows, ncols, ~] = size(I1);
% Calibrate the camera
[stereoParams, pairsUsed, estimationErrors] = estimateCameraParameters(imagePoints, worldPoints, ...
'EstimateSkew', true, 'EstimateTangentialDistortion', true, ...
'NumRadialDistortionCoefficients', 3, 'WorldUnits', 'millimeters', ...
'InitialIntrinsicMatrix', [], 'InitialRadialDistortion', [], ...
'ImageSize', [mrows, ncols]);
% View reprojection errors
%%03查看标定结果
h1=figure; showReprojectionErrors(stereoParams);
% Visualize pattern locations
h2=figure; showExtrinsics(stereoParams, 'CameraCentric');
% Display parameter estimation errors
displayErrors(estimationErrors, stereoParams);
% You can use the calibration data to rectify stereo images.
I2 = imread(imageFileNames2{1});
[J1, J2] = rectifyStereoImages(I1, I2, stereoParams,'OutputView', 'full');
figure; imshowpair(I1, I2, 'montage');title("矫正前");
figure; imshowpair(J1, J2, 'montage');title("矫正后");
% See additional examples of how to use the calibration data. At the prompt type:
% showdemo('StereoCalibrationAndSceneReconstructionExample')
% showdemo('DepthEstimationFromStereoVideoExample')
%%04写入参数
% file name
filename = 'matlab_calib_result';
% create document
docNode = com.mathworks.xml.XMLUtils.createDocument('matlab_calib_result');
% document element
docRootNode = docNode.getDocumentElement();
%
% %%图像大小
sizeNode = docNode.createElement('imageSize');
sizeNode.appendChild(docNode.createTextNode(sprintf('%f,',size(I1))));
docRootNode.appendChild(sizeNode);
%
% %%内参KK
KK_L = stereoParams.CameraParameters1.IntrinsicMatrix;
KK_R = stereoParams.CameraParameters2.IntrinsicMatrix;
kklNode = docNode.createElement('KK_L');
kklNode.appendChild(docNode.createTextNode(sprintf('%f,',KK_L)));
docRootNode.appendChild(kklNode);
kkrNode = docNode.createElement('KK_R');
kkrNode.appendChild(docNode.createTextNode(sprintf('%f,',KK_R)));
docRootNode.appendChild(kkrNode);
% %%畸变系数
% %%径向畸变 k1,k2,k3
RadialDistortion_L = stereoParams.CameraParameters1.RadialDistortion;
RadialDistortion_R = stereoParams.CameraParameters2.RadialDistortion;
RadialDistortion_LNode = docNode.createElement('RadialDistortion_L');
RadialDistortion_LNode.appendChild(docNode.createTextNode(sprintf('%f,',RadialDistortion_L)));
docRootNode.appendChild(RadialDistortion_LNode);
RadialDistortion_RNode = docNode.createElement('RadialDistortion_R');
RadialDistortion_RNode.appendChild(docNode.createTextNode(sprintf('%f,',RadialDistortion_R)));
docRootNode.appendChild(RadialDistortion_RNode);
% % 切向失真 p1, p2
TangentialDistortion_L = stereoParams.CameraParameters1.TangentialDistortion;
TangentialDistortion_R = stereoParams.CameraParameters2.TangentialDistortion;
TangentialDistortion_LNode = docNode.createElement('TangentialDistortion_L');
TangentialDistortion_LNode.appendChild(docNode.createTextNode(sprintf('%f,',TangentialDistortion_L)));
docRootNode.appendChild(TangentialDistortion_LNode);
TangentialDistortion_RNode = docNode.createElement('TangentialDistortion_R');
TangentialDistortion_RNode.appendChild(docNode.createTextNode(sprintf('%f,',TangentialDistortion_R)));
docRootNode.appendChild(TangentialDistortion_RNode);
% % 右相机->左相机
% % 旋转矩阵
R = stereoParams.RotationOfCamera2;
RNode = docNode.createElement('R');
RNode.appendChild(docNode.createTextNode(sprintf('%f,',R)));
docRootNode.appendChild(RNode);
% % 平移矩阵
T = stereoParams.TranslationOfCamera2;
TNode = docNode.createElement('T');
TNode.appendChild(docNode.createTextNode(sprintf('%f,',T)));
docRootNode.appendChild(TNode);
%
% % 本质矩阵
E = stereoParams.EssentialMatrix;
ENode = docNode.createElement('E');
ENode.appendChild(docNode.createTextNode(sprintf('%f,',E)));
docRootNode.appendChild(ENode);
%
% % 基础矩阵
F = stereoParams.FundamentalMatrix;
FNode = docNode.createElement('F');
FNode.appendChild(docNode.createTextNode(sprintf('%f,',F)));
docRootNode.appendChild(FNode);
%
% % 重投影误差
error = stereoParams.MeanReprojectionError;
errorNode = docNode.createElement('error');
errorNode.appendChild(docNode.createTextNode(sprintf('%f,',error)));
docRootNode.appendChild(errorNode);
%
%
% % xmlwrite
xmlFileName = [filename,'.xml'];
xmlwrite(xmlFileName,docNode);
type(xmlFileName)
二、保存成xml格式效果
三、QT C++读取xml文件
导入这俩个库:
#include <QXmlStreamReader>
#include <QFile>
//打开或创建文件
QFile file; //需要打开的文件
QString nodename; //节点的名字
QString OutPut; //最终输出的内容
QStringList list; //输出内容
double size_1,size_2;//图像尺寸
double KK_L1,KK_L2,KK_L3,KK_L4,KK_L5,KK_L6,KK_L7,KK_L8,KK_L9;//左相机内参
double KK_R1,KK_R2,KK_R3,KK_R4,KK_R5,KK_R6,KK_R7,KK_R8,KK_R9;//右相机内参
double RadialDistortion_L1,RadialDistortion_L2,RadialDistortion_L3;//左相机畸变
double TangentialDistortion_L1,TangentialDistortion_L2;
double RadialDistortion_R1,RadialDistortion_R2,RadialDistortion_R3;//右相机畸变
double TangentialDistortion_R1,TangentialDistortion_R2;
double R1,R2,R3,R4,R5,R6,R7,R8,R9;//相机旋转矩阵
double T1,T2,T3;//相机平移矩阵
file.setFileName("C:\\Users\\kurn\\Desktop\\Cam_calibrate\\matlab_calib\\matlab_calib_result.xml"); //查找xml文件的路径
if (!file.exists())
{
qDebug() << "testconfig.xml文件不存在";
}
else
{
qDebug() << "testconfig.xml文件存在";
}
if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) //打开文件
{
qDebug()<<"打开文件失败!";
}
else
{
QXmlStreamReader xmlreader(&file); //读取xml文件的迭代器
qDebug() << "testconfig.xml文件存在,且打开文件成功!";
while(!xmlreader.atEnd() || !xmlreader.hasError()) //当文件没有结束且没有出错执行下面的代码
{
xmlreader.readNextStartElement(); //找到非根节点下的第一个子节点
nodename = xmlreader.name().toString(); //第一个子节点Data
if(nodename == "matlab_calib_result" && xmlreader.isStartElement()) //如果是第一个子节点的开始执行下列代码
{
while(!(nodename == "matlab_calib_result" && xmlreader.isEndElement())) //如果子节点中的内容没有结束
{
xmlreader.readNextStartElement();
nodename = xmlreader.name().toString();
if(nodename == "imageSize" && xmlreader.isStartElement())
{
while(!(nodename == "imageSize" && xmlreader.isEndElement()))
{
OutPut.append(QString("%1").arg(xmlreader.readElementText()));
list = OutPut.split(",");
list.removeLast();
size_1 = list[0].toDouble();
size_2 = list[1].toDouble();
}
list.clear();
OutPut.clear();
}
else if(nodename == "KK_L" && xmlreader.isStartElement())
{
while(!(nodename == "KK_L" && xmlreader.isEndElement()))
{
OutPut.append(QString("%1").arg(xmlreader.readElementText()));
list = OutPut.split(",");
list.removeLast();
KK_L1 = list[0].toDouble();
KK_L2 = list[1].toDouble();
KK_L3 = list[2].toDouble();
KK_L4 = list[3].toDouble();
KK_L5 = list[4].toDouble();
KK_L6 = list[5].toDouble();
KK_L7 = list[6].toDouble();
KK_L8 = list[7].toDouble();
KK_L9 = list[8].toDouble();
}
list.clear();
OutPut.clear();
}
else if(nodename == "KK_R" && xmlreader.isStartElement())
{
while(!(nodename == "KK_R" && xmlreader.isEndElement()))
{
OutPut.append(QString("%1").arg(xmlreader.readElementText()));
list = OutPut.split(",");
list.removeLast();
KK_R1 = list[0].toDouble();
KK_R2 = list[1].toDouble();
KK_R3 = list[2].toDouble();
KK_R4 = list[3].toDouble();
KK_R5 = list[4].toDouble();
KK_R6 = list[5].toDouble();
KK_R7 = list[6].toDouble();
KK_R8 = list[7].toDouble();
KK_R9 = list[8].toDouble();
}
list.clear();
OutPut.clear();
Mat Matrixr = (Mat_<double>(3, 3) <<
KK_R1, KK_R2, KK_R3,
KK_R4, KK_R5, KK_R6,
KK_R7, KK_R8, KK_R9);
}
else if(nodename == "RadialDistortion_L" && xmlreader.isStartElement())
{
while(!(nodename == "RadialDistortion_L" && xmlreader.isEndElement()))
{
OutPut.append(QString("%1").arg(xmlreader.readElementText()));
list = OutPut.split(",");
list.removeLast();
RadialDistortion_L1 = list[0].toDouble();
RadialDistortion_L2 = list[1].toDouble();
RadialDistortion_L3 = list[2].toDouble();
}
list.clear();
OutPut.clear();
}
else if(nodename == "RadialDistortion_R" && xmlreader.isStartElement())
{
while(!(nodename == "RadialDistortion_R" && xmlreader.isEndElement()))
{
OutPut.append(QString("%1").arg(xmlreader.readElementText()));
list = OutPut.split(",");
list.removeLast();
RadialDistortion_R1 = list[0].toDouble();
RadialDistortion_R2 = list[1].toDouble();
RadialDistortion_R3 = list[2].toDouble();
}
list.clear();
OutPut.clear();
}
else if(nodename == "TangentialDistortion_L" && xmlreader.isStartElement())
{
while(!(nodename == "TangentialDistortion_L" && xmlreader.isEndElement()))
{
OutPut.append(QString("%1").arg(xmlreader.readElementText()));
list = OutPut.split(",");
list.removeLast();
TangentialDistortion_L1 = list[0].toDouble();
TangentialDistortion_L2 = list[1].toDouble();
}
list.clear();
OutPut.clear();
}
else if(nodename == "TangentialDistortion_R" && xmlreader.isStartElement())
{
while(!(nodename == "TangentialDistortion_R" && xmlreader.isEndElement()))
{
OutPut.append(QString("%1").arg(xmlreader.readElementText()));
list = OutPut.split(",");
list.removeLast();
TangentialDistortion_R1 = list[0].toDouble();
TangentialDistortion_R2 = list[1].toDouble();
}
list.clear();
OutPut.clear();
}
else if(nodename == "R" && xmlreader.isStartElement())
{
while(!(nodename == "R" && xmlreader.isEndElement()))
{
OutPut.append(QString("%1").arg(xmlreader.readElementText()));
list = OutPut.split(",");
list.removeLast();
R1 = list[0].toDouble();
R2 = list[1].toDouble();
R3 = list[2].toDouble();
R4 = list[3].toDouble();
R5 = list[4].toDouble();
R6 = list[5].toDouble();
R7 = list[6].toDouble();
R8 = list[7].toDouble();
R9 = list[8].toDouble();
}
list.clear();
OutPut.clear();
}
else if(nodename == "T" && xmlreader.isStartElement())
{
while(!(nodename == "T" && xmlreader.isEndElement()))
{
OutPut.append(QString("%1").arg(xmlreader.readElementText()));
list = OutPut.split(",");
list.removeLast();
T1 = list[0].toDouble();
T2 = list[1].toDouble();
T3 = list[2].toDouble();
}
list.clear();
OutPut.clear();
}
else if(nodename == "E" && xmlreader.isStartElement())
{
while(!(nodename == "E" && xmlreader.isEndElement()))
{
OutPut.append(QString("%1").arg(xmlreader.readElementText()));
list = OutPut.split(",");
list.removeLast();
double E1 = list[0].toDouble();
double E2 = list[1].toDouble();
double E3 = list[2].toDouble();
double E4 = list[3].toDouble();
double E5 = list[4].toDouble();
double E6 = list[5].toDouble();
double E7 = list[6].toDouble();
double E8 = list[7].toDouble();
double E9 = list[8].toDouble();
}
list.clear();
OutPut.clear();
}
else if(nodename == "F" && xmlreader.isStartElement())
{
while(!(nodename == "F" && xmlreader.isEndElement()))
{
OutPut.append(QString("%1").arg(xmlreader.readElementText()));
list = OutPut.split(",");
list.removeLast();
double F1 = list[0].toDouble();
double F2 = list[1].toDouble();
double F3 = list[2].toDouble();
double F4 = list[3].toDouble();
double F5 = list[4].toDouble();
double F6 = list[5].toDouble();
double F7 = list[6].toDouble();
double F8 = list[7].toDouble();
double F9 = list[8].toDouble();
}
list.clear();
OutPut.clear();
}
else if(nodename == "error" && xmlreader.isStartElement())
{
while(!(nodename == "error" && xmlreader.isEndElement()))
{
OutPut.append(QString("%1").arg(xmlreader.readElementText()));
list = OutPut.split(",");
list.removeLast();
double ERROR1 = list[0].toDouble();
}
list.clear();
OutPut.clear();
}
}
}
}
file.close();
qDebug()<<OutPut;
}
//图像分辨率
Size image_size = Size(size_1,size_2);
//左相机//
Mat Matrixl = (Mat_<double>(3, 3) <<
KK_L1, KK_L2, KK_L3,
KK_L4, KK_L5, KK_L6,
KK_L7, KK_L8, KK_L9);
//右相机//
Mat Matrixr = (Mat_<double>(3, 3) <<
R1, R2, R3,
R4, R5, R6,
R7, R8, R9);
//左相机畸变
Mat distl = (Mat_<double>(5, 1) <<
RadialDistortion_L1,RadialDistortion_L2,TangentialDistortion_L1,TangentialDistortion_L2,RadialDistortion_L3);
//右相机畸变
Mat distr = (Mat_<double>(5, 1) <<
RadialDistortion_R1,RadialDistortion_R2,TangentialDistortion_R1,TangentialDistortion_R2,RadialDistortion_R3);
Mat R=(Mat_<double>(3,3)<<
R1, R2, R3,
R4, R5, R6,
R7, R8, R9);
Mat T = (Mat_<double>(3, 1) <<
T1, T2, T3);