Skip to content

Commit edb5945

Browse files
0.0.1
1 parent 77a15e8 commit edb5945

33 files changed

+2433
-62
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
# Python Wrapper for SOGMM
22

33
Please see the meta-package https://github.com/gira3d/gira3d-reconstruction for detailed documentation.
4+
5+
## Changelog
6+
7+
### New in 0.0.1
8+
- Supporting scripts for incremental mapping with SOGMMs
9+
- Supporting scripts for the paper https://arxiv.org/pdf/2309.10900.pdf

paper_figures/gl-inference.py

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import os
2+
import json
3+
import argparse
4+
import numpy as np
5+
import open3d as o3d
6+
7+
from sogmm_py.vis_open3d import VisOpen3D
8+
from sogmm_py.utils import np_to_o3d, o3d_to_np
9+
10+
def vis_nvblox_mesh(path, view_string, target_file):
11+
vis = VisOpen3D(visible=False)
12+
render_ops = vis.get_render_option()
13+
render_ops.point_size = 1
14+
pcld = o3d.io.read_triangle_mesh(path, enable_post_processing=True)
15+
vis.add_geometries([pcld])
16+
vis.set_view_status(view_string)
17+
vis.capture_screen_image(target_file)
18+
19+
def vis_pcd(path, view_string, target_file):
20+
vis = VisOpen3D(visible=True)
21+
render_ops = vis.get_render_option()
22+
render_ops.point_size = 1
23+
24+
pcld = o3d.io.read_point_cloud(path)
25+
pcld_np = o3d_to_np(pcld)
26+
pcld_np_cropped = pcld_np[pcld_np[:, 1] < 2.6, :]
27+
pcld_cropped = np_to_o3d(pcld_np_cropped)
28+
29+
vis.add_geometries([pcld_cropped])
30+
vis.set_view_status(view_string)
31+
vis.run()
32+
33+
def vis_gmm_pcd(path, view_string, target_file):
34+
vis = VisOpen3D(visible=False)
35+
render_ops = vis.get_render_option()
36+
render_ops.point_size = 1
37+
38+
pcld = o3d.io.read_point_cloud(path)
39+
pcld_np = o3d_to_np(pcld)
40+
pcld_np_cropped = pcld_np[pcld_np[:, 1] < 2.6, :]
41+
pcld_cropped = np_to_o3d(pcld_np_cropped)
42+
43+
vis.add_geometries([pcld_cropped])
44+
vis.set_view_status(view_string)
45+
vis.capture_screen_image(target_file)
46+
47+
def vis_octomap_pcd(path, view_string, target_file, v):
48+
vis = VisOpen3D(visible=False)
49+
render_ops = vis.get_render_option()
50+
render_ops.point_size = 1
51+
52+
pcld = o3d.io.read_point_cloud(path)
53+
pcld_np = o3d_to_np(pcld)
54+
pcld_np_cropped = pcld_np[pcld_np[:, 1] < 2.6, :]
55+
pcld_cropped = np_to_o3d(pcld_np_cropped)
56+
57+
voxel_grid = o3d.geometry.VoxelGrid.create_from_point_cloud(pcld_cropped, voxel_size=v)
58+
59+
vis.add_geometries([voxel_grid])
60+
vis.set_view_status(view_string)
61+
vis.capture_screen_image(target_file)
62+
63+
64+
if __name__ == "__main__":
65+
parser = argparse.ArgumentParser(description="isogmm metrics")
66+
parser.add_argument('--gt_path', type=str)
67+
parser.add_argument('--results_path', type=str)
68+
parser.add_argument('--dataset_name', type=str, default="livingroom1")
69+
70+
args = parser.parse_args()
71+
72+
livingroom_view = {
73+
"class_name" : "ViewTrajectory",
74+
"interval" : 29,
75+
"is_loop" : False,
76+
"trajectory" :
77+
[
78+
{
79+
"boundingbox_max" : [ 2.583730936050415, 2.5999975204467773, 4.2289800643920898 ],
80+
"boundingbox_min" : [ -2.6225473880767822, 0.045030891895294189, -1.9846775531768799 ],
81+
"field_of_view" : 60.0,
82+
"front" : [ 0.42010601103967038, 0.8521088750580561, 0.3121240210807727 ],
83+
"lookat" : [ -0.019408226013183594, 1.3225142061710358, 1.122151255607605 ],
84+
"up" : [ -0.68270185199437294, 0.52336334468660561, -0.50991076741122343 ],
85+
"zoom" : 2.0
86+
}
87+
],
88+
"version_major" : 1,
89+
"version_minor" : 0
90+
}
91+
92+
lounge_view = {
93+
"class_name" : "ViewTrajectory",
94+
"interval" : 29,
95+
"is_loop" : False,
96+
"trajectory" :
97+
[
98+
{
99+
"boundingbox_max" : [ 2.583730936050415, 2.5999975204467773, 4.2289800643920898 ],
100+
"boundingbox_min" : [ -2.6225473880767822, 0.045030891895294189, -1.9846775531768799 ],
101+
"field_of_view" : 60.0,
102+
"front" : [ -0.085948154700654367, -0.92242139092228226, -0.37649925932537326 ],
103+
"lookat" : [ 2.0916572950719075, 1.2422129553584436, 1.1062828807923488 ],
104+
"up" : [ -0.015645493914887437, -0.37660141707073896, 0.92624326781924338 ],
105+
"zoom" : 0.51799999999999868
106+
}
107+
],
108+
"version_major" : 1,
109+
"version_minor" : 0
110+
}
111+
112+
if args.dataset_name == "livingroom1":
113+
view_string = json.dumps(livingroom_view)
114+
if args.dataset_name == "lounge":
115+
view_string = json.dumps(lounge_view)
116+
117+
vis_gmm_pcd(os.path.join(args.results_path, f'ground_truth/{args.dataset_name}_gt_voxelized.pcd'), view_string,
118+
os.path.join(args.results_path, f'ground_truth/{args.dataset_name}_gt_voxelized.png'))
119+
120+
for s in ["0_02", "0_03", "0_04", "0_05"]:
121+
vis_gmm_pcd(os.path.join(args.results_path, f'isogmm_results/{args.dataset_name}_bw_{s}_pr.pcd'), view_string,
122+
os.path.join(args.results_path, f'isogmm_results/{args.dataset_name}_bw_{s}_pr.png'))
123+
124+
for m in ["800", "400", "200", "100"]:
125+
vis_gmm_pcd(os.path.join(args.results_path, f'fcgmm_results/{args.dataset_name}_{m}_pr_voxelized.pcd'), view_string,
126+
os.path.join(args.results_path, f'fcgmm_results/{args.dataset_name}_{m}_pr_voxelized.png'))
127+
128+
for r in ["0_02", "0_04", "0_06", "0_08"]:
129+
vis_octomap_pcd(os.path.join(args.results_path, f'octomap_results/{args.dataset_name}_{r}_octomap.pcd'), view_string,
130+
os.path.join(args.results_path, f'octomap_results/{args.dataset_name}_{r}_octomap.png'), float(r.replace('_', '.')))
131+
132+
133+
for r in ["0.02", "0.04", "0.06", "0.08"]:
134+
vis_nvblox_mesh(os.path.join(args.results_path, f'nvblox_results_2/{args.dataset_name}_{r}_nvblox.ply'), view_string,
135+
os.path.join(args.results_path, f'nvblox_results_2/{args.dataset_name}_{r}_nvblox.png'))

