3D视觉基础:点云处理、深度估计、立体视觉详解

引言

3D视觉是计算机视觉的前沿分支,致力于从单/多张2D图像或激光/深度传感器数据中还原真实世界的三维几何、语义与空间关系——比如我们用iPhone LiDAR一键扫描家具、自动驾驶汽车的激光雷达实时定位行人、VR中的虚拟场景重建,都依赖这项技术。

📂 所属阶段:第二阶段 — 深度学习视觉基础(CNN 篇)
🔗 相关章节:Vision-Language 多模态 · 模型轻量化


1. 3D视觉基础概念

1.1 概述与核心问题

3D视觉的核心目标是重建可交互的3D世界模型,解决三大关键难题:

  • 如何从2D图像恢复深度信息?
  • 如何处理多视角的几何关联(对极约束、相机标定等)?
  • 如何用统一的框架表示、分析3D数据?

它已渗透到自动驾驶、工业检测、医疗影像等刚需领域,是AI落地的核心技术之一。

1.2 3D数据的5种主流表示

表示类型特点适用场景
点云 (Point Cloud)离散的(x,y,z)点集合,可带颜色、法向量、强度;无序、变长激光雷达数据、快速3D扫描
网格 (Mesh)顶点、边、面组成的显式几何结构;占用空间小、可渲染细节丰富游戏建模、工业CAD模型导出
体素 (Voxel)3D规则网格(类似“像素块”);结构固定但高分辨率下占用巨大医学CT/MRI重建、体素游戏
深度图 (Depth Map)与RGB图同尺寸的单通道图像,像素值对应深度;生成简单但仅含视角内信息深度相机数据、单/双目视觉
体积/隐式场连续的标量/向量函数(如NeRF);无需显式几何但推理成本高高保真新视角合成、复杂场景重建

2. 点云处理技术

2.1 点云基础与Open3D实践

点云是3D视觉中最常用的传感器原生数据,但原始点云通常存在噪声、离群点、密度不均的问题,需要先做预处理。

下面用Open3D和Numpy实现基础的点云处理流程:

import numpy as np
import open3d as o3d

class PointCloudProcessor:
    """简洁的Open3D点云处理器封装"""
    def create_from_numpy(self, points: np.ndarray) -> o3d.geometry.PointCloud:
        """从(N,3)的numpy数组创建点云"""
        pcd = o3d.geometry.PointCloud()
        pcd.points = o3d.utility.Vector3dVector(points)
        return pcd

    def preprocess(self, pcd: o3d.geometry.PointCloud, 
                   voxel_size=0.05, nb_neighbors=20, std_ratio=2.0) -> o3d.geometry.PointCloud:
        """
        一站式预处理:下采样 → 法向量估计 → 离群点去除
        """
        # 体素下采样(解决密度不均,保留几何特征)
        down_pcd = pcd.voxel_down_sample(voxel_size=voxel_size)
        # 法向量估计(为后续分割、重建做准备)
        down_pcd.estimate_normals()
        # 统计离群点去除(过滤激光雷达/扫描带来的噪点)
        filtered_pcd, _ = down_pcd.remove_statistical_outlier(
            nb_neighbors=nb_neighbors, std_ratio=std_ratio
        )
        return filtered_pcd

# 快速测试
if __name__ == "__main__":
    # 生成10000个高斯分布的随机点云
    noisy_points = np.random.randn(10000, 3) * 0.5
    pcd_raw = PointCloudProcessor().create_from_numpy(noisy_points)
    pcd_filtered = PointCloudProcessor().preprocess(pcd_raw)
    # 对比可视化(本地运行时打开draw_geometries)
    # o3d.visualization.draw_geometries([pcd_raw, pcd_filtered], window_name="Raw vs Filtered")
    print(f"原始点数: {len(pcd_raw.points)}, 预处理后点数: {len(pcd_filtered.points)}")

2.2 点云深度学习:简化版PointNet

点云的无序性和变长性让传统CNN无法直接使用,经典的PointNet通过「共享MLP + 对称最大池化」解决了这两个问题:

  • 共享MLP:对每个点独立提取局部特征,保证置换不变性(点的顺序不影响输出)
  • 对称最大池化:聚合所有点的局部特征,得到固定维度的全局特征

下面是PyTorch实现的简化版PointNet分类器:

import torch
import torch.nn as nn

class SimplePointNet(nn.Module):
    """简化版PointNet(不含T-net空间变换模块)"""
    def __init__(self, num_classes=10):
        super().__init__()
        # 共享MLP:逐点提取特征 (B,N,3) → (B,N,1024)
        self.point_mlp = nn.Sequential(
            nn.Conv1d(3, 64, kernel_size=1),
            nn.BatchNorm1d(64),
            nn.ReLU(),
            nn.Conv1d(64, 128, kernel_size=1),
            nn.BatchNorm1d(128),
            nn.ReLU(),
            nn.Conv1d(128, 1024, kernel_size=1),
            nn.BatchNorm1d(1024)
        )
        # 全局特征聚合
        self.global_pool = nn.MaxPool1d(kernel_size=1024)
        # 分类头
        self.classifier = nn.Sequential(
            nn.Linear(1024, 512),
            nn.BatchNorm1d(512),
            nn.ReLU(),
            nn.Dropout(0.3),
            nn.Linear(512, 256),
            nn.BatchNorm1d(256),
            nn.ReLU(),
            nn.Dropout(0.3),
            nn.Linear(256, num_classes)
        )

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        """
        Args:
            x: (batch_size, num_points, 3)
        Returns:
            logits: (batch_size, num_classes)
        """
        # 调整维度以适配Conv1d (B,N,3) → (B,3,N)
        x = x.transpose(2, 1)
        # 逐点特征提取
        x = self.point_mlp(x)
        # 全局特征聚合 (B,1024,N) → (B,1024,1) → (B,1024)
        x = self.global_pool(x).squeeze(-1)
        # 分类
        return self.classifier(x)

