Breeze1124 commited on
Commit
304c700
·
1 Parent(s): 8fa9b11
Files changed (1) hide show
  1. app.py +62 -33
app.py CHANGED
@@ -1,66 +1,97 @@
1
  import gradio as gr
2
  import os
3
 
4
- # --- Configuration ---
5
- # 假設你的 .splat 檔案已經放在 "assets_converted" 資料夾中
6
- # 建議將檔案命名為 office0.splat, office2.splat, room0.splat 以保持簡潔
7
  SCENES = [
8
  {
9
  "name": "Office 0",
10
  "thumb": "assets/office0.PNG",
11
- "model": "assets/office0.splat", # <--- 修改處:改成 .splat 檔案
12
  "tracking_img": "assets/office0_tracking.PNG"
13
  },
14
  {
15
  "name": "Office 2",
16
  "thumb": "assets/office2.PNG",
17
- "model": "assets/office2.splat", # <--- 修改處
18
  "tracking_img": "assets/office2_tracking.PNG"
19
  },
20
  {
21
  "name": "Room 0",
22
  "thumb": "assets/room0.PNG",
23
- "model": "assets/room0.splat", # <--- 修改處
24
  "tracking_img": "assets/room0_tracking.PNG"
25
  }
26
  ]
27
 
28
- # 建立 Gallery 用清單
29
  gallery_items = [(item["thumb"], item["name"]) for item in SCENES]
30
 
31
- def load_scene(evt: gr.SelectData):
32
  """
33
- 載入選定的場景。
34
- Gradio Model3D 元件會根據副檔名 (.splat) 自動切換渲染模式。
35
  """
36
  index = evt.index
37
  scene = SCENES[index]
38
 
39
- # 檢查檔案是否存在,避免報錯讓使用者困惑
40
- if not os.path.exists(scene["model"]):
 
41
  return (
 
42
  None,
43
- scene["tracking_img"] if os.path.exists(scene["tracking_img"]) else None,
44
- f"**⚠️ Error: File not found: {scene['model']}**\n請確認 .splat 檔案已上傳至正確路徑。"
45
  )
46
 
47
- # 計算檔案大小供顯示
48
- file_size = os.path.getsize(scene["model"]) / (1024 * 1024)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  return (
51
- scene["model"],
52
  scene["tracking_img"],
53
- f"**{scene['name']}** ({file_size:.1f} MB) ✓ Loaded (.splat)"
54
  )
55
 
56
  # --- UI ---
57
  with gr.Blocks(title="RGS-SLAM Demo") as demo:
58
 
59
  gr.Markdown("# 🚀 RGS-SLAM Gaussian Splatting Viewer")
60
- gr.Markdown("此檢視器使用 `.splat` 格式,載入速度更快且相容性更高。")
61
 
62
  with gr.Row():
63
- # 左側選單
64
  with gr.Column(scale=1):
65
  gr.Markdown("### 📂 Select Scene")
66
  scene_gallery = gr.Gallery(
@@ -69,30 +100,28 @@ with gr.Blocks(title="RGS-SLAM Demo") as demo:
69
  columns=1,
70
  height=400,
71
  object_fit="contain",
72
- allow_preview=False # 關閉點擊預覽圖片,強制觸發選擇事件
73
  )
74
 
75
- # 右側顯示區
76
  with gr.Column(scale=3):
77
- status = gr.Markdown("**👈 Select a scene from the left to load**")
78
 
79
- with gr.Tab("🎯 3D Reconstruction"):
80
- # Model3D 支援 .splat, .ply, .glb 等格式
81
- model_viewer = gr.Model3D(
82
- label="3D Gaussian Splat",
83
- clear_color=[0.0, 0.0, 0.0, 1.0], # 建議 splat 使用黑色背景
84
- height=600,
85
- interactive=True
86
  )
87
 
88
  with gr.Tab("📍 Camera Trajectory"):
89
  trajectory_img = gr.Image(label="Camera Path", height=600)
90
 
91
- # 事件綁定
92
  scene_gallery.select(
93
  fn=load_scene,
94
- outputs=[model_viewer, trajectory_img, status]
 
95
  )
96
 
97
  if __name__ == "__main__":
98
- demo.launch()
 
 
 
1
  import gradio as gr
2
  import os
3
 
