FiftyOne 3D Visual AI 实战指南:点云、网格与 3D 标注的完整数据工作流
2026/9/16 12:19:03 网站建设 项目流程

FiftyOne 3D Visual AI 实战指南:点云、网格与 3D 标注的完整数据工作流

【免费下载链接】fiftyoneRefine high-quality datasets and visual AI models项目地址: https://gitcode.com/GitHub_Trending/fi/fiftyone

本指南基于 FiftyOne 官方 3D Visual AI Guide(见 docs/source/getting_started/threed_visual_ai/index.rst),系统讲解如何在 FiftyOne 中完成从原始 3D 数据(LiDAR 点云、GLTF/OBJ/PLY/STL/FBX 网格)的加载与可视化,到 3D 边界框、3D 折线等标注的叠加、查询与校验的完整工作流。读完本文,你将掌握fo.Scene()场景构建、FO3D 文件格式、3D 查看器交互导航,以及 2D/3D 标注类自动切换的核心用法,可直接应用于自动驾驶、机器人、AR/VR 等空间计算场景的数据整理与模型训练准备。

指南概述:一条完整的 3D 数据处理链路

官方指南将整个 3D 工作流拆解为两个循序渐进的步骤(对应两个 Jupyter Notebook):

  1. 入门 3D 数据集(Getting Started with 3D Datasets)——学习如何在 FiftyOne 中加载和可视化原始 3D 数据(含点云),在 3D 查看器中完成基本导航,并围绕空间任务组织数据集。对应文件:01_getting_started_3d.ipynb。
  2. 加载 3D 标注(Loading 3D Annotations)——为点云添加边界框与标签等标注,学习如何引入标注并使其无缝叠加到场景中,用于检查与验证。对应文件:02_loading_annotations.ipynb。

两个 Notebook 均可独立运行——每个文件开头都包含必要的pip install命令,无需预先配置任何环境。

前置条件

目标读者:面向希望在 FiftyOne 中处理 3D 数据集的开发者与计算机视觉工程师。无论你面对的是 LiDAR 点云、体素网格还是 3D 边界框,本系列都会介绍所需的工具与工作流。

所需知识:熟悉 FiftyOne 的数据集结构(Dataset/Sample/ 标签字段体系)与基础计算机视觉概念即可;有 2D 检测标注经验会更快上手,点云或 3D 标注经验非必需。

主要依赖包

用途
fiftyone核心库:数据集管理、场景构建与 3D 可视化
open3d3D 数据处理与点云操作(可选辅助)
numpy数值运算与数组操作
matplotlib可视化与绘图

系统要求(按官方指南):

  • 操作系统:Linux(Ubuntu 24.04)、macOS
  • Python:3.10、3.11、3.12
  • 内存:3D 操作建议 8GB RAM
  • 存储:预留 5GB 可用空间存放 3D 数据集
  • 显卡:大型点云可视化建议配备 GPU
  • Notebook 环境:Jupyter、Google Colab、VS Code Notebook 均已验证

3D 数据格式全景

点云(Point Clouds)

  • LiDAR 数据——来自自动驾驶车辆与机器人的原始传感器数据
  • PLY 格式——带颜色与法线信息的标准点云格式(亦可表示网格)
  • PCD 格式——面向高效存储的点云数据格式,是 FiftyOnePointCloud对象直接支持的类型
  • XYZ 格式——基于简单坐标系的点云表示

3D 网格(3D Meshes)

  • GLTF/GLB——现代 3D 格式,支持材质与动画
  • OBJ——Wavefront Object 格式,常用于 3D 几何建模
  • PLY——Stanford Triangle 格式,可表示网格或点云
  • STL——用于 3D 打印的立体光刻格式
  • FBX——Autodesk 3D 内容交换格式(支持 FBX 7.x+)

3D 标注(3D Annotations)

  • 3D 边界框(3D Bounding Boxes)——目标检测,包含位置、尺寸与旋转
  • 3D 折线(3D Polylines)——3D 空间中的路径与车道线标注
  • 3D 分割(3D Segmentation)——面向语义理解的点级标注

核心工作流:加载 → 场景管理 → 可视化 → 标注集成

官方指南演示的完整 3D 数据工作流由四步组成:

  1. 数据加载(Data Loading)——以正确的坐标系与变换加载不同 3D 格式(点云、网格)
  2. 场景管理(Scene Management)——使用 FiftyOne 的Scene类与 FO3D 文件格式创建、组织 3D 场景
  3. 3D 可视化(3D Visualization)——在 FiftyOne 交互式 3D 查看器中导航与交互
  4. 标注集成(Annotation Integration)——添加 3D 边界框、折线等标注,支撑综合分析

