2. Open3D入门与环境搭建

点云处理的第一步,就是搭好环境。Open3D 是目前最友好的点云库之一,我这些年做项目,从 PCL 转到 Open3D 后,开发效率提升了不少。这一章我们就把 Open3D 装好,跑通第一个点云程序。

2.1 安装 Open3D

Open3D 支持 Python 和 C++。我个人习惯用 Python,调试快,适合做原型验证。安装方式很简单,一行命令搞定:

pip install open3d

如果你用的是 conda 环境,也可以:

conda install -c open3d-admin open3d
小提示: 建议在 Python 3.8-3.11 环境下安装。我遇到过 Python 3.12 某些版本兼容性问题,后来降级就正常了。

安装完成后,验证一下:

import open3d as o3d
print(o3d.__version__)

如果输出版本号(比如 0.18.0),说明安装成功。

2.2 核心数据结构:PointCloud 与 Geometry

Open3D 里最常用的数据结构就是 PointCloud。它本质上是一个点的集合,每个点包含三维坐标 (x, y, z)。

创建一个点云对象很简单:

import open3d as o3d
import numpy as np

# 创建空点云
pcd = o3d.geometry.PointCloud()

# 生成随机点数据
points = np.random.rand(100, 3)
pcd.points = o3d.utility.Vector3dVector(points)

print(pcd)
print(f"点数: {len(pcd.points)}")

这里有个关键点:pcd.points 接收的是 Vector3dVector 类型,不能直接赋值 numpy 数组。我第一次用的时候就踩了这个坑,直接赋值报错,后来查文档才明白。

除了坐标,点云还可以带颜色和法向量:

# 添加颜色(RGB 范围 0-1)
colors = np.random.rand(100, 3)
pcd.colors = o3d.utility.Vector3dVector(colors)

# 添加法向量
normals = np.random.rand(100, 3)
pcd.normals = o3d.utility.Vector3dVector(normals)

Open3D 的几何体继承关系如下:

Geometry 基类 → PointCloud, TriangleMesh, LineSet, Image 等

也就是说,PointCloud 是 Geometry 的子类。这种设计让可视化、变换等操作可以统一处理。

2.3 基本 IO 操作

实际项目中,点云数据通常来自文件。Open3D 支持多种格式:

格式 说明 读写支持
.ply Stanford 格式,支持颜色和法向量 读/写
.pcd Point Cloud Library 格式 读/写
.xyz 纯文本,每行 x y z 读/写
.las/.laz LiDAR 标准格式(需额外插件) 读

读写代码非常简洁:

# 读取点云
pcd = o3d.io.read_pointcloud("data/example.ply")

# 写入点云
o3d.io.write_pointcloud("output.pcd", pcd)
注意: 读取 .las 文件需要安装 laspy 库。我曾经在项目里直接读 .las 报错,排查了半天才发现是格式问题。

读取后,建议先检查点云是否为空:

if pcd.is_empty():
    print("点云为空,请检查文件路径")
else:
    print(f"加载了 {len(pcd.points)} 个点")

2.4 可视化窗口控制

Open3D 的可视化非常强大,一行代码就能看到点云:

o3d.visualization.draw_geometries([pcd])

但实际项目中,我们需要更多控制。比如调整窗口大小、背景色、点大小:

# 创建可视化窗口
vis = o3d.visualization.Visualizer()
vis.create_window(window_name="我的点云", width=800, height=600)

# 添加几何体
vis.add_geometry(pcd)

# 设置渲染选项
opt = vis.get_render_option()
opt.background_color = np.array([0.1, 0.1, 0.1])  # 深灰色背景
opt.point_size = 2.0  # 点大小

# 运行可视化
vis.run()
vis.destroy_window()

你想想看,为什么背景要设成深色?因为浅色背景下,白色点云会看不清。我在做室内点云项目时,默认白色背景,结果点云几乎隐身,后来改成深灰就好了。

常用控制快捷键:

  • 左键拖拽:旋转视角
  • 滚轮:缩放
  • Ctrl + 左键:平移
  • R:重置视角
  • H:显示帮助

2.5 本章知识体系

下面这张图总结了本章的核心内容:

Open3D 入门知识体系 环境安装 核心数据结构 文件 IO 可视化控制 pip / conda PointCloud Geometry 基类 ply / pcd / xyz Visualizer 类 安装 → 数据结构 → IO → 可视化 这是本章的学习路径

2.6 完整示例:加载并显示点云

把上面学到的串起来,写一个完整的程序:

import open3d as o3d
import numpy as np

def load_and_visualize(file_path):
    # 1. 读取点云
    pcd = o3d.io.read_pointcloud(file_path)
    if pcd.is_empty():
        print("文件为空或格式不支持")
        return
    
    # 2. 打印信息
    print(f"点数: {len(pcd.points)}")
    print(f"有颜色: {pcd.has_colors()}")
    print(f"有法向量: {pcd.has_normals()}")
    
    # 3. 可视化
    vis = o3d.visualization.Visualizer()
    vis.create_window(window_name="点云查看器", width=1024, height=768)
    vis.add_geometry(pcd)
    
    opt = vis.get_render_option()
    opt.background_color = np.array([0.2, 0.2, 0.2])
    opt.point_size = 3.0
    
    vis.run()
    vis.destroy_window()

if __name__ == "__main__":
    load_and_visualize("data/sample.ply")
避坑指南: 我曾经在读取大文件(超过 500 万点)时,直接 draw_geometries 会卡死。后来改用 Visualizer 类,并设置 vis.poll_events() 循环,才解决。大点云建议分块加载。