Breeze1124 commited on
Commit
0a91ebd
ยท
1 Parent(s): ba6f051

update app.py

Browse files
Files changed (1) hide show
  1. app.py +26 -151
app.py CHANGED
@@ -1,159 +1,57 @@
1
  import gradio as gr
2
  import os
3
- import struct
4
- import numpy as np
5
- import spaces # <--- 1. ๆ–ฐๅขž้€™ๅ€‹ import
6
 
7
- # --- 1. Configuration ---
 
8
  SCENES = [
9
  {
10
  "name": "Office 0",
11
  "thumb": "assets/office0.PNG",
12
- "model": "assets/office0.ply",
13
  "tracking_img": "assets/office0_tracking.PNG"
14
  },
15
  {
16
  "name": "Office 2",
17
  "thumb": "assets/office2.PNG",
18
- "model": "assets/office2.ply",
19
  "tracking_img": "assets/office2_tracking.PNG"
20
  },
21
  {
22
  "name": "Room 0",
23
  "thumb": "assets/room0.PNG",
24
- "model": "assets/room0.ply",
25
  "tracking_img": "assets/room0_tracking.PNG"
26
  }
27
  ]
28
 
29
  gallery_items = [(item["thumb"], item["name"]) for item in SCENES]
30
 
31
- # --- 2. ่ฎ€ๅ–ไธฆ่ฝ‰ๆ› Gaussian Splatting PLY ---
32
- def read_gaussian_ply(filepath):
33
- """่ฎ€ๅ– Gaussian Splatting PLY ไธฆๆๅ–ไฝ็ฝฎๅ’Œ้ก่‰ฒ"""
34
-
35
- with open(filepath, 'rb') as f:
36
- # ่ฎ€ๅ– header
37
- header = []
38
- while True:
39
- line = f.readline().decode('utf-8').strip()
40
- header.append(line)
41
- if line == 'end_header':
42
- break
43
-
44
- # ่งฃๆž vertex ๆ•ธ้‡
45
- vertex_count = 0
46
- for line in header:
47
- if line.startswith('element vertex'):
48
- vertex_count = int(line.split()[-1])
49
- break
50
-
51
- print(f"Reading {vertex_count:,} Gaussian splats from {os.path.basename(filepath)}...")
52
-
53
- # ่ฎ€ๅ–ไบŒ้€ฒๅˆถๆ•ธๆ“š
54
- bytes_per_vertex = 17 * 4 # 17 floats * 4 bytes
55
- data = f.read(vertex_count * bytes_per_vertex)
56
-
57
- # ่งฃๆžๆ•ธๆ“š
58
- vertices = []
59
- colors = []
60
-
61
- for i in range(vertex_count):
62
- offset = i * bytes_per_vertex
63
- vertex_data = struct.unpack('17f', data[offset:offset + bytes_per_vertex])
64
-
65
- # ๆๅ–ไฝ็ฝฎ (x, y, z)
66
- x, y, z = vertex_data[0], vertex_data[1], vertex_data[2]
67
- vertices.append([x, y, z])
68
-
69
- # ๆๅ–้ก่‰ฒ (f_dc_0, f_dc_1, f_dc_2) ไธฆ่ฝ‰ๆ›ๅˆฐ [0, 255]
70
- SH_C0 = 0.28209479177387814
71
- r = max(0, min(255, int((0.5 + SH_C0 * vertex_data[6]) * 255)))
72
- g = max(0, min(255, int((0.5 + SH_C0 * vertex_data[7]) * 255)))
73
- b = max(0, min(255, int((0.5 + SH_C0 * vertex_data[8]) * 255)))
74
- colors.append([r, g, b])
75
-
76
- return np.array(vertices, dtype=np.float32), np.array(colors, dtype=np.uint8)
77
-
78
- # --- 3. ่ฝ‰ๆ›็‚บๆจ™ๆบ– PLY ---
79
- def convert_to_standard_ply(input_path, output_path):
80
- """ๅฐ‡ Gaussian Splatting PLY ่ฝ‰ๆ›็‚บๆจ™ๆบ–ๅธถ้ก่‰ฒ็š„ PLY"""
81
-
82
- vertices, colors = read_gaussian_ply(input_path)
83
-
84
- # ๅฏซๅ…ฅ ASCII PLY
85
- with open(output_path, 'w') as f:
86
- f.write('ply\n')
87
- f.write('format ascii 1.0\n')
88
- f.write(f'element vertex {len(vertices)}\n')
89
- f.write('property float x\n')
90
- f.write('property float y\n')
91
- f.write('property float z\n')
92
- f.write('property uchar red\n')
93
- f.write('property uchar green\n')
94
- f.write('property uchar blue\n')
95
- f.write('end_header\n')
96
-
97
- for vertex, color in zip(vertices, colors):
98
- f.write(f'{vertex[0]} {vertex[1]} {vertex[2]} {color[0]} {color[1]} {color[2]}\n')
99
-
100
- print(f"โœ… Converted to: {output_path}")
101
-
102
- # --- 4. ๆ ธๅฟƒ่™•็†ๅ‡ฝๅผ (ๅŠ ไธŠ @spaces.GPU) ---
103
- # ๆณจๆ„๏ผšๅณไฝฟ้€™ๅชๆ˜ฏๆช”ๆกˆ่ฝ‰ๆ›๏ผŒๅŠ ไธŠ้€™ๅ€‹ๆจ™็ฑคๅฏไปฅ่งฃๆฑบ ZeroGPU ็š„ๆชขๆŸฅ้Œฏ่ชค
104
- # ไธฆไธ”ๅฐ‡้‹็ฎ—็งปๅˆฐ่จˆ็ฎ—็ฏ€้ปžไธŠๅŸท่กŒ
105
- @spaces.GPU(duration=120)
106
- def process_and_load_scene(evt: gr.SelectData):
107
  index = evt.index