这套集成式方案不仅让你"能加载"3D 数据,更能理解空间关系、管理复杂 3D 场景,并面向 3D 计算机视觉应用准备数据集。


Step 1:入门 3D 数据集

理解 FiftyOne Scene 与 FO3D 文件

FiftyOne 通过fo.Scene()管理 3D 样本,其序列化产物即FO3D 文件.fo3d后缀)。从源码看,Scene本质是一个场景图:内部以 n 叉树结构组织 3D 对象,每个对象是树中的一个节点(参见 fiftyone/core/threed/scene_3d.py 中Scene类定义)。一个 3D 对象可以是:

  • 3D 网格(Mesh)——ObjMeshGltfMeshPlyMeshStlMeshFbxMesh
  • 点云(Point Cloud)——PointCloud
  • 3D 形状几何(Shape Geometry)——BoxGeometrySphereGeometry等(参见 fiftyone/core/threed/shape_3d.py)

Scene还可显式初始化cameralightsbackground等附加属性。默认情况下,场景使用中性光照(一个环境光加六个不同角度的方向光),并使用右手坐标系、up 轴为 Y 轴的透视相机——可通过PerspectiveCamera(up="Z")等参数覆盖(相机类定义见 fiftyone/core/threed/camera.py,支持up/fov/near/far参数,默认 fov=50、near=0.1、far=2000)。

场景构建完成后,必须调用scene.write()将其序列化为轻量级 FO3D 文件写入磁盘。从源码(scene_3d.py)可以看到,write()会校验输出路径必须以.fo3d结尾、检查节点重名,并支持resolve_relative_paths(将资源相对路径解析为绝对路径)与pprint(JSON 美化输出)两个选项。

如何加载一个 3D 样本

任何 filepath 以.fo3d结尾的 Sample 都会被识别为 3D 样本,由 3D 样本组成的数据集其media_type3d。你可以在一个.fo3d场景内存储多个 3D 对象,用单个样本封装整个待覆盖的场景。

import fiftyone as fo # 1. 构建场景:设置相机 up 轴为 Z scene = fo.Scene() scene.camera = fo.PerspectiveCamera(up="Z") # 2. 添加自定义网格对象 mesh = fo.GltfMesh("mesh", "mesh.glb") mesh.rotation = fo.Euler(90, 0, 0, degrees=True) # 3. 添加两个几何球体并自定义颜色与位置 sphere1 = fo.SphereGeometry("sphere1", radius=2.0) sphere1.position = [-1, 0, 0] sphere1.default_material.color = "red" sphere2 = fo.SphereGeometry("sphere2", radius=2.0) sphere2.position = [1, 0, 0] sphere2.default_material.color = "blue" scene.add(mesh, sphere1, sphere2) # 4. 写入 FO3D 文件 scene.write("/path/to/scene.fo3d") # 5. 作为样本加入数据集 sample = fo.Sample(filepath="/path/to/scene.fo3d") dataset = fo.Dataset() dataset.add_sample(sample) print(dataset.media_type) # 3d

上面这段代码中,mesh.glb与两个球体被一并加入场景:通过position校正各对象位置,通过default_material.color定制颜色,最后整体写出为 FO3D 文件。这正是 FiftyOne 的核心思路——一个.fo3d文件 = 一个完整 3D 场景 = 一个 Sample

修改既有场景

若要修改已存在的场景,使用Scene.from_fo3d()加载,执行必要的更新后再写回磁盘:

scene = fo.Scene.from_fo3d("/path/to/scene.fo3d") for node in scene.traverse(): if isinstance(node, fo.SphereGeometry): node.visible = False scene.write("/path/to/scene.fo3d")

其中traverse()是场景图的深度遍历接口(源码见 scene_3d.py),它递归产出场景中的所有Object3D节点,是批量操作场景内对象的统一入口。与此配套的还有get_scene_summary()(统计各类对象数量)、get_asset_paths()(列出全部资源路径)与update_asset_paths()(按映射批量改写资源路径)等实用方法,均有对应单元测试覆盖(见 tests/unittests/threed/scene_3d_tests.py)。

3D 网格:格式支持与材质处理

3D 网格由顶点、边与面组成,定义对象的几何形状。部分格式只存几何,另一些则同时包含材质属性与纹理——若网格文件含材质与纹理,FiftyOne 会自动加载并显示。你也可以通过设置网格的default_material属性来指定默认材质;当文件不含任何材质信息时,网格会被赋予一个默认的MeshStandardMaterial(含colorroughnessmetalnessopacityemissive_color等参数,见 fiftyone/core/threed/material_3d.py),且可在 App 中动态调整。

FiftyOne 当前支持GLTF、OBJ、PLY、STL、FBX 7.x+网格格式,对应类(见 fiftyone/core/threed/mesh.py):

