abreza commited on
Commit
161b8e5
·
1 Parent(s): ba85228

add support et visualization

Browse files
Files changed (2) hide show
  1. app.py +86 -70
  2. visualization/et_visualizer.py +131 -0
app.py CHANGED
@@ -1,77 +1,93 @@
1
  import gradio as gr
2
- import numpy as np
3
- import torch
4
- import torch.nn.functional as F
5
- from evo.tools.file_interface import read_kitti_poses_file
6
- from pathlib import Path
7
  from visualization.visualizer import visualize_simulation
 
 
8
 
9
 
10
- def load_trajectory_data(traj_file, char_file, num_cams=30):
11
- trajectory = read_kitti_poses_file(traj_file)
12
- matrix_trajectory = torch.from_numpy(np.array(trajectory.poses_se3)).to(torch.float32)
13
-
14
- raw_trans = torch.clone(matrix_trajectory[:, :3, 3])
15
- raw_rot = matrix_trajectory[:, :3, :3]
16
- rot6d = raw_rot[:, :, :2].permute(0, 2, 1).reshape(-1, 6)
17
-
18
- trajectory_feature = torch.hstack([rot6d, raw_trans]).permute(1, 0)
19
-
20
- padded_trajectory_feature = F.pad(
21
- trajectory_feature,
22
- (0, num_cams - trajectory_feature.shape[1])
23
  )
24
-
25
- padding_mask = torch.ones((num_cams))
26
- padding_mask[trajectory_feature.shape[1]:] = 0
27
-
28
- char_feature = torch.from_numpy(np.load(char_file)).to(torch.float32)
29
- padding_size = num_cams - char_feature.shape[0]
30
- padded_char_feature = F.pad(char_feature, (0, 0, 0, padding_size)).permute(1, 0)
31
-
32
- return {
33
- "traj_filename": Path(traj_file).name,
34
- "char_filename": Path(char_file).name,
35
- "traj_feat": padded_trajectory_feature,
36
- "char_feat": padded_char_feature,
37
- "padding_mask": padding_mask,
38
- "raw_matrix_trajectory": matrix_trajectory
39
- }
40
-
41
- def create_trajectory_interface():
42
- """Create Gradio interface for loading trajectory data"""
43
-
44
- def process_files(traj_file, char_file):
45
- try:
46
- result = load_trajectory_data(traj_file.name, char_file.name)
47
-
48
- # Convert tensors to numpy for display
49
- info = {
50
- "Trajectory filename": result["traj_filename"],
51
- "Character filename": result["char_filename"],
52
- "Trajectory shape": result["traj_feat"].shape,
53
- "Character shape": result["char_feat"].shape,
54
- "Valid frames": int(result["padding_mask"].sum().item())
55
- }
56
-
57
- return str(info)
58
-
59
- except Exception as e:
60
- return f"Error processing files: {str(e)}"
61
-
62
- interface = gr.Interface(
63
- fn=process_files,
64
- inputs=[
65
- gr.File(label="Trajectory File (.txt)"),
66
- gr.File(label="Character File (.npy)")
67
- ],
68
- outputs=gr.Textbox(label="Results"),
69
- title="Trajectory Data Loader",
70
- description="Upload trajectory (.txt) and character (.npy) files to load and process them."
71
- )
72
-
73
- return interface
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74
 
75
  if __name__ == "__main__":
76
- interface = create_trajectory_interface()
77
- interface.launch()
 
1
  import gradio as gr
2
+ from gradio_rerun import Rerun
3
+ from data.loader import load_simulation_data
 
 
 
4
  from visualization.visualizer import visualize_simulation
5
+ from visualization.et_visualizer import visualize_et_data
6
+ from pathlib import Path
7
 
8
 
9
+ def update_simulation_dropdown(file):
10
+ simulations, descriptions = load_simulation_data(file)
11
+ return gr.Dropdown(
12
+ choices=descriptions if descriptions else [],
13
+ value=None,
14
+ allow_custom_value=False
 
 
 
 
 
 
 
15
  )