# 快速测试维度
if __name__ == "__main__":
    test_input = torch.randn(8, 1024, 3)  # batch=8, 点数=1024
    model = SimplePointNet(num_classes=40)  # ModelNet40数据集的40类
    output = model(test_input)
    print(f"输入维度: {test_input.shape}, 输出维度: {output.shape}")

3. 深度估计与立体视觉

3.1 核心技术分类

深度估计是从单/多模态数据中生成深度图的任务,分为以下主流方法:

方法类型输入原理成本精度
单目深度估计单张RGB图深度学习挖掘场景的深度先验(纹理梯度、物体大小、遮挡关系)
双目立体视觉两张RGB图利用对极几何计算左右图的视差(像素偏移),再转深度:深度 = 基线 × 焦距 / 视差中高
激光雷达/ToF相机传感器数据直接测量光的飞行时间或相位差

3.2 OpenCV实现双目立体匹配

我们用OpenCV的SGBM(半全局匹配)算法——它是传统方法中平衡精度和效率的最佳选择:

import cv2
import numpy as np
import matplotlib.pyplot as plt

def sgbm_stereo_depth(left_path: str, right_path: str, 
                       baseline=0.2, focal_length=720):
    """
    用SGBM计算双目图像的视差图和深度图
    Args:
        left_path/right_path: 左右图像路径
        baseline: 相机基线距离(米)
        focal_length: 相机焦距(像素)
    """
    # 1. 读取并预处理灰度图
    left = cv2.imread(left_path, cv2.IMREAD_GRAYSCALE)
    right = cv2.imread(right_path, cv2.IMREAD_GRAYSCALE)
    h, w = left.shape[:2]

    # 2. 创建SGBM匹配器
    stereo = cv2.StereoSGBM_create(
        minDisparity=0,          # 最小视差
        numDisparities=16*5,     # 视差范围(必须是16的倍数)
        blockSize=5,             # 匹配块大小(奇数)
        P1=8*3*5**2,             # 小视差变化的惩罚项
        P2=32*3*5**2,            # 大视差变化的惩罚项
        disp12MaxDiff=1,         # 左右一致性检查的最大差异
        uniquenessRatio=15,      # 唯一匹配的阈值
        preFilterCap=63          # 预处理的截断值
    )

    # 3. 计算视差图(归一化到[0,1])
    disparity = stereo.compute(left, right).astype(np.float32) / 16.0
    disparity_normalized = (disparity - disparity.min()) / (disparity.max() - disparity.min() + 1e-5)

    # 4. 视差转深度(避免除零)
    depth = (baseline * focal_length) / (disparity + 1e-5)
    depth_normalized = (depth - depth.min()) / (depth.max() - depth.min() + 1e-5)

    # 5. 可视化
    plt.figure(figsize=(15, 5))
    plt.subplot(131), plt.imshow(left, cmap='gray'), plt.title('Left Image')
    plt.subplot(132), plt.imshow(disparity_normalized, cmap='jet'), plt.title('Normalized Disparity')
    plt.subplot(133), plt.imshow(depth_normalized, cmap='jet'), plt.title('Normalized Depth')
    plt.tight_layout()
    plt.show()

    return disparity, depth

4. 神经辐射场(NeRF)快速入门

4.1 核心思想与突破

NeRF(Neural Radiance Fields)是2020年CVPR最佳论文,它将3D场景表示为连续的隐式神经网络函数

  • 输入:空间点坐标 (x,y,z) + 观测方向 (θ,φ)
  • 输出:该点的体密度 σ(不透明度) + 颜色 (r,g,b)

再配合体积渲染(沿相机光线积分颜色和密度),就能合成任意视角的高保真图像,是VR/AR内容创作的革命性技术。


相关教程

3D视觉是进阶方向,建议先掌握「**计算机视觉基础 + CNN + PyTorch**」,再从**Open3D点云预处理**和**OpenCV双目立体匹配**这些可落地的小项目入手,最后再接触NeRF这类前沿技术。

总结

3D视觉的三大核心技术栈已经清晰:

  1. 点云处理:Open3D预处理 + PointNet等深度学习模型
  2. 深度估计:单目深度学习(如MiDaS) + 双目SGBM
  3. 高保真重建:NeRF等神经渲染技术

未来的趋势是多模态融合(激光+相机)实时轻量化,这也是自动驾驶、机器人等领域的刚需。