先说结论,ObjectDatasetTools不好用,开发了一个有效的方法,最后效果连接如下:
————–分割线—————
在经历了好几天的煎熬后,发现配置labelfusion太难了,换
ObjectDatasetTools试试吧。
在复现这个代码的时候,深度参考了这位大哥的笔记,以及我自己对官方readme的翻译。
配置相机的部分不再赘述,本文只关注位姿、label以及mask生成的部分。
1.环境配置
(1)使用conda新建一个Python2.7的虚拟环境。
conda create -n ObjectDatasetTools python=2.7
之后按照官方教程走就行。
(2)升级pre-install包
sudo apt-get update
sudo apt-get upgrade
(3)安装依赖
sudo apt-get install build-essential cmake git pkg-config libssl-dev libgl1-mesa-glx
(4)在虚拟环境中安装Python依赖包
sudo pip install numpy Cython==0.19 pypng scipy scikit-learn open3d==0.9.0 scikit-image tqdm pykdtree opencv-python==3.3.0.10 opencv-contrib-python==3.3.0.10 trimesh==2.38.24
数据处理
(1)准备
在arucomarkers文件夹中使用适当大小的aruco标记(ID 1-13)对pdf进行彩色打印。在感兴趣的对象周围贴上标记,如图所示,确保没有带有重复IDS的标记。
在这里插入图片描述
(2)用深度相机记录数据
对旧模型(这里的旧模型我不确定是不是指的librealsense SDK 1.0的玩家,自己尝试吧。)使用record.py,对librealsense SDK 2.0使用recordf2.py:
python record.py LINEMOD/OBJECTNAME
如:通过如下代码实现记录一个sugar box。
python record.py LINEMOD/sugar
默认情况下,脚本在倒计时5后录制40秒,录制时间长度可以在record.py中的第20行进行修改。可以通过按“q”更改录制间隔或退出录制。然后稳定移动相机以获得物体不同视图,同时随时保持2-3个标记在相机的视野内。
注意项目假设所有序列都保存在名为“LINEMOD”的文件夹下,使用其他文件夹名称会报错。
如果使用record.py创建序列,彩色图像、深度图以及相机参数会自动保存在序列目录下。
需要注意的是如果已有彩色图像或者深度图像,则应将彩色图像(.jpg)放在名为“JPEGImages”的文件夹中,并将对其的深度图像放在“depth”文件夹中。注意:该算法嘉定深度图与彩图对齐。将彩图按顺序从0.jpg、1.jpg、…、600.jpg和相应的深度图命名为:0.png,…,600.png,同时应在序列目录下创建一个名为“intrinsics.json”的文件,并按照如下形式手动输入相机参数,如:
{"fx": 614.4744262695312, "fy": 614.4745483398438, "height": 480, "width": 640, "ppy": 233.29214477539062, "ppx": 308.8282470703125, "ID": "620201000292"}
如果不知道相机内参,可以输入一个粗略的估计。所需要的参数为fx,fy,cx,xy。其中,通常,fx=fy等于图像 的宽度,cx=cy是图像的中心。例如:对于640*480分辨率的图像,fx,fy=640,cx=320、cy=240
(3)获取帧变换
以指定的间隔(可以在 config/registrationParameters 中更改间隔)对第一帧计算帧的变换,将变换(4*4 同构变换)保存为 numpy 数组 (.npy)。
python compute_gt_poses.py LINEMOD/duck2
(4)目标物体三维重构
python register_scene.py LINEMOD/duck2
原始的registeredScene.ply 将保存在指定目录下(例如,LINEMOD/sugar)。 registerScene.ply 是场景的注册点云,包括桌面、标记和扫描过程中暴露的任何其他对象,并具有一定程度的噪声消除。 生成的网格看起来如下图,需要在步骤 5 中手动处理:
或者,可以尝试通过尝试 register_segmented 而不是 register_scene 来跳过所有手动工作。
python register_segmented.py LINEMOD/duck2
默认情况下,register_segmented尝试删除所有不需要的背景并执行表面重建,将注册的点云转换为三角形网格。如果MESHING设置为false,脚本将仅尝试移除背景并使用平坦表面自动完成看不见的底部(如果FILLBOTTOM设置为 true),您将需要执行步骤5。
但是,register_segmented可能会失败,因为它使用一些特殊的方法来分割背景,因此您可能需要调整一些参数以使其与您的对象一起使用。要调整的最重要的旋钮是“MAX_RADIUS”,它会切断任何深度读数,其到观察到的aruco标记中心的欧几里得距离大于指定值。此值当前设置为0.2m,如果您有更大的对象,您可能需要增加此值以不切断对象的一部分。运行register_segmented的结果如下所示:
(5)手动处理点云数据
如果对运行register_segmented的结果满意,可以跳过步骤5.
注册的点云需要处理为:
- 删除不感兴趣的背景;
- 执行表面重建并完成缺失的一侧,反之亦然;
- 处理重建的网络(可能需要切掉部分并重新完成缺失的一侧);
- 确保处理后的网格没有任何孤立噪音。
最终生成三角形网格,而不是算法生成的register点云。作者推荐使用meshlab进行处理。
(6)生成图像掩码和标签文件
当为自定义对象完成步骤1-4后,运行如下代码:
python create_label_files.py all
或者(推荐)
python create_label_files.py LINEMOD/duck2
此步骤创建一个名为foldername.ply(例如:sugar.ply)的新网格,其AABB以原点为圆心,并且与OBB的尺寸相同。同时还生成图像掩码(保存在mask文件下),关于新网格的4*4同质变换(保存在transforms里),标签文件保存在labels文件。
通过运行以下命令直观地检查创建的 3D 边界框和掩码的正确性:
python inspectMasks.py LINEMOD/duck2
(7)最后生成的文件如下图所示
文章出处登录后可见!