16
+
17
+
18
+ def create_app():
19
+ with gr.Blocks() as demo:
20
+ with gr.Tabs() as tabs:
21
+ # Camera Simulation Tab
22
+ with gr.Tab("Camera Simulation"):
23
+ gr.Markdown("""
24
+ # Camera Simulation Visualizer
25
+ Upload a JSON file containing camera simulation data and select a simulation to visualize.
26
+ """)
27
+
28
+ with gr.Row():
29
+ file_input = gr.File(
30
+ label="Upload Simulation JSON",
31
+ file_types=[".json"]
32
+ )
33
+ simulation_dropdown = gr.Dropdown(
34
+ label="Select Simulation",
35
+ choices=[],
36
+ type="index",
37
+ scale=2
38
+ )
39
+
40
+ with gr.Row():
41
+ viewer = Rerun(streaming=False)
42
+
43
+ file_input.change(
44
+ update_simulation_dropdown,
45
+ inputs=[file_input],
46
+ outputs=[simulation_dropdown]
47
+ )
48
+
49
+ simulation_dropdown.change(
50
+ visualize_simulation,
51
+ inputs=[file_input, simulation_dropdown],
52
+ outputs=[viewer]
53
+ )
54
+
55
+ # E.T. Dataset Tab
56
+ with gr.Tab("E.T. Dataset"):
57
+ gr.Markdown("""
58
+ # E.T. Dataset Visualizer
59
+ Upload trajectory (.txt) and character (.npy) files to visualize the E.T. dataset.
60
+ """)
61
+
62
+ with gr.Row():
63
+ traj_file = gr.File(
64
+ label="Trajectory File (.txt)",
65
+ file_types=[".txt"]
66
+ )
67
+ char_file = gr.File(
68
+ label="Character File (.npy)",
69
+ file_types=[".npy"]
70
+ )
71
+
72
+ with gr.Row():
73
+ et_viewer = Rerun(streaming=False)
74
+
75
+ def process_et_files(traj_file, char_file):
76
+ if traj_file is None or char_file is None:
77
+ return None
78
+ return visualize_et_data(traj_file.name, char_file.name)
79
+
80
+ with gr.Row():
81
+ visualize_btn = gr.Button("Visualize")
82
+ visualize_btn.click(
83
+ process_et_files,
84
+ inputs=[traj_file, char_file],
85
+ outputs=[et_viewer]
86
+ )
87
+
88
+ return demo
89
+
90
 
91
  if __name__ == "__main__":
