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讀取。