import fiftyone as fo scene = fo.Scene() mesh1 = fo.GltfMesh("mesh1", "mesh.glb") mesh1.rotation = fo.Euler(90, 0, 0, degrees=True) mesh2 = fo.ObjMesh("mesh2", "mesh.obj") # 可选 mtl_path 参数加载 .mtl 材质 mesh3 = fo.PlyMesh("mesh3", "mesh.ply") # 可选 is_point_cloud / center_geometry mesh4 = fo.StlMesh("mesh4", "mesh.stl") mesh5 = fo.FbxMesh("mesh5", "mesh.fbx") scene.add(mesh1, mesh2, mesh3, mesh4, mesh5) scene.write("/path/to/scene.fo3d")

几个值得注意的实现细节(均可在 mesh.py 中验证):

  • 路径校验ObjMesh要求obj_path.obj结尾、mtl_path.mtl结尾,FbxMesh/PlyMesh/StlMesh分别要求.fbx/.ply/.stlGltfMesh要求.gltf.glb,否则抛出ValueError;资源路径既可以是绝对路径,也可以相对于.fo3d文件所在目录
  • PLY 的双重身份PlyMesh通过is_point_cloud参数区分"网格"与"点云"两种形态,并默认center_geometry=True自动居中几何体。
  • OBJ 材质ObjMesh支持mtl_path显式关联.mtl材质文件;若未提供或文件中找不到材质,则回退到默认MeshStandardMaterial

3D 点云:PCD 格式与材质控制

FiftyOne 直接支持PCD 点云格式。创建一个可加入 3D 场景的 PCD 对象:

import fiftyone as fo pcd = fo.PointCloud("my-pcd", "point-cloud.pcd") pcd.default_material.shading_mode = "custom" pcd.default_material.custom_color = "red" pcd.default_material.point_size = 2 scene = fo.Scene() scene.add(pcd) scene.write("/path/to/scene.fo3d")

PointCloud类(见 fiftyone/core/threed/pointcloud.py)要求pcd_path.pcd结尾,并支持center_geometry(默认False)与flag_for_projection(标记用于正交投影,每个场景最多一个)等参数。其默认材质PointCloudMaterial提供以下可调项(见 material_3d.py):

参数默认值说明
shading_mode"height"着色模式,支持height(按高度)、intensity(按强度)、rgb(按颜色)、custom(自定义色)
custom_color"#ffffff"自定义颜色,仅当shading_mode="custom"时生效
point_size1.0点的大小
opacity1.0不透明度,范围[0, 1]

多传感器点云叠加

3D 场景与点云的一大优势在于:可以在同一场景中堆叠多个点云,以镜像不同传感器的输出。例如,一个 LiDAR 传感器与多个按相同时间间隔触发的 RADAR 传感器——用 FiftyOne 可同时可视化全部点云,也可按需逐个开关。这一设计思路来自Scene的 n 叉树场景图结构:任意数量的网格、点云与形状都可以作为独立节点挂载在同一场景下,通过visible属性控制显示状态。


Step 2:加载 3D 标注

3D 样本上的标注字段

3D 样本可以包含任意类型与数量的自定义字段,包括3D 检测3D 折线,它们可被 App 的 3D 可视化器原生显示。与几何数据不同的是,3D 标注存储在数据集专门的字段中,而非嵌入 FO3D 文件——因此它们可以像其他原始/标签字段一样,通过数据集视图(dataset views)在 App 中进行查询与过滤。典型用法如下:

import fiftyone as fo scene = fo.Scene() scene.add(fo.GltfMesh("mesh", "mesh.gltf")) scene.write("/path/to/scene.fo3d") detection = fo.Detection( label="vehicle", location=[0.47, 1.49, 69.44], dimensions=[2.85, 2.63, 12.34], rotation=[0, -1.56, 0], ) sample = fo.Sample( filepath="/path/to/scene.fo3d", ground_truth=fo.Detections(detections=[detection]), )

3D 边界框参数详解:location / dimensions / rotation

下面逐个拆解locationdimensionsrotation的含义(这些参数在源码 fiftyone/core/labels.py 的Detection类文档中有明确定义):

import fiftyone as fo # 对象标签 label = "vehicle" # 对象中心 [x, y, z],使用场景坐标 location = [0.47, 1.49, 69.44] # 对象尺寸 [x, y, z],使用场景单位 dimensions = [2.85, 2.63, 12.34] # 对象绕其中心的旋转 [x, y, z],取值范围 [-pi, pi] rotation = [0, -1.56, 0] # 一个 3D 目标检测 detection = fo.Detection( label=label, location=location, dimensions=dimensions, rotation=rotation, )