108
  scene = SCENES[index]
109
 
110
- converted_dir = "converted"
111
- os.makedirs(converted_dir, exist_ok=True)
112
-
113
- input_ply = scene["model"]
114
- output_ply = f"{converted_dir}/{os.path.basename(input_ply)}"
115
-
116
- # ๆชขๆŸฅๆ˜ฏๅฆ้œ€่ฆ่ฝ‰ๆ› (Lazy Loading)
117
- if not os.path.exists(output_ply):
118
- print(f"\n๐Ÿ”„ Converting {scene['name']} on GPU Node...")
119
- try:
120
- convert_to_standard_ply(input_ply, output_ply)
121
- except Exception as e:
122
- return (
123
- None,
124
- scene["tracking_img"],
125
- f"**Error converting {scene['name']}: {str(e)}**"
126
- )
127
- else:
128
- print(f"โœ… Using cached model: {output_ply}")
129
-
130
- # ๆชขๆŸฅๆช”ๆกˆๅคงๅฐ
131
- if os.path.exists(output_ply):
132
- file_size = os.path.getsize(output_ply) / (1024 * 1024)
133
  return (
134
- output_ply,
135
  scene["tracking_img"],
136
- f"**{scene['name']}** ({file_size:.1f} MB) โœ“ Loaded"
137
  )
138
- else:
139
- return (
140
- None,
141
- scene["tracking_img"],
142
- "**Error: File not found after conversion**"
143
- )
144
-
145
- # --- 5. UI ---
146
- print("\n" + "="*60)
147
- print("๐Ÿš€ RGS-SLAM Viewer - Initializing UI...")
148
- print("="*60 + "\n")
149
 
 
150
  with gr.Blocks(title="RGS-SLAM Demo") as demo:
151
 
152
  gr.Markdown("# ๐Ÿš€ RGS-SLAM Gaussian Splatting Viewer")
153
- gr.Markdown(
154
- "**3D Gaussian Splatting** reconstruction results with camera trajectories. "
155
- "Select a scene below to load the model."
156
- )
157
 
158
  with gr.Row():
159
  with gr.Column(scale=1):
@@ -165,47 +63,24 @@ with gr.Blocks(title="RGS-SLAM Demo") as demo:
165
  height=400,
166
  object_fit="contain"
167
  )
168
-
169
- gr.Markdown("""
170
- ### ๐ŸŽฎ Controls
171
- - **Rotate**: Left mouse drag
172
- - **Zoom**: Mouse wheel
173
- - **Pan**: Right mouse drag
174
- """)
175
 
176
  with gr.Column(scale=3):
177
- status = gr.Markdown("**๐Ÿ‘ˆ Select a scene to begin (Conversion happens on click)**")
178
 
179
  with gr.Tab("๐ŸŽฏ 3D Reconstruction"):
180
- gr.Markdown("### Point Cloud with Colors")
181
  model_viewer = gr.Model3D(
182
- label="Gaussian Splat Visualization",
183
  clear_color=[0.1, 0.1, 0.1, 1.0],
184
  height=600
185
  )
186
- gr.Markdown("*Colors extracted from Gaussian Splatting's spherical harmonics (f_dc)*")
187
 
188
  with gr.Tab("๐Ÿ“ Camera Trajectory"):
