使用 Matlab 生成双目视差及点云图像

目录

  • 使用 Matlab 生成双目视差及点云图像(TODO)
    • 准备工作
    • 采集棋盘格图像
    • 使用 Matlab *Stereo Camera Calibrator* 进行双目相机标定
    • 编写 matlab 脚本,生成视差图,点云图
      • matlab 脚本
      • 运行结果
      • 说明
    • 参考

使用 Matlab 生成双目视差及点云图像(TODO)

最近需要验证一下双相机的成像效果,一开始使用了opencv + python/cpp 代码采集、标定并生成视差图,效果不是很理想,所以决定先用 matlab 标定相机,生成图像点云,查看效果,如果不错的话,以此为基准优化 opencv 代码。

准备工作

首先需要下载 Matlab(废话,哈哈哈),请支持正版,还需要在其中安装名为 Stereo Camera Calibrator 的立体相机标定程序包。图标是这个样子的(截图好麻烦,算了)。当然,对于 Matlab 菜鸟来说,资料手册什么的必不可少(摸着书本过河比无脑乱撞的要好)。所以下面几个资料还是推荐一下了(官网英文板的):

  1. Computer Vision ToolBox 官方网页,跟着教程说明走,不懂就 csdn + StackOverflow,对了,如果可以的话,最好是在这个页面下载 Computer Vision ToolBox 的 PDF 文档(包含 Computer Vision Toolbox Getting Started Guide,Computer Vision Toolbox User’s Guide(以后简称手册) 以及另外两个我认为不重要的),不过需要在 Matlab 注册邮箱
  2. 同上()

好了,开始搞事!下面简单记录下实现步骤,免得以后忘了。

采集棋盘格图像

很无聊的一项工作,但是还是有些要注意的地方。在 Computer Vision ToolBox User’s Guide 中对单目以及双目相机的标定图案、步骤有很详细很规范的说明,以前看 OpenCV 文档的时候的一些模棱两可的操作在这里面都表达的很清楚。
使用 Matlab 生成双目视差及点云图像_第1张图片
具体的操作步骤参考手册把,列出几个以前犯错误的地方,以示提醒。

  1. 标定板一边的棋盘格数与另一边的必须奇偶互斥,如果是 12x9 的棋盘格,那么此棋盘格的角点数为 11x888 个(每条边角点数=此边棋盘格数-1)。
  2. 相机在采集图像前需要使用分辨率板进行对焦校准。分辨率板如图。
    使用 Matlab 生成双目视差及点云图像_第2张图片
  3. 不要使用自动对焦功能。
  4. 每改变一次焦距,就要重新标定相机。
  5. 用于标定图像数目在10-20张之间,所以尽可能地多采集一些图像(对于普通的非工业相机来说),因为很多情况下超过50%的图像最后是要被筛选掉的。
  6. 图像最好保存为无损格式.png.bmp
  7. 标定板的位置尽量放置在双目相机测量物体的距离之间。比如想在1.5米处测量物体,就在大约1.5米处放置标定板。
  8. 采集标定板图像时,可以将标定板多放置几个旋转角度(我没怎么旋转标定板),但是,标定板与相机光轴的倾角不要大于45度。
    使用 Matlab 生成双目视差及点云图像_第3张图片
  9. 标定板尽量要大一些,这样可以使它在标定时占据图像大部分区域;也就是说,如果需要在很近的距离标定相机(近距离成像),就选相对较小的标定板,反正大的标定板。
  10. 标定板在一对双目图像中必须各个棋盘格可见。

采集的标定图像示例(标定板有些小,只显示了左相机图像)
注意,需要将左右图集分别放在同级的两个不同的目录下,比如

*
|-left
    |-left_*.png
|-right
    |-right_*.png

使用 Matlab 生成双目视差及点云图像_第4张图片

使用 Matlab Stereo Camera Calibrator 进行双目相机标定