关于坐标系的注意点:这里的场景坐标从[0, 0, 0]开始,该原点几乎总是自车(ego)位置,即传感器开始采集的位置;它并不映射到任何已知的全局坐标(如 GPS/UTM)。在做多帧数据融合或跨传感器标注对齐时,务必确认各数据的坐标系约定一致。

3D 折线(Polylines)

3D 折线的用法与 3D 检测高度相似:它同样作为数据集上的专用字段存储,需要labelpoints3d两个参数:

# 对象标签 label = "lane" # 一个列表的列表,每个元素为场景坐标下的 [x, y, z] 顶点, # 描述折线中每条形状的顶点 points3d = [[[-5, -99, -2], [-8, 99, -2]], [[4, -99, -2], [1, 99, -2]]] # 一组语义相关的 3D 折线 polyline = fo.Polyline(label=label, points3d=points3d)

points3d是一个嵌套结构:外层列表对应多条形状,内层列表对应每条形状的顶点序列,每个顶点是[x, y, z]三元组。这与 2DPolylinepoints参数([0,1]×[0,1]归一化坐标)在结构上类似,但坐标语义从归一化平面坐标切换为场景三维坐标。

自动的 2D / 3D 标注类型切换

注意一个关键设计:3D 场景下你并不使用Detection3DPolyline3D。FiftyOne 的DetectionPolyline标签类会根据输入参数自动适配 2D 或 3D 形态:

  • Detection:提供bounding_box(2D)时按 2D 目标检测处理;提供location+dimensions+rotation(3D)时按 3D 目标检测处理(参见 labels.py 的类文档)。
  • Polyline:提供points(2D)或points3d(3D)时分别对应 2D/3D 折线。

这意味着你可以在同一数据集内混用 2D 与 3D 标注,FiftyOne 自动完成区分与可视化,无需维护两套标签体系。


总结:你已经掌握了什么

完成上述两步后,你已具备:

  • Step 1(入门 3D 数据集):加载并可视化原始 3D 数据(含点云);理解Scene类与 FO3D 文件格式;处理 GLTF、OBJ、PLY、STL、FBX 等不同网格格式;在 3D 查看器中完成基本导航;围绕空间任务组织 3D 数据集并理解坐标系。
  • Step 2(加载 3D 标注):为点云添加边界框与标签等标注;理解 3D 边界框的location(位置)、dimensions(尺寸)、rotation(旋转)参数;用 3D 折线做路径标注;掌握 FiftyOne 如何自动处理 2D 与 3D 标注类型。

建议练习

  1. 多格式 3D 数据:分别用 GLTF、OBJ、PLY、STL 加载同一对象,对比其在 FiftyOne 中的加载与显示差异,评估哪种格式最适合你的场景。
  2. 3D 场景合成:组合多个网格、点云与几何形状构建复杂 3D 场景,观察场景组织方式对可视化效果的影响。
  3. 3D 标注分析:混用边界框、折线与分割等不同类型 3D 标注,分析其空间关系。
  4. 坐标系理解:实验不同的坐标系与变换(如Euler旋转、相机up轴设置),观察它们如何影响 3D 可视化与标注精度。
  5. 性能优化:使用大型点云并调节不同可视化设置(如point_size、着色模式),观察数据规模对性能的影响。

进一步方向

  • 评估 3D 目标检测模型:引入预测结果与真值,对 3D 边界框运行性能评估。
  • 可视化多模态传感器数据:将点云与 2D 图像、分割掩码等结合,获得全场景理解。
  • 构建自定义 3D 工作流:针对自动驾驶、机器人、AR/VR 等具体领域创建专属工作流。

延伸阅读(仓库内资源)

  • 指南索引页:docs/source/getting_started/threed_visual_ai/index.rst
  • 配套 Notebook ①(场景、网格、点云):01_getting_started_3d.ipynb
  • 配套 Notebook ②(3D 标注):02_loading_annotations.ipynb
  • 指南总结与练习:summary.rst
  • 核心源码:场景与 FO3D 序列化见 fiftyone/core/threed/scene_3d.py,网格类见 fiftyone/core/threed/mesh.py,点云见 fiftyone/core/threed/pointcloud.py,材质见 fiftyone/core/threed/material_3d.py,相机见 fiftyone/core/threed/camera.py,3D 标注定义见 fiftyone/core/labels.py
  • 单元测试:tests/unittests/threed/scene_3d_tests.py(覆盖 FO3D 写入/读取、资源路径解析、场景摘要、高斯溅射等)、tests/unittests/threed/transformation_tests.py、tests/unittests/threed/material_3d_tests.py

【免费下载链接】fiftyoneRefine high-quality datasets and visual AI models项目地址: https://gitcode.com/GitHub_Trending/fi/fiftyone

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询