Breeze1124 commited on
Commit
ba6f051
·
1 Parent(s): 4d3c14b

Add spaces decorator for ZeroGPU

Browse files
Files changed (1) hide show
  1. app.py +38 -65
app.py CHANGED
@@ -2,6 +2,7 @@ import gradio as gr
2
  import os
3
  import struct
4
  import numpy as np
 
5
 
6
  # --- 1. Configuration ---
7
  SCENES = [
@@ -47,10 +48,9 @@ def read_gaussian_ply(filepath):
47
  vertex_count = int(line.split()[-1])
48
  break
49
 
50
- print(f"Reading {vertex_count:,} Gaussian splats...")
51
 
52
  # 讀取二進制數據
53
- # 每個 vertex: 17 個 float (x,y,z, nx,ny,nz, f_dc_0,f_dc_1,f_dc_2, opacity, scale*3, rot*4)
54
  bytes_per_vertex = 17 * 4 # 17 floats * 4 bytes
55
  data = f.read(vertex_count * bytes_per_vertex)
56
 
@@ -67,8 +67,6 @@ def read_gaussian_ply(filepath):
67
  vertices.append([x, y, z])
68
 
69
  # 提取顏色 (f_dc_0, f_dc_1, f_dc_2) 並轉換到 [0, 255]
70
- # Gaussian Splatting 使用球諧函數,f_dc 是 DC 分量
71
- # 轉換公式: color = (0.5 + SH_C0 * f_dc) * 255
72
  SH_C0 = 0.28209479177387814
73
  r = max(0, min(255, int((0.5 + SH_C0 * vertex_data[6]) * 255)))
74
  g = max(0, min(255, int((0.5 + SH_C0 * vertex_data[7]) * 255)))
@@ -101,75 +99,52 @@ def convert_to_standard_ply(input_path, output_path):
101
 
102
  print(f"✅ Converted to: {output_path}")
103
 
104
- # --- 4. 初始化 - 轉換所有文件 ---
105
- def initialize_converted_models():
106
- """轉換所有 Gaussian Splatting PLY 為標準格式"""
 
 
 
 
107
 
108
  converted_dir = "converted"
109
  os.makedirs(converted_dir, exist_ok=True)
110
 
111
- converted_scenes = []
 
112
 
113
- for scene in SCENES:
114
- input_ply = scene["model"]
115
- output_ply = f"{converted_dir}/{os.path.basename(input_ply)}"
116
-
117
- if not os.path.exists(output_ply):
118
- print(f"\n🔄 Converting {scene['name']}...")
119
- try:
120
- convert_to_standard_ply(input_ply, output_ply)
121
- except Exception as e:
122
- print(f"❌ Error converting {input_ply}: {e}")
123
- continue
124
- else:
125
- print(f"✅ Already converted: {output_ply}")
126
-
127
- # 更新場景配置
128
- converted_scenes.append({
129
- **scene,
130
- "converted_model": output_ply
131
- })
132
-
133
- return converted_scenes
134
-
135
- # --- 5. 選擇處理 ---
136
- def create_select_handler(converted_scenes):
137
- """創建選擇處理函數"""
138
- def on_select(evt: gr.SelectData):
139
- index = evt.index
140
- scene = converted_scenes[index]
141
-
142
- if "converted_model" not in scene or not os.path.exists(scene["converted_model"]):
143
  return (
144
  None,
145
  scene["tracking_img"],
146
- f"**Error: Converted model not found for {scene['name']}**"
147
  )
148
-
149
- file_size = os.path.getsize(scene["converted_model"]) / (1024 * 1024)
150
-
151
- print(f"\n📂 Loading: {scene['name']}")
152
- print(f" File: {scene['converted_model']}")
153
- print(f" Size: {file_size:.1f} MB\n")
154
-
155
  return (
156
- scene["converted_model"],
157
  scene["tracking_img"],
158
- f"**{scene['name']}** ({file_size:.1f} MB) ✓"
 
 
 
 
 
 
159
  )
160
-
161
- return on_select
162
-
163
- # --- 6. UI ---
164
- print("\n" + "="*60)
165
- print("🚀 RGS-SLAM Viewer - Initializing...")
166
- print("="*60)
167
-
168
- # 轉換模型
169
- converted_scenes = initialize_converted_models()
170
 
 
171
  print("\n" + "="*60)
172
- print(" Ready to launch!")
173
  print("="*60 + "\n")
174
 
175
  with gr.Blocks(title="RGS-SLAM Demo") as demo:
@@ -177,7 +152,7 @@ with gr.Blocks(title="RGS-SLAM Demo") as demo:
177
  gr.Markdown("# 🚀 RGS-SLAM Gaussian Splatting Viewer")
178
  gr.Markdown(
179
  "**3D Gaussian Splatting** reconstruction results with camera trajectories. "
180
- "Models are automatically converted to viewable format."
181
  )
182
 
183
  with gr.Row():
@@ -199,7 +174,7 @@ with gr.Blocks(title="RGS-SLAM Demo") as demo:
199
  """)
200
 
201
  with gr.Column(scale=3):
202
- status = gr.Markdown("**👈 Select a scene to begin**")
203
 
204
  with gr.Tab("🎯 3D Reconstruction"):
205
  gr.Markdown("### Point Cloud with Colors")
@@ -217,11 +192,9 @@ with gr.Blocks(title="RGS-SLAM Demo") as demo:
217
  height=600
218
  )
219
 
220
- # Event binding
221
- select_handler = create_select_handler(converted_scenes)
222
-
223
  scene_gallery.select(
224
- fn=select_handler,
225
  outputs=[model_viewer, trajectory_img, status]
226
  )
227
 
 
2
  import os
3
  import struct
4
  import numpy as np
5
+ import spaces # <--- 1. 新增這個 import
6
 
7
  # --- 1. Configuration ---
8
  SCENES = [
 
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
 
 
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)))
 
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:
 
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():
 
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")
 
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