paper_figures/spatial-hash-ablation.py

Whitespace-only changes.

paper_figures/video.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,26 @@
88

99
def custom_draw_geometry_with_key_callback(pcd):
1010

11+
def rotate_view(vis):
12+
ctr = vis.get_view_control()
13+
ctr.rotate(0.75, 0.0)
14+
return False
15+
1116
def change_background_to_black(vis):
1217
opt = vis.get_render_option()
18+
opt.point_size = 2
1319
opt.background_color = np.asarray([0, 0, 0])
1420
return False
1521

1622
key_to_callback = {}
1723
key_to_callback[ord("K")] = change_background_to_black
24+
key_to_callback[ord("R")] = rotate_view
1825
o3d.visualization.draw_geometries_with_key_callbacks([pcd], key_to_callback)
1926

20-
results_path = '/Volumes/GoogleDrive/My Drive/phd/adaptive_perception/results'
21-
22-
with open(os.path.join(results_path, 'cave/cave.pkl'), 'rb') as f:
23-
loaded_model = pickle.load(f)
24-
25-
pts = loaded_model.sample(3*loaded_model.support_size_, 1.8)
26-
np.savetxt('cave_pts.txt', pts)
27-
28-
pcd = np_to_o3d(pts)
29-
30-
# pcd = o3d.geometry.PointCloud()
31-
# pcd.points = o3d.utility.Vector3dVector(pts[:, :3])
32-
# colors = plt.get_cmap("inferno")(pts[:, 3])
33-
# pcd.colors = o3d.utility.Vector3dVector(colors[:, :3])
27+
pcld = o3d.io.read_point_cloud('/media/fractal/T7/rss2023-resub/results/isogmm_results/livingroom1_bw_0_02_pr.pcd')
28+
pcld_np = o3d_to_np(pcld)
29+
pcld_np_cropped = pcld_np[pcld_np[:, 1] < 2.6, :]
30+
pcld_np_cropped_2 = pcld_np_cropped[pcld_np_cropped[:, 2] < 3.1, :]
31+
pcld_cropped_2 = np_to_o3d(pcld_np_cropped_2)
3432

