Bootstrap

Matlab双目相机棋盘格标定法操作流程

双目相机棋盘格标定法操作流程

1.准备棋盘格

棋盘格应选择长方形的板子,每个格子为正方形,所有的格子必须同样大小,且黑白相间分布。
板子的形式有多种,但是上面那句话是原则,可以用下面这幅图直接打印,也可以根据自己实际情况进行行列数量调整,但建议最好保持行列的黑色格子都为奇数,并且整个棋盘格是左右对称、上下对称的,因为这样做标定效果给更佳,我标定过近百次,这都是一点一点摸索出来的。
棋盘格
上面的这张图片原文件的链接:
链接:https://pan.baidu.com/s/1lWCLELpKLfieq5M-xtbJ0w?pwd=2y9f
提取码:2y9f

2.拍摄标定图片

安装好相机,将标定板放置在合适的距离处,在拍摄前手动调节相机对焦,使标定板在相机视野中达到最清晰的效果,随后每拍摄一张图片移动一次标定板,必须保持整个棋盘格出现在两个相机视野中,也不可有遮挡,尽量让标定板不要太歪,尽量让标定板每次出现在视野中的不同位置。
合适的距离: 与你的目标检测距离、镜头景深、标定板大小有关,我的检测目标是30米内、镜头景深在10-20米左右、标定板单个格子266毫米,我的标定距离大约保持在14-16米之间。距离越远就需要尺寸越大的标定板!
大概拍摄30组左右照片就可以了。
在这里插入图片描述

3.使用Matlab进行标定

(1)打开“Stereo Camera Calibrator”工具

打开Matlab,点击点击顶部的“APP”,在“图像处理和计算机视觉”中选择“Stereo Camera Calibrator”工具。
stereo camera calibrator

(2)选择标定图片文件路径
打开工具后,点击“Add Images”,在弹出的对话框中,点击两个“Browse”分别加载左右相机的图片,“camera 1”为左相机,“camera 2”为右相机。“Pattern Selection”选择“Checkerboard”,在下方输入棋盘格上一个格子的边长,单位默认为毫米。
在这里插入图片描述
点击确定,开始加载图片。
加载标定图片

(3)检查图片
加载完成后,浏览每组图片,检查标定板上的坐标轴朝向是否一致,通常情况下没有错误,但偶尔会有!若有,则删除对应的该组图片。
在这里插入图片描述

(4)进行标定
左侧一列是图片的缩略图,有时候显示不出来,这是我电脑的问题,不影响标定结果,可以不用管。
检查图片上的坐标轴没有问题后,选择顶部“Radial Distortion:Compute:”中的参数,然后点击“Calibrate”进行标定。
在这里插入图片描述
标定中
在这里插入图片描述

(5)查看误差
标定后,在“Reprojection Errors”中查看误差大小,虚线为平均误差,若存在误差很大的图片,则在左侧缩略图中右键单击,去掉该组(可能不止一组)照片,然后点击“Calibrate”重新标定;可以在“Camera-centric”中是来查看相机与图片的空间位置是否与你实际拍摄时候的位置差不多,因为当误差太大的时候,这里的左相机、右相机、图片三者之间的位置关系真的很离谱!
在这里插入图片描述

(6)提取参数
当没有问题时候点击页面上方的“Export Camera Parameters”提取相机参数,在弹出的对话框中可修改参数文件的名字。点击确定,就可以生成参数文件了。
在这里插入图片描述

在主页面(就是你启动Matlab的第一个页面)右侧的工作区可以看到刚才在生成的参数文件。
在这里插入图片描述

(7)查看参数
双击此文件,在页面中间会显示各个参数组:
Camera Parameters1”为左相机参数组
Camera Parameters2”为右相机参数组
RotationOfCamera2”为左右相机间的旋转矩阵
TranslationOfCamera2”为左右相机间的平移矩阵
在这里插入图片描述
双击“Camera Parameters1”查看左相机参数:
RadialDistortion” 为 切向畸变参数
TangentialDistortion” 为 径向畸变参数
IntrinsicMatrix” 为 内参矩阵
在这里插入图片描述
双击“IntrinsicMatrix” 查看内参矩阵,注意参数文件中的所有矩阵都是转置后的矩阵,在使用的时候要转置过来!!!
在这里插入图片描述

