基于 BOP 格式构建 PVN3D 自定义训练数据集技术文档

1. 目的

本文说明如何基于 BOP 风格的数据组织方式,为当前仓库中的 PVN3D 准备可训练的自定义数据集。

重点回答四个问题:

  1. PVN3D 训练到底依赖哪些文件
  2. 如果数据已经是 BOP 格式,需要补齐什么
  3. 如果只是沿用现有 LINEMOD 类别,如何最小代价接入
  4. 如果是真正的自定义新类别,代码和数据还需要改哪些地方

本文基于当前仓库代码,而不是通用的 BOP 理论描述。


2. 先给结论

如果你只是想把"BOP 格式的数据"拿来训练当前仓库里的 PVN3D,需要先明确你属于哪一种情况。

情况 A:对象类别仍然是当前仓库已经支持的 LINEMOD 类别

例如:

  • ape
  • can
  • driller
  • duck

这时你主要需要做的是:

  1. 准备符合 BOP 结构的训练数据
  2. 转换到 Linemod_preprocessed
  3. 确保 models/train.txtgt.ymlrgb/depth/mask 可用
  4. 可选地准备 renders/

这种情况最简单,因为:

  • 类别映射已经存在
  • lm_obj_kps 已经存在
  • 关键点文件已经存在
  • 训练代码基本不用改

情况 B:你要训练真正的新物体类别

例如:

  • 自己采集的工业零件
  • 当前仓库里没有的对象 ID
  • 自定义 BOP 数据集而不是 LINEMOD 对象

这时除了数据转换外,还必须补齐:

  1. 类别映射
  2. 模型文件
  3. 关键点文件
  4. models_info.yml
  5. 训练脚本和配置中的对象列表

这不是单纯"转一下 BOP 数据"就能完成的事情,而是要把新类别接入当前 LINEMOD 风格管线。


3. 当前仓库训练时真正依赖什么

当前 LINEMOD 训练入口是:

训练数据集是:

训练集初始化时,LM_Dataset('train', cls_type=...) 直接依赖这些文件:

