文章目录
- 1. 引言
- 2. 从视差到深度
- 3. 从深度到三维点云
- 4. 点云存储与可视化
- 5. 点云后处理
- 6. 深度精度分析
- 7. 多视角配准概述
- 8. 总结
1. 引言
经过标定、校正、匹配、后处理,我们终于得到了一张高质量的视差图。这是双目视觉的"成品数据",但要真正还原三维世界,还需最后一步——把二维视差转换为三维坐标,生成三维点云(3D Point Cloud)。这一步是"从图像到三维"的最后一跃,完成它,整个双目流水线才算闭环。
本篇介绍视差到深度的转换、深度到点云的投影、点云的存储与可视化、后处理,以及深度精度分析。
2. 从视差到深度
三角测量的一般原理:空间一点P PP在左右两幅图像中各有一个像点,从左、右相机光心分别向对应像点作投影射线,两条射线在空间中的交点即恢复出的三维点——这就是一般意义上的三角测量(Triangulation),对任意双相机构型都成立。本篇处理的校正后平行光轴双目是它的特例:两条射线共面且水平对齐,交点的求解退化为一个简洁的公式Z = f B / d Z = fB/dZ=fB/d。下面从视差出发推导它。
图 1:从视差图到三维点云的转换链。视差d dd经Z = f B / d Z=fB/dZ=fB/d转为深度,再经内参反投影为三维坐标,最后做点云后处理。
核心公式(第 1 篇已推导):
Z = f B d \boxed{Z = \frac{fB}{d}}Z=dfB
其中f ff为焦距(像素)、B BB为基线、d dd为视差。由Z = f B / d Z = fB/dZ=fB/d可见:
| 视差 d | 深度 Z | 含义 |
|---|---|---|
| 大 | 小 | 物体近 |
| 小 | 大 | 物体远 |
| 0 | ∞ | 无穷远(无有效深度) |
⚠️异常值处理:视差为 0 或负值无物理意义,需置为无效;过小视差对应极远距离,误差被放大,常设深度上界截断。
3. 从深度到三维点云
已知深度Z ZZ和像素坐标( u , v ) (u, v)(u,v),结合内参K KK反投影为相机坐标系下的三维点:
X = ( u − c x ) Z f x , Y = ( v − c y ) Z f y , Z = f B d X = \frac{(u - c_x)\,Z}{f_x}, \quad Y = \frac{(v - c_y)\,Z}{f_y}, \quad Z = \frac{f B}{d}X=fx(u−cx)Z,Y=fy(v−cy)Z,Z=dfB
其中( f x , f y , c x , c y ) (f_x, f_y, c_x, c_y)(fx,fy,cx,cy)为内参;立体校正后左右相机焦距一致且f x = f y = f f_x = f_y = ffx=fy=f,故深度公式统一记Z = f B / d Z = fB/dZ=fB/d。这组公式本质是针孔投影u = f x X / Z + c x u = f_x X/Z + c_xu=fxX/Z+cx的逆解。
OpenCV 提供重投影矩阵Q QQ(由stereoRectify输出)一步完成:
# 视差图 (float32) → 三维点云 (N×3)points=cv2.reprojectImageTo3D(disp,Q)# Q 是 stereoRectify 返回的 4×4 重投影矩阵Q QQ矩阵封装了f ff、c x c_xcx、c y c_ycy、T x T_xTx(基线)等参数,reprojectImageTo3D对每个像素应用:
[ X Y Z W ] = Q [ u v d 1 ] , ( X , Y , Z ) = ( X / W , Y / W , Z / W ) \begin{bmatrix} X \\ Y \\ Z \\ W \end{bmatrix} = Q \begin{bmatrix} u \\ v \\ d \\ 1 \end{bmatrix}, \quad (X,Y,Z) = (X/W, Y/W, Z/W)XYZW=Quvd1,(X,Y,Z)=(X/W,Y/W,Z/W)
| 转换 | 公式 | 工具 |
|---|---|---|
| 视差→深度 | Z = f B / d Z = fB/dZ=fB/d | 手算,或Z = Q [ 2 ] [ 3 ] / ( Q [ 3 ] [ 2 ] d + Q [ 3 ] [ 3 ] ) Z=Q[2][3]/(Q[3][2]d+Q[3][3])Z=Q[2][3]/(Q[3][2]d+Q[3][3]) |
| 像素+深度→3D点 | X = ( u − c x ) Z / f x X=(u-c_x)Z/f_xX=(u−cx)Z/fx等 | reprojectImageTo3D |
4. 点云存储与可视化
图 2:常见点云存储格式对比与三维点云散点示意。PLY 最通用,Open3D/MeshLab/CloudCompare 均支持。
点云数据结构为N × 3 N \times 3N×3(或N × 6 N \times 6N×6含颜色)的浮点数组,存储格式多样:
| 格式 | 全称 | 存储 | 工具 | 备注 |
|---|---|---|---|---|
| PLY | Polygon File Format | ASCII/二进制 | Open3D/MeshLab | ★最常用 |
| PCD | Point Cloud Data | ASCII/二进制 | PCL 库 | PCL 生态 |
| XYZ | 纯坐标文本 | ASCII | 通用 | 简单 |
| LAS | ASPRS LAS(LASer 数据格式) | 二进制 | LAS 工具/LiDAR 处理软件 | 大地测量 |
可视化工具:Open3D(Python,交互式)、CloudCompare(GUI,专业)、MeshLab(网格+点云)。Open3D 示例:
importopen3daso3dimportnumpyasnp# 构造点云pcd=o3d.geometry.PointCloud()pcd.points=o3d.utility.Vector3dVector(points[:,:3])# N×3ifpoints.shape[1]==6:pcd.colors=o3d.utility.Vector3dVector(points[:,3:6]/255.0)o3d.io.write_point_cloud("output.ply",pcd)o3d.visualization.draw_geometries([pcd])# 交互式查看5. 点云后处理
图 3:点云后处理。原始点云含离群点(左);统计滤波剔除离群(中);体素下采样均匀化密度(右)。
原始点云仍有离群点和密度不均,需后处理:
| 步骤 | 方法 | 作用 | Open3D/OpenCV |
|---|---|---|---|
| 统计滤波 | 剔除邻域距离异常的点 | 去离群点 | remove_statistical_outlier |
| 半径滤波 | 剔除邻域点数过少的点 | 去孤立点 | remove_radius_outlier |
| 体素下采样 | 按体素栅格均匀采样 | 降密度、均匀化 | voxel_down_sample |
| 表面重建 | Poisson / Ball Pivoting | 点云→网格 | create_from_point_cloud_poisson |
# Open3D 后处理示例pcd,_=pcd.remove_statistical_outlier(nb_neighbors=20,std_ratio=2.0)pcd=pcd.voxel_down_sample(voxel_size=0.005)# 5mm 体素pcd.estimate_normals()# Poisson 重建前需先估计点云法线mesh,densities=o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(pcd,depth=9)实践要点:统计滤波参数(邻域数、标准差倍数)需根据点云密度调整;体素尺寸应略小于最小要保留的细节尺度。
6. 深度精度分析
图 4:深度精度分析。左:固定基线 6cm 下,深度分辨率随距离二次方增长;右:不同基线对比,基线越大远距离精度越高。(示意图,实际数值见下表。)
对Z = f B / d Z = fB/dZ=fB/d求导,深度分辨率(视差量化 1 像素带来的深度变化):
Δ Z = ∣ d Z d d ∣ Δ d = f B d 2 Δ d = Z 2 f B Δ d \Delta Z = \left|\frac{dZ}{dd}\right| \Delta d = \frac{fB}{d^2} \Delta d = \frac{Z^2}{fB} \Delta dΔZ=dddZΔd=d2fBΔd=fBZ2Δd
| 关键结论 | 含义 |
|---|---|
| 误差与Z 2 Z^2Z2成正比 | 距离越远,深度精度急剧下降 |
| 误差与f B fBfB成反比 | 焦距、基线越大,精度越高 |
| 亚像素Δ d < 1 \Delta d < 1Δd<1 | 亚像素精化可显著提升精度 |
以f = 800 f=800f=800px、B = 6 B=6B=6cm、Δ d = 0.25 \Delta d=0.25Δd=0.25px(亚像素)为例,Δ Z = Z 2 Δ d / ( f B ) = Z 2 / 192 \Delta Z = Z^2\Delta d/(fB) = Z^2/192ΔZ=Z2Δd/(fB)=Z2/192:
| 深度 Z | 深度分辨率 ΔZ | 评价 |
|---|---|---|
| 1 m | 约 5.2 mm | 高精度(毫米级) |
| 5 m | 约 130 mm | 厘米~分米级 |
| 10 m | 约 520 mm | 误差达分米量级 |
| 20 m | 约 2080 mm | 精度差(米级) |
工程启示:双目在近距离(几米内)精度可达毫米~厘米级,10m 处误差已达分米量级,远距离急剧恶化。这也是自动驾驶远距感知多配 LiDAR 的原因——双目在 50m 外精度通常不足。
7. 多视角配准概述
单对双目只能恢复一个视角的点云。要重建完整物体/场景,需从多个视角拍摄,经**配准(Registration)**拼接。核心算法是ICP(Iterative Closest Point):
- 在两片点云间找最近点对
- 计算最优旋转平移使点对距离最小
- 迭代直到收敛
Open3D:o3d.pipelines.registration.registration_icp。配准可结合特征描述子(FPFH)做全局粗配,再用 ICP 精配,最终融合为完整点云或表面网格。
8. 总结
本篇完成了从视差到三维的最后一跃:
- 视差→深度:Z = f B / d Z = fB/dZ=fB/d,深度与视差反比
- 深度→点云:X = ( u − c x ) Z / f x X=(u-c_x)Z/f_xX=(u−cx)Z/fx等,或
reprojectImageTo3D一键完成 - 点云存储:PLY 通用,PCD 服务 PCL,Open3D 读写
- 点云后处理:统计/半径滤波去离群,体素下采样均匀化,Poisson 重建网格
- 精度规律:Δ Z ∝ Z 2 / ( f B ) \Delta Z \propto Z^2/(fB)ΔZ∝Z2/(fB),远距离精度急剧下降
- 多视角:ICP 配准拼接多视角点云
至此,双目立体视觉的理论链路已全部走通:成像→标定→畸变→极线→校正→匹配→后处理→三维重建。在下一篇中,我们将用 OpenCV 把整条链路串成端到端可运行的完整工程,并讨论 SGBM 调参与实时优化。
💡思考题:深度分辨率Δ Z ∝ Z 2 \Delta Z \propto Z^2ΔZ∝Z2,意味着远距离精度极差。除了增大基线和焦距,还有什么方法能提升远距离精度?(提示:亚像素精化、多帧时序融合、或结合单目/先验深度。)