189
- gr.Markdown("### SLAM Tracking Results")
190
- trajectory_img = gr.Image(
191
- label="Camera Path",
192
- height=600
193
- )
194
 
195
- # Event binding (็›ดๆŽฅ็ถๅฎšๅˆฐๆœ‰ @spaces.GPU ็š„ๅ‡ฝๅผ)
196
  scene_gallery.select(
197
- fn=process_and_load_scene,
198
  outputs=[model_viewer, trajectory_img, status]
199
  )
200
-
201
- gr.Markdown("---")
202
- gr.Markdown(
203
- "**Note:** Gaussian Splatting PLY files contain spherical harmonics coefficients. "
204
- "Colors are extracted from the DC component (f_dc_0, f_dc_1, f_dc_2) for visualization."
205
- )
206
 
207
  if __name__ == "__main__":
208
- demo.launch(
209
- server_name="0.0.0.0",
210
- server_port=7860
211
- )
 
1
  import gradio as gr
2
  import os
 
 
 
3
 
4
+ # --- Configuration ---
5
+ # ๆŒ‡ๅ‘ๆˆ‘ๅ€‘ๅ‰›ๅ‰›ไธŠๅ‚ณ็š„ "assets_converted" ่ณ‡ๆ–™ๅคพ
6
  SCENES = [
7
  {
8
  "name": "Office 0",
9
  "thumb": "assets/office0.PNG",
10
+ "model": "assets_converted/office0_converted.ply", # ๆŒ‡ๅ‘่ฝ‰ๅฅฝ็š„ๆช”
11
  "tracking_img": "assets/office0_tracking.PNG"
12
  },
13
  {
14
  "name": "Office 2",
15
  "thumb": "assets/office2.PNG",
16
+ "model": "assets_converted/office2_converted.ply",
17
  "tracking_img": "assets/office2_tracking.PNG"
18
  },
19
  {
20
  "name": "Room 0",
21
  "thumb": "assets/room0.PNG",
22
+ "model": "assets_converted/room0_converted.ply",
23
  "tracking_img": "assets/room0_tracking.PNG"
24
  }
25
  ]
26
 
27
  gallery_items = [(item["thumb"], item["name"]) for item in SCENES]
28
 
29
+ def load_scene(evt: gr.SelectData):
30
+ """
31
+ ๅ› ็‚บๆช”ๆกˆๅทฒ็ถ“ๆ˜ฏๆจ™ๆบ–ๆ ผๅผ๏ผŒ็›ดๆŽฅๅ›žๅ‚ณ่ทฏๅพ‘ๅณๅฏใ€‚
32
+ ไธ้œ€่ฆ GPU๏ผŒไธ้œ€่ฆ้‹็ฎ—ใ€‚
33
+ """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  index = evt.index
35
  scene = SCENES[index]
36
 
37
+ if not os.path.exists(scene["model"]):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  return (
39
+ None,
40
  scene["tracking_img"],
41
+ f"**Error: Model file not found: {scene['model']}**"
42
  )
43
+
44
+ file_size = os.path.getsize(scene["model"]) / (1024 * 1024)
45
+ return (
46
+ scene["model"],
47
+ scene["tracking_img"],
48
+ f"**{scene['name']}** ({file_size:.1f} MB) โœ“ Loaded"
49
+ )
 
 
 
 
50
 
51
+ # --- UI ---
52
  with gr.Blocks(title="RGS-SLAM Demo") as demo:
53
 
54
  gr.Markdown("# ๐Ÿš€ RGS-SLAM Gaussian Splatting Viewer")
 
 
 
 
55
 
56
  with gr.Row():
57
  with gr.Column(scale=1):
 
63
  height=400,
64
  object_fit="contain"
65
  )
 
 
 
 
 
 
 
66
 
67
  with gr.Column(scale=3):
68
+ status = gr.Markdown("**๐Ÿ‘ˆ Select a scene to load**")
69
 
70
  with gr.Tab("๐ŸŽฏ 3D Reconstruction"):
 
71
  model_viewer = gr.Model3D(
72
+ label="3D Model",
73
  clear_color=[0.1, 0.1, 0.1, 1.0],
74
  height=600
75
  )
 
76
 
77
  with gr.Tab("๐Ÿ“ Camera Trajectory"):
78
+ trajectory_img = gr.Image(label="Camera Path", height=600)
 
 
 
 
79
 
 
80
  scene_gallery.select(
81
+ fn=load_scene,
82
  outputs=[model_viewer, trajectory_img, status]
83
  )
 
 
 
 
 
 
84
 
85
  if __name__ == "__main__":
86
+ demo.launch()