text 复制代码
Linemod_preprocessed/
├── data/
│   └── {obj_id:02d}/
│       ├── train.txt
│       ├── gt.yml
│       ├── rgb/*.png
│       ├── depth/*.png
│       └── mask/*.png
├── models/
│   └── obj_{obj_id:02d}.ply

可选增强数据:

text 复制代码
Linemod_preprocessed/
├── renders/{cls}/*.pkl
├── renders/{cls}/file_list.txt
├── fuse/{cls}/*.pkl
└── fuse/{cls}/file_list.txt

另外,训练和评估还依赖:

text 复制代码
pvn3d/datasets/linemod/lm_obj_kps/{cls}/
├── corners.txt
├── farthest.txt
├── farthest4.txt
├── farthest12.txt
├── farthest16.txt
└── farthest20.txt

以及:

text 复制代码
pvn3d/datasets/linemod/dataset_config/models_info.yml

4. 从代码角度看,训练最少需要什么

4.1 每帧训练样本需要的信息

linemod_dataset.py 中,每个训练样本最终需要得到:

  • RGB 图像
  • 深度图
  • 单物体 mask
  • 相机内参 K
  • 位姿 RT

这些会被转换成:

  • 点云
  • 每点的 RGB 特征
  • 中心偏移监督
  • 关键点偏移监督

所以无论你的原始数据格式是什么,只要想训练 PVN3D,最终必须为每个样本提供:

  1. 彩色图
  2. 深度图
  3. 当前物体的二值 mask
  4. 当前物体的 6D pose
  5. 相机内参

4.2 每个类别还需要的信息

训练不是只靠逐帧标注就够了。每个类别还必须有:

  1. 物体 3D 模型 .ply
  2. 物体关键点文件 farthest*.txt
  3. 包围盒角点文件 corners.txt
  4. 类别到 obj_id 的映射

对应代码读取位置:


5. 如果你的数据已经是 BOP 格式,需要具备哪些内容

当前仓库已经有训练转换脚本:

从这个脚本的输入可以看出,BOP 根目录至少要具备:

text 复制代码
<bop_root>/
├── lm_models/
│   └── models/
│       ├── obj_000001.ply
│       ├── obj_000002.ply
│       └── ...
├── lm_train/
│   └── train/
│       └── 000001/
│           ├── rgb/
│           ├── depth/
│           ├── mask/
│           └── scene_gt.json
└── lm_train_pbr/
    └── train_pbr/
        └── 000000/
            ├── rgb/
            ├── depth/
            ├── mask_visib/
            ├── scene_gt.json
            └── scene_camera.json

也支持 zip 包形式:

  • lm_train.zip
  • lm_train_pbr.zip

5.1 真实训练数据最少要求

真实训练数据转换时,脚本实际读取:

  • scene_gt.json
  • rgb/{frame}.png.jpg
  • depth/{frame}.png
  • mask/{frame}_{ann_idx}.png

也就是说,真实训练样本最少要有:

  • RGB
  • depth
  • 每个实例的 mask
  • 6D pose 标注

5.2 PBR 合成训练数据最少要求

PBR 训练数据转换时,脚本实际读取:

  • scene_gt.json
  • scene_camera.json
  • rgb/{frame}.jpg.png
  • depth/{frame}.png
  • mask_visib/{frame}_{ann_idx}.png,如果没有则退回 mask/

也就是说,PBR 样本除了 pose,还必须有相机内参和深度缩放信息。

5.3 模型文件要求

模型目录必须存在:

text 复制代码
lm_models/models/obj_{obj_id:06d}.ply

转换后会拷贝到:

text 复制代码
Linemod_preprocessed/models/obj_{obj_id:02d}.ply

6. BOP 转换后,PVN3D 训练目录应当长什么样

如果你要训练单个对象,例如 ape,最终至少应得到:

text 复制代码
pvn3d/datasets/linemod/Linemod_preprocessed/
├── data/
│   └── 01/
│       ├── train.txt
│       ├── test.txt
│       ├── gt.yml
│       ├── rgb/
│       ├── depth/
│       └── mask/
├── models/
│   └── obj_01.ply
└── renders/
    └── ape/
        ├── *.pkl
        └── file_list.txt

其中:

  • train.txt 是训练硬依赖
  • test.txt 用于测试和验证
  • gt.yml 是当前仓库使用的位姿标注格式
  • renders/ape 是可选但推荐的合成训练数据

如果你没有 renders/,训练仍能启动,但只能用真实图像。


7. 当前仓库现成脚本能处理到什么程度

7.1 测试集转换脚本

作用:

  1. lm_test_all/test
  2. 生成 test.txt
  3. 生成 gt.yml
  4. 拷贝模型 .ply

这个脚本只够:

  • 测试
  • demo
  • eval

不够直接训练,因为它不生成:

  • train.txt
  • renders/*.pkl

7.2 训练集转换脚本

作用:

  1. 将 BOP 真实训练数据转成 data/%02d/*
  2. 生成 train.txt
  3. 生成 gt.yml
  4. 将 PBR 数据转成 renders/{cls}/*.pkl
  5. 拷贝模型 .ply

也就是说,当前仓库已经具备:

  • BOP 训练数据接入能力

但它的前提是:

  • 你的对象类别仍然是当前脚本支持的对象 ID

8. 如果只是沿用现有 LINEMOD 类别,应如何准备数据

这是最稳妥的路径。

8.1 数据侧需要准备

你需要准备一套符合 BOP 结构的数据根目录,例如:

text 复制代码
/workspace/bop/
├── lm_models/models/
├── lm_train/train/
└── lm_train_pbr/train_pbr/

说明:

  • 你当前说明 BOP 数据根目录是 /workspace/bop
  • 当前仓库的转换脚本支持通过 --bop-root 显式指定该路径

如果你的数据就在 /workspace/bop,只需要显式传参即可。

8.2 执行训练转换

例如把数据转换到当前仓库默认训练目录:

bash 复制代码
python pvn3d/datasets/convert_bop_lm_train_to_pvn3d.py \
  --bop-root /workspace/bop \
  --output-root /home/xx/project/workflow/self/PVN3D/pvn3d/datasets/linemod/Linemod_preprocessed \
  --scene-ids 1 \
  --overwrite

如果只转真实训练数据:

bash 复制代码
python pvn3d/datasets/convert_bop_lm_train_to_pvn3d.py \
  --bop-root /workspace/bop \
  --output-root /home/xx/project/workflow/self/PVN3D/pvn3d/datasets/linemod/Linemod_preprocessed \
  --scene-ids 1 \
  --real-only \
  --overwrite

如果只转 PBR 数据:

bash 复制代码
python pvn3d/datasets/convert_bop_lm_train_to_pvn3d.py \
  --bop-root /workspace/bop \
  --output-root /home/xx/project/workflow/self/PVN3D/pvn3d/datasets/linemod/Linemod_preprocessed \
  --scene-ids 1 \
  --pbr-only \
  --overwrite

8.3 做目录校验

可以用仓库里的检查脚本验证布局:

bash 复制代码
python pvn3d/datasets/check_linemod_pvn3d_layout.py \
  --data-root /home/xx/project/workflow/self/PVN3D/pvn3d/datasets/linemod/Linemod_preprocessed \
  --obj-ids 1

注意:

  • 这个检查脚本主要检查 test.txt
  • 对训练来说,你还应额外确认 train.txt 存在且非空

8.4 启动训练

bash 复制代码
cd /home/xx/project/workflow/self/PVN3D/pvn3d
conda activate pvn3d
python -m train.train_linemod_pvn3d --cls ape

如果显存较小,则结合前面已经支持的参数:

bash 复制代码
PYTORCH_CUDA_ALLOC_CONF=max_split_size_mb:64 python -m train.train_linemod_pvn3d \
  --cls ape \
  --mini_batch_size 1 \
  --val_mini_batch_size 1 \
  --n_sample_points 4096 \
  --num_workers 2

9. 自定义自己的测试场景数据集,如何采集并制作成 LINEMOD / PVN3D 可用格式

这一节讨论的是:

  • 你已经有自己的真实场景
  • 想采集一批 RGB-D 测试样本
  • 希望最终接到当前仓库的 demo / eval / test 流程

这里需要先分清两个层次:

  1. 场景数据本身如何采集
  2. 采集后如何整理成当前仓库可读的 Linemod_preprocessed 风格

9.1 自采测试场景最少需要采到什么

如果目标只是"让 PVN3D 在自己的真实场景里测试",每个场景帧至少需要以下信息:

  1. RGB 图像
  2. 深度图
  3. 当前目标物体的 mask
  4. 相机内参
  5. 目标物体的真实 6D pose

其中:

  • RGB、深度图是输入
  • mask 和 pose 是评估时的真值
  • 内参用于把深度还原成点云以及做投影

如果你只想做"无标注 demo",则可以临时不准备:

  • mask
  • pose

但如果你想做真正的定量测试,就必须有这两项。

9.2 采集流程建议

推荐的采集流程是:

  1. 固定相机,并完成相机内参标定
  2. 准备目标物体的高质量 3D 模型 .ply
  3. 在不同距离、角度、光照、遮挡条件下采集 RGB-D 帧
  4. 为每帧标注目标的 6D pose
  5. 由投影或人工校正生成物体 mask

这里最关键的不是"拍到图",而是:

  • 模型坐标系
  • 相机坐标系
  • pose 标注

三者必须严格一致。

如果这三者不一致,后续无论是评估还是可视化都会错。

9.3 推荐的原始采集产物

在最开始的原始数据层,不一定非要直接做成 LINEMOD 格式。更合理的是先保留一份"采集原始版":

text 复制代码
my_scene_raw/
├── rgb/
│   ├── 000001.png
│   ├── 000002.png
│   └── ...
├── depth/
│   ├── 000001.png
│   ├── 000002.png
│   └── ...
├── pose/
│   ├── 000001.json
│   ├── 000002.json
│   └── ...
├── mask/
│   ├── 000001.png
│   ├── 000002.png
│   └── ...
└── camera.json

原因是:

  • 原始采集格式更容易维护
  • 以后可以再导出成 BOP、LINEMOD、或别的格式
  • 不建议一开始就把原始数据直接耦合到某个训练框架的目录结构

9.4 如何把自采测试场景整理成 BOP 风格

如果你想复用当前仓库已有的转换脚本,最省事的做法不是手写 LINEMOD 目录,而是先把自采数据整理成 BOP 风格。

对单对象测试集,建议整理为:

text 复制代码
/workspace/bop/my_dataset_test/test/000001/
├── rgb/
│   ├── 000000.png
│   ├── 000001.png
│   └── ...
├── depth/
│   ├── 000000.png
│   ├── 000001.png
│   └── ...
├── mask/
│   ├── 000000_000000.png
│   ├── 000001_000000.png
│   └── ...
├── scene_gt.json
└── scene_camera.json

其中:

  • 场景目录 000001 可以理解为某个对象或某个测试场景
  • scene_gt.json 保存每帧每个实例的 cam_R_m2ccam_t_m2c
  • scene_camera.json 保存每帧相机参数,例如 cam_Kdepth_scale
  • mask 用 BOP 约定命名:frameid_annid.png

如果每帧只有一个目标实例,ann_idx 通常就是 000000

9.5 自采测试场景整理成 LINEMOD / PVN3D 格式时需要哪些文件

如果你不经过 BOP 中间层,直接整理成当前仓库能读的测试目录,至少需要:

text 复制代码
Linemod_preprocessed/data/{obj_id:02d}/
├── test.txt
├── gt.yml
├── rgb/
│   ├── 000001.png
│   ├── 000002.png
│   └── ...
├── depth/
│   ├── 000001.png
│   ├── 000002.png
│   └── ...
└── mask/
    ├── 000001.png
    ├── 000002.png
    └── ...

此外还需要:

text 复制代码
Linemod_preprocessed/models/obj_{obj_id:02d}.ply

9.6 test.txt 应如何制作

test.txt 的内容非常简单,每行一个帧号,不带扩展名,例如:

text 复制代码
000001
000002
000003

要求:

  • 必须和 rgb/depth/mask/ 文件名一致
  • 必须和 gt.yml 中的键一致

9.7 gt.yml 应如何制作

当前仓库的测试读取逻辑要求:

  • 每个帧号是一个键
  • 每个键对应一个列表
  • 列表里至少有一个字典

每个字典至少包含:

  • cam_R_m2c
  • cam_t_m2c
  • obj_id

典型结构:

yaml 复制代码
1:
  - cam_R_m2c: [r11, r12, r13, r21, r22, r23, r31, r32, r33]
    cam_t_m2c: [tx, ty, tz]
    obj_id: 1
2:
  - cam_R_m2c: [...]
    cam_t_m2c: [...]
    obj_id: 1

注意:

  • cam_R_m2c 是长度为 9 的行优先展开数组
  • cam_t_m2c 在当前 LINEMOD 流程里通常按毫米保存
  • 训练/测试代码内部会在需要时转成米

9.8 自采场景中的 pose 如何得到

这是最核心也最难的一步。常见做法有三种:

  1. 人工交互式标注
  2. 基于 AprilTag / ArUco / 外部定位系统建立参考系后求解
  3. 用 Blender / 仿真自动生成

无论用哪种方法,最终必须得到:

  • 物体模型坐标系到相机坐标系的变换 R, t

如果你是纯真实采集,推荐优先保证:

  • 相机内参准确
  • 模型尺度准确
  • cam_t_m2c.ply 单位一致

9.9 自采测试场景中的 mask 如何得到

常见做法:

  1. 根据真实 pose 和模型投影自动渲染出 mask
  2. 用标注工具手工勾出 mask
  3. 先用语义分割工具自动生成,再人工修正

建议:

  • 如果 pose 足够准,优先用模型投影自动生成
  • 如果有遮挡严重、透明反光、深度噪声大,再人工修正

9.10 深度图和相机内参需要注意什么

当前代码会把深度图结合相机内参变成点云,因此必须保证:

  1. 深度图数值真实可用
  2. 深度单位清晰
  3. 相机内参与采集设备一致

如果是 BOP 风格,通常通过:

  • scene_camera.json 中的 cam_K
  • depth_scale

来说明。

如果你直接做 LINEMOD 格式,则要保证:

  • 代码里使用的 K 与你的采集相机一致

当前默认 LINEMOD 内参写在:

如果你的实际相机不是 LINEMOD 原始相机,就不应继续直接使用默认内参。

9.11 建议的制作路线

对于自采测试场景,推荐采用两步走:

  1. 先保存为你自己的"原始采集格式"
  2. 再写一个小转换脚本导出成 BOP 或 Linemod_preprocessed

原因:

  • 后续你可能还要做重标注
  • 还可能用于别的算法或基准
  • 原始数据和训练框架格式解耦更稳

9.12 自采测试场景的最小检查清单

在你认为"测试集已经做完"之前,至少检查这些项:

  • rgbdepthmask 帧数一致
  • test.txt 中的帧号都存在
  • gt.yml 的每个键都对应真实文件
  • obj_id 与当前类别一致
  • cam_R_m2c 长度为 9
  • cam_t_m2c 长度为 3
  • .ply 模型存在且尺度正确
  • 相机内参与实际采集设备一致

10. 如果是真正的新类别,自定义数据集还需要什么

这是最容易低估的部分。

当前仓库的 LINEMOD 分支不是"任意 BOP 数据自动适配"的实现,而是对一组固定对象有很多硬编码假设。

10.1 必须修改类别映射

位置:

你至少要改这些内容:

  • lm_cls_lst
  • lm_obj_dict
  • lm_id2obj_dict

否则:

  • 训练入口 --cls xxx 找不到你的类别
  • 数据集无法把类名转成 obj_id
  • 评估逻辑无法正确反查类名

10.2 必须准备关键点文件

位置:

  • pvn3d/datasets/linemod/lm_obj_kps/{cls}/

至少要有:

text 复制代码
corners.txt
farthest.txt

如果保留当前多种评估/可视化逻辑,最好一并准备:

text 复制代码
farthest4.txt
farthest12.txt
farthest16.txt
farthest20.txt

原因是训练和评估会调用:

其中:

  • get_kps() 读取 farthest*.txt
  • get_ctr() 通过 corners.txt 求中心

如果这些文件不存在,训练和评估会直接失败。

10.3 必须准备模型尺寸信息

位置:

当前代码会读取:

text 复制代码
pvn3d/datasets/linemod/dataset_config/models_info.yml

如果你引入了新的对象 ID,需要把它的模型尺寸信息写进去。

10.4 必须准备模型文件

需要提供:

text 复制代码
Linemod_preprocessed/models/obj_{obj_id:02d}.ply

这个 .ply 需要满足当前代码的读取方式:

  • 能读出顶点坐标
  • 单位与现有流程一致

当前 LINEMOD 流程默认把 .ply 当作毫米单位,并在内部转成米。

10.5 需要考虑训练脚本只按"单类训练"设计

当前 LINEMOD 训练是:

bash 复制代码
python -m train.train_linemod_pvn3d --cls ape

即一次训练一个对象类别。

所以引入新类别后,你还要保证:

  • 新类别名能被 --cls 识别
  • 数据目录按该类别的 obj_id 放置
  • 关键点目录按该类别名建立

10.6 新类别接入时,转换脚本也需要同步改

如果你希望继续使用当前仓库的 BOP 转换脚本,那么下面这几个常量也需要更新:

你至少要同步:

  • SUPPORTED_OBJ_IDS
  • OBJ_ID_TO_NAME

否则会出现以下情况:

  • 脚本直接跳过你的对象
  • renders/{cls} 无法按你的类名生成
  • .ply 无法按新对象 ID 拷贝或命名

10.7 新类别接入时,训练与评估的隐含依赖也要检查

除了主训练脚本,还建议逐项检查这些依赖:

  1. demo.py 里是否使用了固定类别名
  2. pvn3d_eval_utils.py 是否依赖 lm_id2obj_dict
  3. 任何使用 obj_id -> cls_name 的地方是否都能映射到新类别
  4. lm_sym_cls_ids 是否需要更新

其中对称物体尤其要注意:

  • 如果你的新对象是对称物体
  • 评估时通常需要像 eggboxglue 一样特殊处理

否则 ADD 和 ADDS 的解释会不准确。

10.8 新类别接入时,建议新增哪些文档化产物

从工程维护角度,建议你为每个新类别额外保存:

  1. 模型来源说明
  2. 模型单位说明
  3. 坐标系定义说明
  4. 相机标定文件
  5. 关键点生成脚本或生成记录
  6. BOP 转换脚本的对象映射说明

这些内容不直接参与训练,但会显著影响后续复现实验和排查标注错误。

10.9 新类别接入的建议实施顺序

推荐顺序如下:

  1. 先给新对象分配稳定 obj_id
  2. 准备 .ply 并确认单位
  3. 生成 corners.txtfarthest*.txt
  4. 修改 common.py 的类别映射
  5. 修改 models_info.yml
  6. 修改 BOP 转换脚本中的对象白名单和名称映射
  7. 准备真实训练集 train.txt + gt.yml + rgb/depth/mask
  8. 可选补齐 renders/
  9. 先做 test / demo 验证,再开始训练

这样做的原因是:

  • 先验证几何与坐标系统是否正确
  • 再投入长时间训练

如果一开始就直接训练,很多错误会被掩盖成"loss 不收敛"。


11. 新类别接入时建议改动的代码与数据清单

这一节不要求你现在真实修改代码,但需要明确有哪些位置迟早要动。

11.1 必改代码文件

通常至少包括:

  1. common.py
  2. convert_bop_lm_train_to_pvn3d.py
  3. convert_bop_lm_to_pvn3d.py

按实际情况可能还包括:

  1. demo.py
  2. pvn3d_eval_utils.py
  3. 任何使用固定 LINEMOD 类名或对象 ID 的脚本

11.2 必补数据文件

通常至少包括:

  1. Linemod_preprocessed/models/obj_{obj_id:02d}.ply
  2. Linemod_preprocessed/data/{obj_id:02d}/train.txt
  3. Linemod_preprocessed/data/{obj_id:02d}/test.txt
  4. Linemod_preprocessed/data/{obj_id:02d}/gt.yml
  5. rgb/*.png
  6. depth/*.png
  7. mask/*.png
  8. lm_obj_kps/{cls}/corners.txt
  9. lm_obj_kps/{cls}/farthest*.txt
  10. dataset_config/models_info.yml

11.3 最容易遗漏的点

工程上最常见的遗漏项有:

  1. 新类别名已经加到 lm_obj_dict,但 lm_id2obj_dict 没同步
  2. .ply 已经放进 models/,但 lm_obj_kps/{cls} 没创建
  3. gt.ymlobj_id 写对了,但 train.txt / test.txt 帧号对不上
  4. 相机内参沿用了默认 LINEMOD 的 K,但实际采集设备不同
  5. cam_t_m2c.ply 的单位不一致
  6. 对称物体没有更新对称类别列表

12. 自定义数据集最小必需清单

如果你的目标是"让一个新对象在当前 PVN3D LINEMOD 流程中能训练起来",至少需要以下内容。

10.1 数据文件

text 复制代码
Linemod_preprocessed/data/{obj_id:02d}/
├── train.txt
├── gt.yml
├── rgb/*.png
├── depth/*.png
└── mask/*.png

10.2 模型文件

text 复制代码
Linemod_preprocessed/models/obj_{obj_id:02d}.ply

10.3 关键点文件

text 复制代码
pvn3d/datasets/linemod/lm_obj_kps/{cls}/
├── corners.txt
├── farthest.txt
├── farthest4.txt
├── farthest12.txt
├── farthest16.txt
└── farthest20.txt

10.4 配置和映射

text 复制代码
pvn3d/common.py
pvn3d/datasets/linemod/dataset_config/models_info.yml

10.5 可选增强数据

text 复制代码
Linemod_preprocessed/renders/{cls}/*.pkl
Linemod_preprocessed/renders/{cls}/file_list.txt
Linemod_preprocessed/fuse/{cls}/*.pkl
Linemod_preprocessed/fuse/{cls}/file_list.txt

其中真正的"硬依赖"是:

  • 训练样本目录
  • 模型 .ply
  • 关键点文件
  • 类别映射

13. 推荐实施路线

路线 A:先复用现有 LINEMOD 对象

如果你的目标是先把训练链路打通,这是最推荐的路线。

步骤:

  1. 准备 BOP 格式的 lm_train / lm_train_pbr / lm_models
  2. 用当前仓库脚本转换到 Linemod_preprocessed
  3. 校验训练目录
  4. 启动单类训练

优点:

  • 改动最少
  • 风险最低
  • 文档和代码都已有参考

路线 B:再接入真正的新类别

如果你确认要训练新物体,建议在路线 A 跑通后再做。

步骤:

  1. 为新对象分配 obj_id
  2. 修改 common.py 中类别映射
  3. 补齐 models_info.yml
  4. 准备 .ply
  5. 生成 corners.txtfarthest*.txt
  6. 准备训练样本目录
  7. 视需要修改转换脚本中的 SUPPORTED_OBJ_IDSOBJ_ID_TO_NAME

优点:

  • 可扩展到任意自定义对象

代价:

  • 代码改动明显更多
  • 更容易漏掉关键点文件或映射配置

14. 当前仓库里需要特别注意的限制

12.1 训练转换脚本当前是 LINEMOD 定制的

convert_bop_lm_train_to_pvn3d.py 中,当前写死了:

  • SUPPORTED_OBJ_IDS
  • OBJ_ID_TO_NAME

所以如果你的 BOP 数据里有新的对象 ID,这个脚本默认不会自动支持。

12.2 当前训练数据集假设每次只训练一个对象

这和 BOP 的多对象场景组织方式不同。

也就是说,你虽然可以从多对象 BOP 数据中抽取某个对象的数据来训练,但当前 LINEMOD 分支不是一个原生多对象联合训练实现。

12.3 当前关键点文件需要你自己提供

仓库不会自动从 .ply 生成:

  • corners.txt
  • farthest*.txt

如果你接入新类别,这些文件必须自行生成。


15. 实际落地时你至少需要准备什么

如果你现在要基于 /workspace/bop 做一套可训练数据,建议按下面清单准备。

最小可训练版本

  1. /workspace/bop/lm_models/models/obj_XXXXXX.ply
  2. /workspace/bop/lm_train/train/{scene_id}/rgb
  3. /workspace/bop/lm_train/train/{scene_id}/depth
  4. /workspace/bop/lm_train/train/{scene_id}/mask
  5. /workspace/bop/lm_train/train/{scene_id}/scene_gt.json
  6. 将其转换到 Linemod_preprocessed/data/{obj_id}
  7. 准备 lm_obj_kps/{cls}/corners.txt
  8. 准备 lm_obj_kps/{cls}/farthest*.txt
  9. common.pymodels_info.yml 中登记类别

更完整、更稳的版本

在最小版本基础上,再补:

  1. /workspace/bop/lm_train_pbr/train_pbr/...
  2. scene_camera.json
  3. mask_visib
  4. 转换得到 renders/{cls}/*.pkl

这样训练时就能混合:

  • 真实图像
  • PBR 合成图像

通常比只用真实图像更稳。


16. 总结

基于 BOP 格式构建 PVN3D 自定义训练数据集,不只是"把 RGB、depth、mask 拷过来"。

对当前仓库来说,真正需要同时满足的是三层要求:

  1. 逐帧训练样本完整
  2. 类别级别的模型与关键点完整
  3. 代码中的类别映射与对象配置完整

如果你只是沿用现有 LINEMOD 类别,当前仓库已经提供了相对完整的:

  • BOP 训练数据转换脚本
  • 训练目录结构
  • 训练入口

如果你要训练真正的新类别,则至少还要补齐:

  • 新对象 ID 映射
  • .ply
  • corners.txt
  • farthest*.txt
  • models_info.yml
  • 转换脚本中的对象白名单

所以最稳妥的实施顺序是:

  1. 先用现有 LINEMOD 类别跑通 BOP 到训练的整条链路
  2. 再把这套流程推广到新类别

这样能显著减少"数据格式已经对了,但训练仍然起不来"的排查成本。

相关推荐
sin°θ_陈3 小时前
前馈式3D Gaussian Splatting 研究地图(路线三):大重建模型如何进入 3DGS——GRM、GS-LRM 与 Long-LRM 的方法转向
3d·aigc·gpu算力·三维重建·空间计算·3dgs·空间智能
sin°θ_陈3 小时前
前馈式3D Gaussian Splatting 研究地图(路线二):几何优先的前馈式 3DGS——前馈式 3DGS 如何重新拥抱多视图几何
深度学习·3d·webgl·三维重建·空间计算·3dgs·空间智能
阿酷tony15 小时前
Nano Banna 提示词:创意超逼真的3D商业风格产品图
人工智能·3d·gemini·图片生成
智算菩萨16 小时前
【OpenGL】10 完整游戏开发实战:基于OpenGL的2D/3D游戏框架、物理引擎集成与AI辅助编程指南
人工智能·python·游戏·3d·矩阵·pygame·opengl
Jackson_GJH1 天前
3D 建模入坑指南:NURBS 与 Polygon 有什么区别?CAD 与 DCC 怎么选?
3d
CV实验室1 天前
Meta引爆3D革命!SAM 3D 发布:单张图秒建3D模型,AR/VR、游戏圈炸锅!
计算机视觉·3d·meta·ar·vr
星河耀银海1 天前
3D效果:HTML5 WebGL结合AI实现智能3D场景渲染
前端·人工智能·深度学习·3d·html5·webgl
全栈若城1 天前
HarmonyOS 6 实战:Component3D 与 SURFACE 渲染模式深度解析
3d·架构·harmonyos6
KaGme1 天前
生成3DGS场景在unity中的呈现
3d·unity·游戏引擎