import gradio as gr import subprocess import os import shutil import uuid import base64 import numpy as np from plyfile import PlyData, PlyElement from urllib.parse import quote STATIC_DIR = "/tmp/sharp_static" os.makedirs(STATIC_DIR, exist_ok=True) # 库文件路径(Docker 镜像中已下载) GAUSSIAN_SPLATS_JS = "/app/static/gaussian-splats-3d.module.js" def convert_to_binary_ply(input_path, output_path): """将 PLY 转为二进制格式,并统一属性为 float32""" plydata = PlyData.read(input_path) vert = plydata['vertex'] dtype = vert.data.dtype names = dtype.names new_dtype = [(name, np.float32) for name in names] old_data = vert.data new_data = np.zeros(old_data.shape, dtype=new_dtype) for name in names: new_data[name] = old_data[name].astype(np.float32) new_vert = PlyElement.describe(new_data, 'vertex') elements = [new_vert] for el in plydata.elements: if el.name != 'vertex': elements.append(el) PlyData(elements, text=False).write(output_path) def sharp_predict(image, enable_3d_preview): input_dir = "/tmp/sharp_input" output_dir = "/tmp/sharp_output" os.makedirs(input_dir, exist_ok=True) os.makedirs(output_dir, exist_ok=True) input_path = os.path.join(input_dir, "input.png") image.save(input_path) result = subprocess.run( ["sharp", "predict", "-i", input_dir, "-o", output_dir, "-c", "/app/checkpoints/sharp_2572gikvuh.pt"], cwd="/app/ml-sharp", capture_output=True, text=True, timeout=1800 ) if result.returncode != 0: raise gr.Error(f"SHARP 运行失败:{result.stderr}") ply_files = [f for f in os.listdir(output_dir) if f.endswith(".ply")] if not ply_files: raise gr.Error("未生成 .ply 文件") orig_ply = os.path.join(output_dir, ply_files[0]) unique_name = f"model_{uuid.uuid4().hex[:8]}.ply" dest_path = os.path.join(STATIC_DIR, unique_name) convert_to_binary_ply(orig_ply, dest_path) # 公网文件 URL(用于 SuperSplat 跳转) space_host = "satosakura-sharp.hf.space" # 请确认是你的域名 file_url = f"/file={dest_path}" full_url = f"https://{space_host}{file_url}" supersplat_url = f"https://playcanvas.com/supersplat/editor?content={quote(full_url)}" # 准备 HTML 说明(总是显示) info_html = f"""
""" # 如果启用了 3D 预览,生成自包含 HTML 文件 viewer_html_path = None if enable_3d_preview: # 读取模型数据 with open(dest_path, "rb") as f: ply_bytes = f.read() ply_b64 = base64.b64encode(ply_bytes).decode("utf-8") # 读取渲染库 if os.path.exists(GAUSSIAN_SPLATS_JS): with open(GAUSSIAN_SPLATS_JS, "rb") as f: js_bytes = f.read() js_code = js_bytes.decode("utf-8") else: js_code = "" # 构建自包含 HTML viewer_html_content = f"""
📁 下方“下载交互式查看器”可下载自包含的 HTML 文件,
双击即可在本地浏览器中实时旋转/缩放模型(利用本地 GPU)。