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

Add images using LFS

Browse files
.gitattributes CHANGED
@@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ *.ply filter=lfs diff=lfs merge=lfs -text
37
+ *.PNG filter=lfs diff=lfs merge=lfs -text
app.py ADDED
@@ -0,0 +1,238 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+ import struct
4
+ import numpy as np
5
+
6
+ # --- 1. Configuration ---
7
+ SCENES = [
8
+ {
9
+ "name": "Office 0",
10
+ "thumb": "assets/office0.PNG",
11
+ "model": "assets/office0.ply",
12
+ "tracking_img": "assets/office0_tracking.PNG"
13
+ },
14
+ {
15
+ "name": "Office 2",
16
+ "thumb": "assets/office2.PNG",
17
+ "model": "assets/office2.ply",
18
+ "tracking_img": "assets/office2_tracking.PNG"
19
+ },
20
+ {
21
+ "name": "Room 0",
22
+ "thumb": "assets/room0.PNG",
23
+ "model": "assets/room0.ply",
24
+ "tracking_img": "assets/room0_tracking.PNG"
25
+ }
26
+ ]
27
+
28
+ gallery_items = [(item["thumb"], item["name"]) for item in SCENES]
29
+
30
+ # --- 2. 讀取並轉換 Gaussian Splatting PLY ---
31
+ def read_gaussian_ply(filepath):
32
+ """讀取 Gaussian Splatting PLY 並提取位置和顏色"""
33
+
34
+ with open(filepath, 'rb') as f:
35
+ # 讀取 header
36
+ header = []
37
+ while True:
38
+ line = f.readline().decode('utf-8').strip()
39
+ header.append(line)
40
+ if line == 'end_header':
41
+ break
42
+
43
+ # 解析 vertex 數量
44
+ vertex_count = 0
45
+ for line in header:
46
+ if line.startswith('element vertex'):
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
+
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
+ # 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)))
75
+ b = max(0, min(255, int((0.5 + SH_C0 * vertex_data[8]) * 255)))
76
+ colors.append([r, g, b])
77
+
78
+ return np.array(vertices, dtype=np.float32), np.array(colors, dtype=np.uint8)
79
+
80
+ # --- 3. 轉換為標準 PLY ---
81
+ def convert_to_standard_ply(input_path, output_path):
82
+ """將 Gaussian Splatting PLY 轉換為標準帶顏色的 PLY"""
83
+
84
+ vertices, colors = read_gaussian_ply(input_path)
85
+
86
+ # 寫入 ASCII PLY
87
+ with open(output_path, 'w') as f:
88
+ f.write('ply\n')
89
+ f.write('format ascii 1.0\n')
90
+ f.write(f'element vertex {len(vertices)}\n')
91
+ f.write('property float x\n')
92
+ f.write('property float y\n')
93
+ f.write('property float z\n')
94
+ f.write('property uchar red\n')
95
+ f.write('property uchar green\n')
96
+ f.write('property uchar blue\n')
97
+ f.write('end_header\n')
98
+
99
+ for vertex, color in zip(vertices, colors):
100
+ f.write(f'{vertex[0]} {vertex[1]} {vertex[2]} {color[0]} {color[1]} {color[2]}\n')
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:
176
+
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():
184
+ with gr.Column(scale=1):
185
+ gr.Markdown("### 📂 Select Scene")
186
+ scene_gallery = gr.Gallery(
187
+ value=gallery_items,
188
+ label="Available Scenes",
189
+ columns=1,
190
+ height=400,
191
+ object_fit="contain"
192
+ )
193
+
194
+ gr.Markdown("""
195
+ ### 🎮 Controls
196
+ - **Rotate**: Left mouse drag
197
+ - **Zoom**: Mouse wheel
198
+ - **Pan**: Right mouse drag
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")
206
+ model_viewer = gr.Model3D(
207
+ label="Gaussian Splat Visualization",
208
+ clear_color=[0.1, 0.1, 0.1, 1.0],
209
+ height=600
210
+ )
211
+ gr.Markdown("*Colors extracted from Gaussian Splatting's spherical harmonics (f_dc)*")
212
+
213
+ with gr.Tab("📍 Camera Trajectory"):
214
+ gr.Markdown("### SLAM Tracking Results")
215
+ trajectory_img = gr.Image(
216
+ label="Camera Path",
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
+
228
+ gr.Markdown("---")
229
+ gr.Markdown(
230
+ "**Note:** Gaussian Splatting PLY files contain spherical harmonics coefficients. "
231
+ "Colors are extracted from the DC component (f_dc_0, f_dc_1, f_dc_2) for visualization."
232
+ )
233
+
234
+ if __name__ == "__main__":
235
+ demo.launch(
236
+ server_name="0.0.0.0",
237
+ server_port=7860
238
+ )
assets/office0.PNG ADDED

Git LFS Details

  • SHA256: 01917dc7bc7429978272496fd1f867b385950e5bd50fd6576ab41bae16bfdf6e
  • Pointer size: 131 Bytes
  • Size of remote file: 985 kB
assets/office0.ply ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5e4993a8a3ff0e4aed46b765feefde8cd64e4578d3e818cdc5451b8491e070cb
3
+ size 16192712
assets/office0_tracking.PNG ADDED

Git LFS Details

  • SHA256: eb2d4fd091aeede6a776574a7848c216514de8fded040f20973ff386ddf88ad9
  • Pointer size: 132 Bytes
  • Size of remote file: 1.28 MB
assets/office2.PNG ADDED

Git LFS Details

  • SHA256: 537913bec352a93303c8d93a0d6e09cc095c8e88c1165ce7b501e2a224315eea
  • Pointer size: 131 Bytes
  • Size of remote file: 978 kB
assets/office2.ply ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:71bfcaaac3bff99ad34a435877be0c4ce87bf6c75728ee457f19b9ea74333059
3
+ size 26793844
assets/office2_tracking.PNG ADDED

Git LFS Details

  • SHA256: e2c83a29186c50958b46ed355012e971e0793519ec85aaa15f03fc6f8fa792d4
  • Pointer size: 132 Bytes
  • Size of remote file: 1.25 MB
assets/room0.PNG ADDED

Git LFS Details

  • SHA256: 4efd4ac3a9e74e5dc6fc207f3dea79cf9fe3bc3f89b110acaf2bc337433bed21
  • Pointer size: 131 Bytes
  • Size of remote file: 957 kB
assets/room0.ply ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e1ebdf314fb5d4f0bbc0ad3b58b605c1a89432347a99a61fad2285976cee09fc
3
+ size 19860972
assets/room0_tracking.PNG ADDED

Git LFS Details

  • SHA256: aff1af877227be214664c67ce332cb383e57bedc476f4779162d4fab06712166
  • Pointer size: 131 Bytes
  • Size of remote file: 844 kB
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ gradio>=4.0.0
2
+ trimesh
3
+ plotly
4
+ numpy
5
+ scipy