4
+ # 獲取當前絕對路徑,確保讀取檔案無誤
5
+ BASE_DIR = os.path.abspath(os.getcwd())
6
+
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
+ def load_scene(evt: gr.SelectData, request: gr.Request):
31
  """
32
+ 載入選定的場景並生成自動播放的 iframe 連結
33
+ request: 用來獲取當前 Gradio 的網址 (localhost share link)
34
  """
35
  index = evt.index
36
  scene = SCENES[index]
37
 
38
+ full_model_path = os.path.join(BASE_DIR, scene["model"])
39
+
40
+ if not os.path.exists(full_model_path):
41
  return (
42
+ "<div style='text-align:center; padding:50px'>⚠️ File not found</div>",
43
  None,
44
+ f"**⚠️ Error:** File not found: {scene['model']}"
 
45
  )
46
 
47
+ # 1. 取得你目前的 Gradio 伺服器網址 (例如 https://xxxx.gradio.live 或 http://127.0.0.1:7860)
48
+ # 注意:如果是在本地跑且沒有 share=True,這個網址通常是 http
49
+ if request:
50
+ host = request.headers.get("host") # e.g. "7213...gradio.live"
51
+ # 判斷是 http 還是 https (Gradio Share 連結通常是 https)
52
+ protocol = "https" if "gradio.live" in host else "http"
53
+ base_url = f"{protocol}://{host}"
54
+ else:
55
+ base_url = "http://127.0.0.1:7860"
56
+
57
+ # 2. 組合檔案的下載連結 (Gradio 的 /file/ 路徑)
58
+ # 注意 Windows路徑的反斜線可能需要處理,但在 Gradio file serving 通常沒問題
59
+ file_url = f"{base_url}/file={full_model_path}"
60
+
61
+ # 3. 組合外部 Viewer 的連結 (利用 ?url= 參數)
62
+ viewer_url = f"https://antimatter15.com/splat/?url={file_url}"
63
 
64
+ print(f"🔗 Generated Link: {viewer_url}") # Debug 用,可以在終端機看到連結
65
+
66
+ # 4. 生成 HTML
67
+ html = f"""
68
+ <iframe
69
+ src="{viewer_url}"
70
+ width="100%"
71
+ height="600px"
72
+ frameborder="0"
73
+ allow="camera; gpu"
74
+ style="border-radius: 8px; background: #000;"
75
+ ></iframe>
76
+ """
77
+
78
+ # 提示訊息
79
+ status_msg = f"**{scene['name']}** - Auto-loading via External Viewer..."
80
+ if protocol == "http":
81
+ status_msg += "\n\n⚠️ **Note:** If screen is black, use `share=True` (see explanation)."
82
+
83
  return (
84
+ html,
85
  scene["tracking_img"],
86
+ status_msg
87
  )
88
 
89
  # --- UI ---
90
  with gr.Blocks(title="RGS-SLAM Demo") as demo:
91
 
92
  gr.Markdown("# 🚀 RGS-SLAM Gaussian Splatting Viewer")
 
93
 
94
  with gr.Row():
 
95
  with gr.Column(scale=1):
96
  gr.Markdown("### 📂 Select Scene")
97
  scene_gallery = gr.Gallery(
 
100
  columns=1,
101
  height=400,
102
  object_fit="contain",
103
+ allow_preview=False
104
  )
105
 
 
106
  with gr.Column(scale=3):
107
+ status = gr.Markdown("**👈 Select a scene to auto-load**")
108
 
109
+ with gr.Tab("🎯 3D Viewer"):
110
+ # 初始狀態為空
111
+ viewer_frame = gr.HTML(
112
+ value="<div style='text-align: center; padding: 100px; color: #666;'>Select a scene</div>"
 
 
 
113
  )
114
 
115
  with gr.Tab("📍 Camera Trajectory"):
116
  trajectory_img = gr.Image(label="Camera Path", height=600)
117
 
 
118
  scene_gallery.select(
119
  fn=load_scene,
120
+ inputs=None, # inputs 不需要顯式傳入,gr.SelectData 會自動處理
121
+ outputs=[viewer_frame, trajectory_img, status]
122
  )
123
 
124
  if __name__ == "__main__":
125
+ # 關鍵:allowed_paths 允許 Gradio 讀取當前資料夾的檔案
126
+ # 建議開啟 share=True 以解決 HTTPS 跨域問題
127
+ demo.launch(share=True, allowed_paths=[BASE_DIR])