接下来就是操作matlab的标定包了。

  1. 首先打开matlab,在 App 中选择 Stereo Camera Calibrator
    使用 Matlab 生成双目视差及点云图像_第5张图片
  2. 打开后选择 Add Image(1号),在弹出的对话框中分别给定左右图像集的搜索路径,然后指定棋盘格的大小(单位:mm)
    使用 Matlab 生成双目视差及点云图像_第6张图片
  3. 可以选择 3 Coefficient(2号)(出处:手册page204,如下图) 使标定更准确。
    在这里插入图片描述
  4. 点击 Calibrate(3号)对双目图像进行标定,标定后可以计算出 reprojection error (再次投影误差) 并以条形图显示,可以通过上下拖拽红色区域批量删除误差值过高的图像对,也可以通过 ctrl+鼠标左键多选要删除的不符合要求的图像,被选择的图像在左侧显示栏中以蓝色背景显示,可以直接右键其中的任何一组图像对进行批量删除。我的删图标准,如下;通常情况下,Overall Mean Error(平均误差达)0.06 左右就可以了。
    1. 图像对中任何一个或一对图像误差值过大的
    2. 接着是图像对中左右图误差值只差过大的
    3. reprojection error (再次投影误差) 如图(放大处理),还没有查是如何计算出来的以及代表着什么(TODO
      使用 Matlab 生成双目视差及点云图像_第7张图片
  5. 点击 Show Rectified,对图像对进行y轴(水平对齐),输出图如下
    使用 Matlab 生成双目视差及点云图像_第8张图片
  6. 接着点击 Export Camera Parameters(5号),会出现两个选项的下拉列表,Export Parameters to workspace 将标定的内外参数矩阵,投影误差等导出到 Matlab 主程序界面的工作区,Generate Matlab script 生成标定运算的脚本。
  7. 最后记得保存这次的 session 标定会话,也可以创建或导出保存的会话(6,7号)

编写 matlab 脚本,生成视差图,点云图

matlab 脚本

run("D:\M_matLab2020a\workSpace\522d_0605\run_522d_0605.m");

% 读取左右彩色图像
I1_C3 = imread("D:\M_matLab2020a\workSpace\522d_0605\object_left\left_0.png");
I2_C3 = imread("D:\M_matLab2020a\workSpace\522d_0605\object_right\right_0.png");

% 矫正左右彩色图像,利用导入的立体相机参数
[J1_C3, J2_C3] = rectifyStereoImages(I1_C3, I2_C3, stereoParams);

% 利用矫正后的左右图生成立体图像
Anaglyph = stereoAnaglyph(J1_C3, J2_C3);
figure; imshow(Anaglyph);

% 使用 imtool 确定视差范围值(max=93.5),这里取 128,(具体操作见说明)
figure; imtool(Anaglyph);
disparityRange = [0, 128];

% 利用矫正后的灰度图生成视差图
J1_C1 = rgb2gray(J1_C3);
J2_C1 = rgb2gray(J2_C3);

% Minimum value of uniqueness = 20
disparityMap_t20 = disparitySGM(J1_C1, J2_C1, 'DisparityRange', disparityRange, 'UniquenessThreshold', 20);
figure; imshow(disparityMap_t20, disparityRange); title('disp t20'); colormap jet; colorbar;

% Minimum value of uniqueness = 15
disparityMap_t15 = disparitySGM(J1_C1, J2_C1, 'DisparityRange', disparityRange, 'UniquenessThreshold', 15);
figure; imshow(disparityMap_t15, disparityRange); title('disp t15'); colormap jet; colorbar;

% Minimum value of uniqueness = 10
disparityMap_t10 = disparitySGM(J1_C1, J2_C1, 'DisparityRange', disparityRange, 'UniquenessThreshold', 10);
figure; imshow(disparityMap_t10, disparityRange); title('disp t10'); colormap jet; colorbar;

% Minimum value of uniqueness = 5
disparityMap_t5 = disparitySGM(J1_C1, J2_C1, 'DisparityRange', disparityRange, 'UniquenessThreshold', 5);
figure; imshow(disparityMap_t5, disparityRange); title('disp t5'); colormap jet; colorbar;

% Minimum value of uniqueness = 0
disparityMap_t0 = disparitySGM(J1_C1, J2_C1, 'DisparityRange', disparityRange, 'UniquenessThreshold', 0);
figure; imshow(disparityMap_t0, disparityRange); title('disp t0'); colormap jet; colorbar;

% 利用视差图重建 3D 图
points3D = reconstructScene(disparityMap_t10, stereoParams);

% 将距离单位由 mm -> m
points3D = points3D ./ 1000;

% 存储 3D 图的点云数据
ptCloud = pointCloud(points3D, 'Color', J1_C3);

% 使用 pcplayer 观察点云图
player3D = pcplayer([-1, 1], [-1, 1], [0, 2], 'VerticalAxis', 'Y', 'VerticalAxisDir', 'Up');
view(player3D, ptCloud);

运行结果

原始图(投影了散斑激光)
使用 Matlab 生成双目视差及点云图像_第9张图片
视差图
使用 Matlab 生成双目视差及点云图像_第10张图片
点云图
使用 Matlab 生成双目视差及点云图像_第11张图片
使用 Matlab 生成双目视差及点云图像_第12张图片

说明

确定视差范围
使用 imtool 工具测量近中远三个物体的视差距离如图
使用 Matlab 生成双目视差及点云图像_第13张图片
最大视差为 106,则视差范围设为 [0, 128]

参考

  1. matlab 教程
  2. Reconstruct 3-D scene from disparity map
  3. Compute disparity map through semi-global matchin
  4. Depth Estimation From Stereo Video
  5. stereoParameters

你可能感兴趣的:(双目相机,matlab)