3D 点云标注

功能概览
X-AnyLabeling 点云工作区支持逐点语义标注和实例标注:语义类别区分车辆、道路等类型,实例区分同一类别中的不同对象。支持逐帧编辑、复核和相机图像辅助,输出与原始点一一对应的标签文件。
数据准备
当前点云工作区支持 *.bin 和 *.ply 格式文件的导入。
| 文件 | 要求 |
|---|---|
.bin | 无文件头,每点依次为 X、Y、Z、强度,均为小端 float32,每点 16 字节。仅含 XYZ 的 BIN 需先转换。 |
.ply | PLY 1.0,支持 ASCII、小端和大端二进制;vertex 必须包含 x、y、z。可选 intensity;RGB 着色要求 red、green、blue 均为 uchar/uint8。顶点不支持 list 属性。 |
.label | 可选的已有标签,每点一个小端 uint32,点数和点序必须与点云一致,详见后续章节。 |
- 点云文件不能为空,坐标不能含 NaN 或无穷值。
- PCD、LAS、LAZ 等文件需先转换,缺少强度或 RGB 时,相应着色模式不可用;
- 工作区需要可用的 OpenGL 显示环境;若提示显示不可用,请检查显卡驱动及远程桌面的 OpenGL 支持。
可直接打开单个文件,也可按以下方式组织序列;labels、images 和两个 JSON 文件按需准备:
dataset/
├── velodyne/
│ ├── 000000.bin # or 000000.ply
│ └── 000001.bin # or 000001.ply
├── labels/
│ ├── 000000.label
│ └── 000001.label
├── images/
│ ├── 000000.png
│ └── 000001.png
├── classes.json
└── calibration.json
“打开目录”可选择直接存放 BIN/PLY 的目录;若所选目录下有 velodyne,则读取该子目录。文件按名称中的数字自然排序,不递归扫描其他子目录。
“打开文件”使用点云同目录、同名的 .label;“打开目录”会查找点云旁及数据集 labels 目录中的同名标签,多处匹配时提示选择。已设置序列输出目录时优先使用该目录;没有标签则以全零标签开始。classes.json 需通过“加载类别”导入,放在数据旁不会自动加载。
快速开始
- 在主窗口左侧工具栏点击“点云工作区”(坐标轴图标),无需先加载图像。
- 点击“打开文件”或“打开目录”导入点云;需要保留已有标签时,先指定新的“输出目录”。
- 在右侧“类别”中点击“新建类别”,填写 ID、名称和颜色,或用“加载类别”导入 JSON,然后选中目标类别。
- 选择“赋予语义类别”,按 B 使用笔刷拖涂,或按 P 逐点圈选多边形后按 Enter。选择完成即应用标注。
- 若需区分对象,切换“创建实例”,再次圈选已赋予该类别的目标;每次完成选择创建一个实例,补画同一对象时用“添加到当前实例”。
- 等待自动保存完成,检查底部状态;按 A/D 切换上一帧/下一帧。复核后可在帧列表右键选择“标记为已复核”。
标签修改会自动写回当前保存路径。保留原始标注时,请在编辑前备份标签或切换输出目录;“放弃”不会恢复已经自动保存的修改。
界面与工具
| 区域 | 用途 |
|---|---|
| 顶部文件工具栏 | 打开文件/目录、设置序列输出目录、当前帧另存为、配置相机图像;右端为键盘快捷键和帮助。 |
| 左侧帧列表 | 切换帧,查看标签文件是否存在及复核状态。勾选标记表示已有标签文件,圆点表示复核状态;悬停可查看点云和标签路径。 |
| 中央视图区及上方工具栏 | 浏览点云,选择标注工具、操作类型、选择深度和着色方式。 |
| 右侧类别与实例面板 | 管理类别、选择当前标注目标、控制显示,定位和合并实例。列表点数为全帧统计。 |
| 底部状态栏 | 查看点数、可见点数、保存状态及操作提示。 |
左右面板可用标题栏的折叠按钮收起,也可拖动分隔线调整宽度。工具图标的名称可通过悬停查看。
| 工具或操作 | 用法 |
|---|---|
| 浏览 V | 左键或中键拖动平移,右键拖动旋转,滚轮缩放。 |
| 笔刷 B | 左键拖涂,松开应用当前标注操作;Ctrl+滚轮调整笔刷半径。 |
| 多边形 P | 左键依次添加顶点;Enter、双击或点击起点闭合并应用,Esc 取消。圈选中可用 Ctrl+左键拖动平移、滚轮缩放;旋转会取消未完成的圈选。 |
| 适应全部点云 F | 将整帧点云纳入视野;俯视图、正视图、侧视图切换观察方向,重置视角恢复初始方向和范围。 |
| 撤销/重做 | 回退或恢复当前帧的点标签修改,快捷键见右上角“键盘快捷键”;切帧后不保留该帧的撤销历史。 |
| 穿透选择 | 关闭时只选当前视角表面点;开启时选中圈选范围内各个深度的点,仍排除被隐藏的点。 |
| 语义/强度/RGB/实例 | 分别按类别、强度、原始颜色或实例着色;只影响显示。实例模式中没有实例的点会暗化。 |
| 点大小 | 调整显示点大小,范围为 1~10 像素;与笔刷半径不同。 |
| A/D 或 PgUp/PgDown | 上一帧/下一帧;先点击点云视图、帧列表或相机视图使其获得焦点。 |
标注操作
先选类别或实例,再选操作,最后用笔刷或多边形选择点。切换工具、类别或标注操作会取消尚未完成的选择。
| 操作 | 结果与条件 |
|---|---|
| 赋予语义类别 | 将选中点改为当前类别;改变类别会清除这些点的实例 ID,同类别重涂保留实例。选择类别 0 则同时清除语义和实例标签。 |
| 创建实例 | 为选中点中属于当前非零类别的点创建实例,其他类别及未标注点会被排除;涉及已有实例时会提示确认转移。 |
| 添加到当前实例 | 先在实例列表选中目标,再圈选要补入的同类别点。涉及其他实例的点时会提示确认转移。 |
| 从当前实例移除 | 将圈选范围内属于当前实例的点移出,保留语义类别。 |
| 拆分当前实例 | 将当前实例的一部分点拆成新实例;不能选择空集或整个实例。 |
| 合并到当前实例 | 在实例列表用 Ctrl/Shift 多选同类别实例后点击合并;当前行是保留 ID 的目标实例。 |
| 删除实例 | 使用实例行的删除按钮,清除整个实例的实例 ID,保留语义类别。 |
类别行支持双击编辑名称和颜色,已有 ID 不可修改。移除类别定义会同时清除当前帧该类别的语义和实例标签,其他帧的标签文件不变;ID 0 保留给未标注点,不能删除。类别定义修改不属于点标签的撤销历史;标签中未定义的类别仍保留原 ID,可双击该类别行补充定义。
类别行的勾选控制该类别是否显示;实例行的选中用于指定操作目标,勾选则用于隔离显示。实例总开关打开且有实例被勾选时,仅显示这些实例;取消全部实例勾选后恢复显示,关闭实例总开关则只显示无实例点。类别隐藏仍然生效,“定位实例”可将当前实例纳入视野。
隐藏点不会被笔刷或多边形修改,但整实例删除、实例合并和移除类别会处理当前帧相应对象的全部点,包括隐藏点。建议先用多边形标出大区域,再用小笔刷修边;密集或遮挡场景先隔离类别/实例,再从多个视角检查,穿透选择适合需要一次覆盖前后层的目标。
输出格式
完成编辑后约 350 毫秒自动保存;连续编辑会延后保存。切帧或退出程序前会尝试保存,失败时提供保存、放弃或取消选项。关闭点云窗口仅隐藏工作区,同一次程序会话中重新打开会保留当前状态。
“输出目录”立即将当前帧写入所选目录,后续帧也以同名 .label 保存到该处,并记住此序列的目录设置;不会一次复制全部帧标签。后续帧在输出目录中尚无标签时,会尝试读取原位置的已有标签,后续保存写入输出目录。“另存为”只修改当前帧的保存路径,同一会话中再次编辑也写入该路径;建议保留点云同名,异名标签不会在重启后按名称自动匹配。
| 输出 | 内容 |
|---|---|
每帧 .label | 无文件头,小端 uint32,每点 4 字节。低 16 位为语义 ID,高 16 位为实例 ID:label = (instance_id << 16) | semantic_id。语义 0 表示未标注,实例 0 表示无实例,ID 范围均为 0~65535。 |
| 类别 JSON | 类别 ID、名称和颜色,需随标签一并交付;不包含点坐标或实例列表。 |
标签始终保存整帧点数,不受隐藏或筛选影响。原始 BIN/PLY 不会被改写;标注后不要重排、删减或插入原始点,否则标签会错位。实例以“类别 ID、实例 ID”组合区分,同一编号不保证跨类别或跨帧对应同一对象。
类别配置默认位于 <工作目录>/xanylabeling_data/pointcloud/pointcloud_classes.json;未指定工作目录时使用用户主目录。不同数据集使用不同类别表时,请显式“加载类别”;通过“保存类别”可另存 JSON,后续类别修改会保存到该文件。导入类别表只更新定义,不重映射已有点标签。格式如下,version 固定为 1,ID 唯一且必须包含 0,颜色使用 #RRGGBB:
{
"version": 1,
"classes": [
{"id": 0, "name": "未标注", "color": "#808080"},
{"id": 10, "name": "车辆", "color": "#6496F5"},
{"id": 40, "name": "道路", "color": "#FF00FF"}
]
}
帧列表的“已复核”是本机进度记录,不写入 .label。标记当前帧已复核时会先保存;文件变化后复核标记可能失效。自动保存或标签文件存在不代表已完成复核。
相机图像辅助
点击顶部 Camera image(相机图像),选择图像目录。图像与点云按不含扩展名的文件名匹配,如 000000.bin 对应 000000.png;支持 PNG、JPEG 等当前 Qt 可读取的图像,不递归扫描子目录。同目录不能出现同名不同扩展名的图像,如 000000.png 与 000000.jpg,缺少匹配图像时显示提示。
仅选择图像目录时,右上角显示参考图像;需要点云叠加时,再选择 Calibration JSON。图像支持左键拖动平移、滚轮缩放,双击或点击 Fit image 恢复适应显示;Projected points 开关控制叠加,颜色和隐藏状态随点云视图更新。相机图像用于观察,不能直接在图像上圈选修改点标签。
标定文件采用 X-AnyLabeling 自有 JSON 格式,一份标定对应一个固定相机及整段序列。以下字段均必填,不接受额外字段:
| 字段 | 定义 |
|---|---|
schema_version | 整数 1。 |
image_size | [宽, 高],单位为像素,必须是正整数且与实际图像尺寸一致。 |
camera_model | 固定为 "pinhole"。 |
camera_matrix | 3×3 内参,形式为 [[fx, 0, cx], [0, fy, cy], [0, 0, 1]],焦距必须为正,单位为像素。 |
T_pointcloud_to_camera | 4×4 点云到目标相机的刚体变换,上部为旋转 R 和平移 t,最后一行为 [0, 0, 0, 1]。旋转须正交且行列式为 +1。 |
distortion_model | "none" 或 "opencv5"。 |
distortion_coefficients | 无畸变时为 [];opencv5 时严格为 [k1, k2, p1, p2, k3],即三个径向和两个切向畸变系数。 |
矩阵按行存储,计算使用列向量:X_camera = R × X_pointcloud + t。输入是点云文件中的原始坐标;目标相机坐标 X 向右、Y 向下、Z 向前,图像左上角为像素原点,u 向右、v 向下。平移与点云必须使用相同长度单位;软件不会自动交换坐标轴、换算单位或反转变换方向,所有矩阵和畸变系数必须为有限数值。
原始畸变图像应使用其内参、外参及五参数畸变;已去畸变或校正的图像应使用处理后的内参和相机坐标系,设置 distortion_model: "none",不能再次套用原始畸变参数。投影依次执行坐标变换、归一化、畸变和内参映射,剔除相机后方及图像外的点;尺寸不匹配时保留参考图像并禁用投影,不自动缩放内参。
仓库提供同帧点云、图像和标定 JSON。打开示例 BIN,将图像目录设为 assets/pointcloud,选择其中的 calibration.json 即可查看叠加;其标定内容如下,仅适用于该样例对应的相机:
{
"schema_version": 1,
"image_size": [1241, 376],
"camera_model": "pinhole",
"camera_matrix": [
[718.856, 0.0, 607.1928],
[0.0, 718.856, 185.2157],
[0.0, 0.0, 1.0]
],
"T_pointcloud_to_camera": [
[0.00042768023855836203, -0.9999672484946015, -0.008084491683471012, 0.047953978595318754],
[-0.007210626507497482, 0.008081198471645075, -0.9999413164503825, -0.0551710332087719],
[0.9999738645903279, 0.00048594858103900374, -0.007206933692422334, -0.28841710386859104],
[0.0, 0.0, 0.0, 1.0]
],
"distortion_model": "none",
"distortion_coefficients": []
}
当前支持单相机、固定标定,不支持逐帧外参、鱼眼或其他畸变模型,也不直接导入 KITTI 标定文本。图像是否同帧需自行保证;软件只按名称关联,不做时间同步。叠加用于辅助检查,不能根据图像判断点是否被真实物体遮挡。重新启动程序后需重新选择图像目录和标定文件。