92
+ demo = create_app()
93
+ demo.queue().launch(share=False)
visualization/et_visualizer.py ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tempfile
2
+ import os
3
+ import spaces
4
+ import numpy as np
5
+ import torch
6
+ import torch.nn.functional as F
7
+ from evo.tools.file_interface import read_kitti_poses_file
8
+ from pathlib import Path
9
+ import rerun as rr
10
+ from typing import Optional, Dict
11
+ from visualization.logger import SimulationLogger
12
+
13
+
14
+ def load_trajectory_data(traj_file: str, char_file: str, num_cams: int = 30) -> Dict:
15
+ trajectory = read_kitti_poses_file(traj_file)
16
+ matrix_trajectory = torch.from_numpy(
17
+ np.array(trajectory.poses_se3)).to(torch.float32)
18
+
19
+ raw_trans = torch.clone(matrix_trajectory[:, :3, 3])
20
+ raw_rot = matrix_trajectory[:, :3, :3]
21
+
22
+ # Convert to 6D rotation representation
23
+ rot6d = raw_rot[:, :, :2].permute(0, 2, 1).reshape(-1, 6)
24
+ trajectory_feature = torch.hstack([rot6d, raw_trans]).permute(1, 0)
25
+
26
+ # Pad trajectory features
27
+ padded_trajectory_feature = F.pad(
28
+ trajectory_feature,
29
+ (0, num_cams - trajectory_feature.shape[1])
30
+ )
31
+
32
+ # Create padding mask
33
+ padding_mask = torch.ones((num_cams))
34
+ padding_mask[trajectory_feature.shape[1]:] = 0
35
+
36
+ # Load and pad character features
37
+ char_feature = torch.from_numpy(np.load(char_file)).to(torch.float32)
38
+ padding_size = num_cams - char_feature.shape[0]
39
+ padded_char_feature = F.pad(
40
+ char_feature, (0, 0, 0, padding_size)).permute(1, 0)
41
+
42
+ return {
43
+ "traj_filename": Path(traj_file).name,
44
+ "char_filename": Path(char_file).name,
45
+ "traj_feat": padded_trajectory_feature,
46
+ "char_feat": padded_char_feature,
47
+ "padding_mask": padding_mask,
48
+ "raw_matrix_trajectory": matrix_trajectory
49
+ }
50
+
51
+
52
+ class ETLogger(SimulationLogger):
53
+ def __init__(self):
54
+ super().__init__()
55
+ rr.init("et_visualization")
56
+ rr.log("world", rr.ViewCoordinates.RIGHT_HAND_Y_UP, timeless=True)
57
+
58
+ def log_trajectory(self, trajectory: np.ndarray, padding_mask: np.ndarray):
59
+ """Log camera trajectory."""
60
+ valid_frames = int(padding_mask.sum())
61
+ valid_trajectory = trajectory[:valid_frames]
62
+
63
+ # Log trajectory points
64
+ positions = valid_trajectory[:, :3, 3]
65
+ rr.log(
66
+ "world/trajectory/points",
67
+ rr.Points3D(
68
+ positions,
69
+ colors=np.full((len(positions), 4), [0.0, 0.8, 0.8, 1.0])
70
+ ),
71
+ timeless=True
72
+ )
73
+
74
+ # Log trajectory line
75
+ if len(positions) > 1:
76
+ lines = np.stack([positions[:-1], positions[1:]], axis=1)
77
+ rr.log(
78
+ "world/trajectory/line",
79
+ rr.LineStrips3D(
80
+ lines,
81
+ colors=[(0.0, 0.8, 0.8, 1.0)]
82
+ ),
83
+ timeless=True
84
+ )
85
+
86
+ def log_character(self, char_feature: np.ndarray, padding_mask: np.ndarray):
87
+ """Log character feature visualization."""
88
+ valid_frames = int(padding_mask.sum())
89
+ valid_char = char_feature[:, :valid_frames]
90
+
91
+ if valid_char.shape[0] > 0:
92
+ rr.log(
93
+ "world/character",
94
+ rr.Points3D(
95
+ valid_char.reshape(-1, 3),
96
+ colors=np.full(
97
+ (valid_char.reshape(-1, 3).shape[0], 4), [0.8, 0.2, 0.2, 1.0])
98
+ ),
99
+ timeless=True
100
+ )
101
+
102
+
103
+ @spaces.GPU
104
+ def visualize_et_data(traj_file: str, char_file: str) -> Optional[str]:
105
+ """Visualize E.T. dataset using Rerun."""
106
+ try:
107
+ # Load data
108
+ data = load_trajectory_data(traj_file, char_file)
109
+
110
+ # Create temporary file for RRD
111
+ temp_dir = tempfile.mkdtemp()
112
+ rrd_path = os.path.join(temp_dir, "et_visualization.rrd")
113
+
114
+ # Initialize logger and log data
115
+ logger = ETLogger()
116
+ logger.log_trajectory(
117
+ data["raw_matrix_trajectory"].numpy(),
118
+ data["padding_mask"].numpy()
119
+ )
120
+ logger.log_character(
121
+ data["char_feat"].numpy(),
122
+ data["padding_mask"].numpy()
123
+ )
124
+
125
+ # Save visualization
126
+ rr.save(rrd_path)
127
+ return rrd_path
128
+
129
+ except Exception as e:
130
+ print(f"Error visualizing E.T. data: {str(e)}")
131
+ return None