35-
custom_draw_geometry_with_key_callback(pcd)
33+
custom_draw_geometry_with_key_callback(pcld_cropped_2)

paper_figures/zr-likelihood.py

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
import argparse
2+
import os
3+
import numpy as np
4+
import glob
5+
import time
6+
from cprint import cprint
7+
8+
from sogmm_py.vis_open3d import VisOpen3D
9+
from sogmm_py.utils import read_log_trajectory, np_to_o3d, o3d_to_np, ImageUtils
10+
from sogmm_py.gmm_spatial_hash import GMMSpatialHash
11+
12+
from sogmm_gpu import SOGMMInference as GPUInference
13+
from sogmm_gpu import SOGMMLearner as GPUFit
14+
from sogmm_gpu import SOGMMf4Device as GPUContainerf4
15+
from sogmm_cpu import SOGMMf4Host as CPUContainerf4
16+
17+
18+
def extract_ms_data(X):
19+
d = np.array([np.linalg.norm(x) for x in X[:, 0:3]])[:, np.newaxis]
20+
g = X[:, 3][:, np.newaxis]
21+
return np.concatenate((d, g), axis=1)
22+
23+
24+
parser = argparse.ArgumentParser(description="Incremental-SOGMM")
25+
parser.add_argument('--datasetroot', type=str)
26+
27+
args = parser.parse_args()
28+
29+
dfolder = args.datasetroot
30+
31+
dname = 'lounge'
32+
deci = 2.0
33+
bandwidth = 0.015
34+
35+
learner = GPUFit(bandwidth)
36+
inference = GPUInference()
37+
gsh = GMMSpatialHash(resolution=0.2)
38+
39+
frame_1 = 675
40+
color_1 = [1.0, 0.0, 0.0]
41+
frame_2 = 700
42+
color_2 = [0.0, 0.0, 1.0]
43+
44+
# paths to all rgb and depth images in the dataset
45+
rgb_paths = sorted(
46+
glob.glob(os.path.join(dfolder, dname + '-color/*.png')))
47+
depth_paths = sorted(
48+
glob.glob(os.path.join(dfolder, dname + '-depth/*.png')))
49+
50+
# read the full camera trajectory
51+
traj = read_log_trajectory(os.path.join(dfolder, dname + '-traj.log'))
52+
53+
K_d = np.eye(3)
54+
K_d[0, 0] = 525.0/deci
55+
K_d[1, 1] = 525.0/deci
56+
K_d[0, 2] = 319.5/deci
57+
K_d[1, 2] = 239.5/deci
58+
W_d = (int)(640/deci)
59+
H_d = (int)(480/deci)
60+
iu_d = ImageUtils(K_d, im_h=H_d, im_w=W_d)
61+
62+
# first frame
63+
pose_1 = traj[frame_1].pose
64+
translation_1 = pose_1[:3, 3]
65+
rotation_1 = pose_1[:3, :3].flatten()
66+
pcld_1, im_1 = iu_d.generate_pcld_wf(pose_1, rgb_path=rgb_paths[frame_1],
67+
depth_path=depth_paths[frame_1], size=(W_d, H_d))
68+
cprint.info(f"num points pcld_1: {pcld_1.shape[0]}")
69+
70+
lsogmm_gpu = GPUContainerf4()
71+
learner.fit(extract_ms_data(pcld_1), pcld_1, lsogmm_gpu)
72+
cprint.info(f"num components lsogmm_gpu: {lsogmm_gpu.n_components_}")
73+
74+
# second frame
75+
pose_2 = traj[frame_2].pose
76+
translation_2 = pose_2[:3, 3]
77+
pcld_2, im_2 = iu_d.generate_pcld_wf(pose_2, rgb_path=rgb_paths[frame_2],
78+
depth_path=depth_paths[frame_2], size=(W_d, H_d))
79+
cprint.info(f"num points pcld_2: {pcld_2.shape[0]}")
80+
81+
ts = time.time()
82+
scores_4d = inference.score_4d(pcld_2, lsogmm_gpu)
83+
te = time.time()
84+
cprint.info(f"4D time {te - ts} seconds")
85+
scores_4d = scores_4d.flatten()
86+
novel_4d_case = pcld_2[scores_4d < -3.14, :]
87+
88+
ts = time.time()
89+
scores_3d = inference.score_3d(pcld_2[:, :3], lsogmm_gpu)
90+
te = time.time()
91+
cprint.info(f"3D time {te - ts} seconds")
92+
scores_3d = scores_3d.flatten()
93+
novel_3d_case = pcld_2[scores_3d < -3.14, :]
94+
95+
lsogmm_cpu = CPUContainerf4(lsogmm_gpu.n_components_)
96+
lsogmm_gpu.to_host(lsogmm_cpu)
97+
gsh.add_points(lsogmm_cpu.means_, np.arange(0, lsogmm_cpu.n_components_, dtype=int))
98+
99+
ts = time.time()
100+
fov_comp_indices = gsh.find_points(pcld_2)
101+
submap_cpu = lsogmm_cpu.submap_from_indices(fov_comp_indices)
102+
submap_gpu = GPUContainerf4(submap_cpu.n_components_)
103+
submap_gpu.from_host(submap_cpu)
104+
scores_3d_fov = inference.score_3d(pcld_2[:, :3], submap_gpu)
105+
te = time.time()
106+
cprint.info(f"3D FoV time {te - ts} seconds")
107+
cprint.info(f"num components submap_gpu: {submap_gpu.n_components_}")
108+
scores_3d_fov = scores_3d_fov.flatten()
109+
novel_3d_fov_case = pcld_2[scores_3d_fov < -3.14, :]
110+
111+
vis0 = VisOpen3D(visible=True, window_name='a')
112+
vis0.add_geometries([np_to_o3d(pcld_1),
113+
np_to_o3d(pcld_2)])
114+
115+
vis0.add_geometries([np_to_o3d(pcld_1[:, :3], color=color_1),
116+
np_to_o3d(pcld_2[:, :3], color=color_2)])
117+
vis0.frustrum(pose_1, K_d, W_d, H_d, scale=0.4, color=color_1)
118+
vis0.frustrum(pose_2, K_d, W_d, H_d, scale=0.4, color=color_2)
119+
120+
vis1 = VisOpen3D(visible=True, window_name='b')
121+
vis1.add_geometries([np_to_o3d(pcld_1),
122+
np_to_o3d(novel_4d_case[:, :3], color=color_2)])
123+
vis1.update_view_point(extrinsic=np.linalg.inv(pose_2))
124+
vis1.poll_events()
125+
vis1.update_renderer()
126+
127+
vis2 = VisOpen3D(visible=True, window_name='c')
128+
vis2.add_geometries([np_to_o3d(pcld_1),
129+
np_to_o3d(novel_3d_case[:, :3], color=color_2)])
130+
vis2.update_view_point(extrinsic=np.linalg.inv(pose_2))
131+
vis2.poll_events()
132+
vis2.update_renderer()
133+
134+
vis3 = VisOpen3D(visible=True, window_name='d')
135+
vis3.add_geometries([np_to_o3d(pcld_1),
136+
np_to_o3d(novel_3d_fov_case[:, :3], color=color_2)])
137+
vis3.update_view_point(extrinsic=np.linalg.inv(pose_2))
138+
vis3.poll_events()
139+
vis3.update_renderer()
140+
141+
vis0.run()
142+
vis1.run()
143+
vis2.run()
144+
vis3.run()

