1. 点云数据读取与可视化
任务目标
本案例将使用 Open3D 读取 PCD/PLY 格式的点云文件,并实现基本的 3D 可视化。完成本案例后,你将能够:加载点云数据、在交互式窗口中旋转/缩放/平移视角,并通过键盘切换不同视角(前视、俯视、侧视)。
环境与依赖
- Python 3.8+
- Open3D:
pip install open3d - NumPy(Open3D 自动依赖,无需单独安装)
实现代码
以下代码完整实现了点云读取、可视化与视角切换功能。代码中内置了示例数据生成逻辑,确保在没有外部文件时也能直接运行验证。
import open3d as o3d
import numpy as np
import os
import sys
# ========== 1. 数据准备:生成或加载点云 ==========
def get_point_cloud(file_path=None):
"""从文件加载点云;若文件不存在或未指定,则生成一个示例点云(彩色立方体表面)"""
if file_path and os.path.exists(file_path):
# 根据扩展名自动选择读取函数
ext = os.path.splitext(file_path)[1].lower()
if ext in ['.pcd', '.ply']:
pcd = o3d.io.read_point_cloud(file_path)
if pcd.is_empty():
raise ValueError(f"文件 {file_path} 中未读取到有效点云")
return pcd
else:
raise ValueError(f"不支持的文件格式: {ext},仅支持 .pcd 或 .ply")
# 生成示例点云:立方体表面 + 随机噪声,便于观察三维结构
print("未指定有效文件,生成示例点云(立方体表面)...")
# 生成立方体8个顶点
vertices = np.array([
[0,0,0], [1,0,0], [1,1,0], [0,1,0],
[0,0,1], [1,0,1], [1,1,1], [0,1,1]
], dtype=np.float64)
# 对每条边进行插值,形成表面点
edges = [(0,1),(1,2),(2,3),(3,0),(4,5),(5,6),(6,7),(7,4),(0,4),(1,5),(2,6),(3,7)]
points = []
for a, b in edges:
for t in np.linspace(0, 1, 20):
points.append(vertices[a] + t * (vertices[b] - vertices[a]))
points = np.array(points)
# 添加少量噪声使点云更真实
points += np.random.normal(0, 0.01, points.shape)
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(points)
# 根据坐标生成颜色(便于视觉区分方向)
colors = (points - points.min(axis=0)) / (points.max(axis=0) - points.min(axis=0))
pcd.colors = o3d.utility.Vector3dVector(colors)
return pcd
# ========== 2. 视角切换回调 ==========
view_control = None # 全局引用,供回调使用
def switch_view(vis):
"""键盘回调:按1=前视(X轴),2=俯视(Z轴),3=侧视(Y轴)"""
global view_control
key = vis.get_key_code()
ctr = vis.get_view_control()
if key == ord('1'): # 前视:沿X轴看
ctr.set_front([1, 0, 0])
ctr.set_up([0, 0, 1])
elif key == ord('2'): # 俯视:沿Z轴看
ctr.set_front([0, 0, 1])
ctr.set_up([0, 1, 0])
elif key == ord('3'): # 侧视:沿Y轴看
ctr.set_front([0, 1, 0])
ctr.set_up([0, 0, 1])
else:
return False
return False # 返回False表示不阻止其他事件
# ========== 3. 主程序 ==========
def main():
# 支持命令行传入文件路径:python script.py your_file.pcd
file_path = sys.argv[1] if len(sys.argv) > 1 else None
# 加载点云
pcd = get_point_cloud(file_path)
print(f"点云点数: {len(pcd.points)}")
# 创建可视化窗口
vis = o3d.visualization.VisualizerWithKeyCallback()
vis.create_window(window_name="3D点云可视化", width=800, height=600)
# 添加点云到场景
vis.add_geometry(pcd)
# 注册键盘回调
vis.register_key_callback(ord('1'), switch_view)
vis.register_key_callback(ord('2'), switch_view)
vis.register_key_callback(ord('3'), switch_view)
# 设置初始视角(默认等轴测视角)
ctr = vis.get_view_control()
ctr.set_front([-0.5, -0.5, -0.5]) # 等轴测方向
ctr.set_up([0, 0, 1])
# 启动交互式窗口(阻塞直到窗口关闭)
vis.run()
vis.destroy_window()
if __name__ == "__main__":
main()
运行方式
- 将上述代码保存为
pointcloud_viewer.py - 直接运行(使用内置示例数据):
python pointcloud_viewer.py - 或指定点云文件运行:
python pointcloud_viewer.py your_pointcloud.pcd(支持 .pcd 和 .ply)
验证方法与判定标准
运行程序后,应出现一个3D可视化窗口,其中显示彩色立方体点云(或你指定的点云文件)。通过以下操作验证功能是否正常:
- 旋转:按住鼠标左键拖动,点云应随鼠标旋转
- 缩放:滚动鼠标滚轮,点云应放大/缩小
- 平移:按住
Ctrl+ 鼠标左键拖动(或按住鼠标右键拖动),点云应平移 - 视角切换:按下键盘
1键,视角切换为前视(沿X轴方向);按2键切换为俯视(沿Z轴方向);按3键切换为侧视(沿Y轴方向)
通过条件:以上所有交互操作均能正常响应,且视角切换后点云显示方向正确(例如俯视时看到的是立方体顶面)。窗口关闭后程序正常退出,无报错。
常见问题
- 窗口无法打开:确认已安装 Open3D 且版本 ≥ 0.13(
pip install --upgrade open3d) - 读取文件失败:确认文件路径正确且格式为 PCD/PLY 二进制或 ASCII 格式
- 视角切换无效:确保点击窗口使其获得键盘焦点后再按键