(8)保存参数
右键单击主页面中右侧的工作区中的参数文件,选择“另存为”:
在这里插入图片描述

在弹出的对话框中选择文件存储位置,并命名文件,保存参数文件,后期查看参数可直接打开该文件,无需再次标定!
在这里插入图片描述
标定到这里就结束了,下面是个人对参数使用的方法,完全可以不看。

利用.yml文件使得三维还原代码更整洁

通常我们都是将参数一个个直接写在双目相机计算深度的代码中,这样做一方面让代码里显得比较乱,更重要的:当你下次标定后使用新的参数时候就需要修改掉这次的参数,但是如果后期需要再次使用这次的参数你就得再次把参数修改回来,这么多参数实在是太麻烦了。如果使用.yml文件把每次标定的参数存储起来,使用的时候从相应的.yml文件读取参数就会很方便。

1.创建.yml文件

在下面的代码中按照参数名输入刚才标定得到的相应的参数,切记:Matlab里的看到参数矩阵与这里的矩阵是转置关系!转置!转置!转置!(也就是Matlab里的矩阵的行对应的这里矩阵的列
注意:此文件需要在OpenCV环境下运行,因为调用了OpenCV头文件!

#pragma warning(disable : 4996)
#include <opencv2/opencv.hpp>
#include <time.h>

using namespace cv;

int main(int, char** argv)
{
    cv::FileStorage fsout("params_xxx.yml", cv::FileStorage::WRITE);//设置.yml文件名
	time_t rawtime;
	time(&rawtime);
	fsout<<"Create Time"<<asctime(localtime(&rawtime));

    //LeftCamera: RadialDistortion:K1,K2, TangentialDistortion P1,P2,K3=0
    Mat distCoeffL = (Mat_<double>(5, 1) << -0.0965143163438232, 0.528857463222299, 0.00400201778517539, 0.000769418618327448, 0);

    //LeftCamera:
    Mat cameraMatrixL = (Mat_<double>(3, 3) << 2414.74726172403, -1.81676763117102, 746.034283238341,
                                                0, 2416.93643407851, 601.393646216103,
                                                0,        0,            1);

    //RightCamera:K1,K2,P1,P2,K3=0
    Mat distCoeffR = (Mat_<double>(5, 1) << -0.104134549797886, 0.660535154992057, 0.00335642390820930, 0.00130477683496583, 0);

    //rightCamera:
    Mat cameraMatrixR = (Mat_<double>(3, 3) << 2419.29214682585, -1.90019288011447, 756.039807112457,
                                                0, 2421.64766201800, 600.742056297907,
                                                0, 0,      1);

    //TranslationOfCamera2
    Mat T = (Mat_<double>(3, 1) << -108.775406733637, -1.39294062589888, 12.7940208531868);

    //RotationOfCamera2,
    Mat rec = (Mat_<double>(3, 3) << 0.999607134219369, 0.0280182799413774, -0.000743778776209935,
        							-0.0280273645396337, 0.999425813526378, -0.0190396978468605,
        							0.000209892124224654, 0.0190530639600006, 0.999818451869654);

    fsout<<"cameraMatrixL"<<cameraMatrixL<<"distCoeffL"<<distCoeffL
    <<"cameraMatrixR"<<cameraMatrixR<<"distCoeffR"<<distCoeffR<<"T"<<T<<"rec"<<rec;
}

2.读取.yml文件

在你的深度计算代码中创建好相应的参数变量,使用以下函数读取前面创建的.yml文件。str为.yml文件的路径!

bool readparams(string str)
{
	//str = "ParametersFile Path/ParametersFile Name.yml";
    cv::FileStorage fsin(str, cv::FileStorage::READ);
    if(fsin.isOpened())
    {
		fsin["cameraMatrixL"] >> cameraMatrixL;
		fsin["distCoeffL"] >> distCoeffL;
		fsin["cameraMatrixR"] >> cameraMatrixR;
		fsin["distCoeffR"] >> distCoeffR;
		fsin["T"] >> T;
		fsin["rec"] >> rec;
    }
    else
    {
		cout<<"Read YAML file filed!"<<endl;
		return false; 
    }
    return true;
}

如果对您有帮助,别忘了一键三连呀!

;