最近需要验证一下双相机的成像效果,一开始使用了opencv + python/cpp 代码采集、标定并生成视差图,效果不是很理想,所以决定先用 matlab 标定相机,生成图像点云,查看效果,如果不错的话,以此为基准优化 opencv 代码。
首先需要下载 Matlab(废话,哈哈哈),请支持正版,还需要在其中安装名为 Stereo Camera Calibrator 的立体相机标定程序包。图标是这个样子的(截图好麻烦,算了)。当然,对于 Matlab 菜鸟来说,资料手册什么的必不可少(摸着书本过河比无脑乱撞的要好)。所以下面几个资料还是推荐一下了(官网英文板的):
好了,开始搞事!下面简单记录下实现步骤,免得以后忘了。
很无聊的一项工作,但是还是有些要注意的地方。在 Computer Vision ToolBox User’s Guide 中对单目以及双目相机的标定图案、步骤有很详细很规范的说明,以前看 OpenCV 文档的时候的一些模棱两可的操作在这里面都表达的很清楚。
具体的操作步骤参考手册把,列出几个以前犯错误的地方,以示提醒。
.png
,.bmp
。采集的标定图像示例(标定板有些小,只显示了左相机图像)
注意,需要将左右图集分别放在同级的两个不同的目录下,比如
*
|-left
|-left_*.png
|-right
|-right_*.png
接下来就是操作matlab的标定包了。
y轴
(水平对齐),输出图如下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);
确定视差范围
使用 imtool 工具测量近中远三个物体的视差距离如图
最大视差为 106,则视差范围设为 [0, 128]