run_scripts/config_parser.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import os
2+
import configargparse
3+
4+
5+
class ConfigParser(configargparse.ArgParser):
6+
def __init__(self):
7+
super().__init__(default_config_files=[
8+
os.path.join(os.path.dirname(__file__),
9+
'livingroom1.yaml')
10+
], conflict_handler='resolve')
11+
12+
# for 4D point cloud dataset
13+
self.add_argument('--path_datasets', type=str)
14+
self.add_argument('--path_results', type=str)
15+
self.add_argument('--dataset_name', type=str)
16+
self.add_argument('--color_ext', type=str)
17+
self.add_argument('--nframes', type=int)
18+
self.add_argument('--bandwidth', type=float)
19+
self.add_argument('--deci', type=float)
20+
self.add_argument('--machine', type=str)
21+
self.add_argument('--zfill', type=int)
22+
self.add_argument('--l_thres', type=float)
23+
self.add_argument('--bw_list', nargs='+', type=float)
24+
25+
def get_config(self):
26+
config = self.parse_args()
27+
return config

run_scripts/copyroom.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
path_datasets: "/media/fractal/T7/datasets"
2+
path_results: "/media/fractal/T7/rss2023-resub/results"
3+
dataset_name: "copyroom"
4+
color_ext: "png"
5+
nframes: 5490
6+
bandwidth: 0.03
7+
deci: 5.0
8+
machine: "fractal"
9+
zfill: 6
10+
l_thres: -1.0
11+
bw_list: [0.05, 0.04, 0.03, 0.02]

0 commit comments

Comments
 (0)