Closed rockywind closed 1 year ago
Here is the thing you can do! :)
vis.to_file(vis.mesh(mesh.v, mesh.f), "a.ply")
Thank you very much!
Hi, Can you sharing the waymo-pcd.ply?
Oops sorry for making a mistake in the common script! I've pushed a fix. Feel free to pull and check again. The file should be automatically downloaded.
Hi, I want to run the code on my own data, my data style is the same as Kitti. Can you give me some tutorial.
We haven't tested on KITTI dataset yet. But it should be easy! Some pseudo-code look like:
xyz_list = []
sensor_list = []
for frame_idx in range(1000):
xyz = load_kitti_lidar(frame_idx)
pose = load_kitti_pose(frame_idx)
xyz_list.append(pose.transform(xyz))
sensor_list.append(pose.transform([[0,0,0] for _ in range(xyz.shape[0])]))
xyz = np.concatenate(xyz_list)
sensor = np.concatenate(sensor_list)
Hope this helps!
Thank you very much!
How to add the color to the mesh on waymo dataset?
@heiwang1997 Hi, I confuse with the setting of sensor on kitti dataset. I think the xyz is in world coordinate and the sensor is velo_to_world's translation. The value of sensor is the same for all point clouds.
The below is the reconstruction of kitti dataset.
Hi thanks for the questions.
Open3D
to visualize our mesh, and if you press Ctrl+9
on your keyboard, you should be able to see the normal map we've drawn on the paper.base_pose
is the same for all input frames? That means your car is static I guess. Could you maybe visualize the positions of the sensors as well as the points just for debugging purposes?Best.
@heiwang1997 您好,感谢您的解答。我用中文提问会更清晰。
您好,我对您的第二点不是太理解,为何“senseor(base_pose)值取每个输入帧的velo_to_world”,但“对所有的输入帧base_pose的值是一样的”呢?可以理解为所有的输入帧的pose都是一样的吗?
另外,KITTI数据集噪声比较大,可以尝试提升一下Normal estimation knn的值~
您好,之前描述有错误,已经修改了。 您觉得这两种做法有什么问题吗?
好的,谢谢! 我觉得第二种做法应该是没问题的,如果觉得噪声比较大,可以尝试两种方案:
get_estimate_normal_preprocess_fn
的第一个参数;十分感谢,我还有两个问题请教哈
不客气的~有关你的问题:
velo_to_world
矩阵具体是pose还是pose的逆,只要能将激光雷达局部坐标系的点云变换到世界坐标系下即可,变换后尽可能Z轴朝上,因为我们的默认模型训练数据都是Z轴朝上的;十分感谢,
[inverse(velo_to_world[0]) @ velo_to_world[i] for i in range(velo_to_world)]
I've got some quite good results on KITTI and Newer College datasets using NKSR and the reconstruction is also super fast (in about 10 seconds)
@YuePanEdward Hi, Can you share the code on KITTI dataset?
You can try to add this to common.py.
And then replace xyz_np, sensor_np = load_waymo_example()
with
xyz_np, sensor_np = load_kitti_like_data(pc_folder, pose_file, calib_file, every_n_frame=1, begin_frame=0, end_frame=100)
and provide the correct path to your dataset.
For the visualization, you may use open3d:
import open3d as o3d
mesh_v, mesh_f = mesh.v.detach().cpu().numpy(), mesh.f.detach().cpu().numpy()
mesh = o3d.geometry.TriangleMesh(o3d.utility.Vector3dVector(mesh_v), o3d.utility.Vector3iVector(mesh_f))
mesh.compute_vertex_normals()
o3d.visualization.draw_geometries([mesh])
o3d.io.write_triangle_mesh(your_mesh_path, mesh)
I've got some quite good results on KITTI and Newer College datasets using NKSR and the reconstruction is also super fast (in about 10 seconds) I wonder if the nksr lib will also be made open-source? The marching cubes algorithm implemented there seems to be super fast.
How can you reconstruct large scale like kitti without CUDA out of Memory?
Hey wow @YuePanEdward these look amazing!
Any chance you want to send a PR with an example script for these datasets? This would be greatly appreciated by the community!
Also if you want to win a free GPU, feel free to upload anything cool you do here for the contest: nvda.ws/3NkPYs5
You can try to add this to common.py.
And then replace
xyz_np, sensor_np = load_waymo_example()
withxyz_np, sensor_np = load_kitti_like_data(pc_folder, pose_file, calib_file, every_n_frame=1, begin_frame=0, end_frame=100)
and provide the correct path to your dataset.For the visualization, you may use open3d:
import open3d as o3d mesh_v, mesh_f = mesh.v.detach().cpu().numpy(), mesh.f.detach().cpu().numpy() mesh = o3d.geometry.TriangleMesh(o3d.utility.Vector3dVector(mesh_v), o3d.utility.Vector3iVector(mesh_f)) mesh.compute_vertex_normals() o3d.visualization.draw_geometries([mesh]) o3d.io.write_triangle_mesh(your_mesh_path, mesh)
您好请问一下,能解释一下这段代码的含义吗
poses.append( np.matmul(Tr_inv, np.matmul(pose, Tr)) ) # lidar pose in world frame
You can try to add this to common.py. And then replace
xyz_np, sensor_np = load_waymo_example()
withxyz_np, sensor_np = load_kitti_like_data(pc_folder, pose_file, calib_file, every_n_frame=1, begin_frame=0, end_frame=100)
and provide the correct path to your dataset. For the visualization, you may use open3d:import open3d as o3d mesh_v, mesh_f = mesh.v.detach().cpu().numpy(), mesh.f.detach().cpu().numpy() mesh = o3d.geometry.TriangleMesh(o3d.utility.Vector3dVector(mesh_v), o3d.utility.Vector3iVector(mesh_f)) mesh.compute_vertex_normals() o3d.visualization.draw_geometries([mesh]) o3d.io.write_triangle_mesh(your_mesh_path, mesh)
您好请问一下,能解释一下这段代码的含义吗
poses.append( np.matmul(Tr_inv, np.matmul(pose, Tr)) ) # lidar pose in world frame
You may check the explanation here: https://github.com/PRBonn/kiss-icp/issues/156#issuecomment-1551695713, which should be similar to the issue here.
@YuePanEdward The results look amazing! For the marching cubes implementation, please refer to the code here. Thank you! 🍉
Hi, @heiwang1997 How to use the marching cubes implemention? Have a example code? The below is my own data result. How can I improve it?
Yes, you can check out here for example code.
Have you tried out the tricks that we talked about in the previous messages? What does the input point cloud look like?
Hi, This is my setting.
The below is my new result. My dataset is paking data. Can I finetune the model on my own data? The performance of reconstruction can improve when I finetune?
Hey I'm not sure if everything is correctly set up here, and from your result it seems that parts of the ground are flipped. This could either be because your sensor positions are not accurate, or your point cloud contains too much noise, so our model fails to handle such cases. To fine-tune the model, you will need ground-truth geometry and we use the CARLA dataset for that -- it's available in the README. Feel free to check that out. Have you tried out the tricks that we talked about in the previous messages? What does the input point cloud look like?
Hi rockywind
Considering that this is parking data, the point cloud on the ground is probably very sparse because the ego-car doesn't move at all or only slightly. In such cases, you are left with individual scan lines on the ground, for which it is very hard to estimate the normals correctly. Could you maybe visualize the input point cloud?
Hi,all This is the visualization of the input point cloud.
Hi, @heiwang1997 当我调大sensor的Z+2值时候,重建的mesh会往上补全。
Interesting... would you mind send me your file and let me investigate into it a bit? I think I will just need the XYZ + sensor array that you've generated
@heiwang1997 想请问一下sensor array里面给的是什么信息啊
是每个点对应的传感器位置,即采集这个点的时候,传感器的xyz世界坐标~
@heiwang1997 再请教一下,我跑的时候报out of memory了,我有两张gpu,能不能用两张gpu来跑这个重建?另外参考readme里的内容,把 field.to_("cpu") reconstructor.network.to("cpu") 这两句话取消注释,会报错 RuntimeError: (*grid) and query are not on the same device!
如果要用两个GPU的话,需要把input事先切成两块,然后分别输入每个GPU对应的Reconstructor 关于第二个错误,能麻烦发下完整的代码吗?我测试一下
如果要用两个GPU的话,需要把input事先切成两块,然后分别输入每个GPU对应的Reconstructor 关于第二个错误,能麻烦发下完整的代码吗?我测试一下
就是您example里的代码
device = torch.device("cuda:0")
reconstructor = nksr.Reconstructor(device)
reconstructor.chunk_tmp_device = torch.device("cpu")
input_xyz = torch.from_numpy(xyz_np).float().to(device)
input_sensor = torch.from_numpy(sensor_np).float().to(device)
field = reconstructor.reconstruct(
input_xyz, sensor=input_sensor, detail_level=None,
# Minor configs for better efficiency (not necessary)
approx_kernel_grad=True, solver_tol=1e-4, fused_mode=True,
# Chunked reconstruction (if OOM)
chunk_size=50,
preprocess_fn=nksr.get_estimate_normal_preprocess_fn(64, 85.0)
)
# (Optional) Convert to CPU for mesh extraction
field.to_("cpu")
reconstructor.network.to("cpu")
mesh = field.extract_dual_mesh(mise_iter=1)
mesh = vis.mesh(mesh.v, mesh.f)
您好,我运行您的代码的时候提示找不到xyz_np
和sensor_np
变量,能烦请您发一下完整的代码吗?谢谢!
另外,如果直接运行 python examples/recons_waymo.py
,我这里是不会报错的
您好,我运行您的代码的时候提示找不到
xyz_np
和sensor_np
变量,能烦请您发一下完整的代码吗?谢谢!另外,如果直接运行
python examples/recons_waymo.py
,我这里是不会报错的
我这个代码上面读数据的load函数是我自己写的,读的我自己的数据,所以没放上来
我把examples/reconswaymo.py中的 field.to("cpu") reconstructor.network.to("cpu") 取消注释的话,还是会报错
可以print一下nksr的版本吗?print(nksr.__version__)
可以print一下nksr的版本吗?
print(nksr.__version__)
1.0.0+pt20cu118
谢谢,请您安装最新版本的nksr:
pip install -U nksr -f https://nksr.huangjh.tech/whl/torch-2.0.0+cu118.html
您好,请问可以将点云的深度信息加进去吗
You can try to add this to common.py.
And then replace
xyz_np, sensor_np = load_waymo_example()
withxyz_np, sensor_np = load_kitti_like_data(pc_folder, pose_file, calib_file, every_n_frame=1, begin_frame=0, end_frame=100)
and provide the correct path to your dataset.For the visualization, you may use open3d:
import open3d as o3d mesh_v, mesh_f = mesh.v.detach().cpu().numpy(), mesh.f.detach().cpu().numpy() mesh = o3d.geometry.TriangleMesh(o3d.utility.Vector3dVector(mesh_v), o3d.utility.Vector3iVector(mesh_f)) mesh.compute_vertex_normals() o3d.visualization.draw_geometries([mesh]) o3d.io.write_triangle_mesh(your_mesh_path, mesh)
@YuePanEdward @rockywind I tried this visualization script and got a gray mesh. Could you please tell me how to add the original intensity colors to the mesh or any other similar feature? Thanks
请问这个可以使用colmap中SFM的结果作为输入吗?
SFM points from COLMAP don't have normal information and could be too sparse. Alternatively you could take the oriented point cloud from a typical MVG pipeline (e.g. from https://github.com/openMVG/openMVG) and replace the Poisson reconstruction with NKSR :)
Alternatively you could take the oriented point cloud from a typical MVG pipeline
OK,Thank you for your reply, I'll try it.
I've got some quite good results on KITTI and Newer College datasets using NKSR and the reconstruction is also super fast (in about 10 seconds)
Hi @YuePanEdward, sorry for digging this up. I'm trying to run NKSR on KITTI seq 0 and for some reason mine does not look as good as yours
I'm just asking if you use the defaults parameter as followed
field = reconstructor.reconstruct(
input_xyz, sensor=input_sensor, detail_level=None,
# Minor configs for better efficiency (not necessary)
approx_kernel_grad=True, solver_tol=1e-4, fused_mode=True,
# Chunked reconstruction (if OOM)
chunk_size=51.2,
preprocess_fn=nksr.get_estimate_normal_preprocess_fn(64, 85.0)
)
Thanks in advance!
Hi, thank you for sharing the code. I run the code on the server so I haven't the monitor to show the result.