### 双目视觉稠密三维重建在 MATLAB 中的实现
双目视觉是一种通过模拟人类双眼观察世界的方式来进行三维重建的技术。为了完成双目的稠密三维重建,通常需要经过以下几个阶段:相机标定、特征匹配、视差计算以及最终的三维点云生成。
#### 1. 相机标定
相机标定是双目视觉的基础工作之一,它涉及获取相机内部参数(焦距、主点位置等)和外部参数(旋转矩阵和平移向量)。MATLAB 提供了一个强大的工具箱——Camera Calibration Toolbox,可以用来完成这一任务[^3]。
```matlab
% 加载标定数据
load('stereoParams.mat');
% 显示标定结果
showExtrinsics(stereoParams);
```
上述代码展示了如何加载已经保存好的立体相机参数并显示其外参信息。如果尚未进行标定,则可以通过拍摄棋盘格图案来完成标定过程。
#### 2. 特征提取与匹配
一旦完成了相机标定,下一步就是从两幅图像中找到对应的特征点。常用的方法包括 SIFT 或 SURF 等局部描述符技术,但在 MATLAB 中可以直接调用内置函数 `estimateGeometricTransform` 来简化此操作。
```matlab
% 使用SURF检测器查找关键点
points1 = detectSURFFeatures(I1);
points2 = detectSURFFeatures(I2);
% 提取特征描述子
[features1, valid_points1] = extractFeatures(I1, points1);
[features2, valid_points2] = extractFeatures(I2, points2);
% 进行特征匹配
indexPairs = matchFeatures(features1, features2);
matchedPoints1 = valid_points1(indexPairs(:,1));
matchedPoints2 = valid_points2(indexPairs(:,2));
% 绘制匹配结果
figure;
showMatchedFeatures(I1, I2, matchedPoints1, matchedPoints2);
```
这段脚本实现了基于 SURF 的特征点检测、描述子提取及初步匹配,并将匹配结果显示出来。
#### 3. 计算视差图
有了对应关系后就可以进入核心部分—计算视差图了。视差反映了同一物体在左右两张图片上的水平偏移距离,它是恢复深度的重要依据。
```matlab
% 创建立体块对象
blockSize = 7; % 设置窗口大小
disparityRange = [-60 60]; % 定义搜索范围
sgbm = disparitySGM(disparityRange,'BlockSize', blockSize,...
'UniquenessMargin', 10,...
'P1', 8*3*blockSize^2,...
'P2', 32*3*blockSize^2);
% 获取视差地图
dispMap = estimateDisparity(sgbm,I1Gray,I2Gray);
% 展示视差效果
imshow(dispMap,[],'InitialMagnification','fit');
title('Disparity Map');
colormap jet;
colorbar;
```
这里采用了半全局匹配 (Semi-Global Matching, SGM) 方法生成高质量的视差图[^1]。
#### 4. 构建三维模型
最后一步是从视差图转换成实际的空间坐标系下的三维点集。这需要用到之前得到的相机内外参数。
```matlab
% 将像素坐标转至归一化平面
[x,y]=meshgrid(1:size(I1,2),1:size(I1,1));
xyzPts=undistortImage([x(:)-camIntrinsics.PrincipalPoint(1),...
y(:)-camIntrinsics.PrincipalPoint(2)], camIntrinsics);
% 应用三角测量原理获得真实世界坐标
Z=(baseline.*focalLength)./double(dispMap(:)+eps);
X=Z.*(xyzPts(:,1)/focalLength);
Y=Z.*(xyzPts(:,2)/focalLength);
% 合并XYZ分量形成完整的点阵列
pointCloud=[reshape(X,size(x)), reshape(Y,size(y)), ...
reshape(Z,size(x))];
pcshow(pointCloud(:,:,1:3),'VerticalAxis','y',...
'VerticalAxisDir','down','MarkerSize',30);
xlabel('X'); ylabel('Y'); zlabel('Z');
title('Reconstructed Point Cloud');
```
以上程序片段解释了怎样把二维平面上测得的数据映射到真实的三维空间里去。
---