Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import pytexrecon # 导入你的pytexrecon封装 | |
| import numpy as np | |
| from PIL import Image | |
| import io | |
| from typing import Dict, Tuple, Optional | |
| # -------------------------- 核心功能:拆分步骤,优先验证TexRecon实例 -------------------------- | |
| def init_texrecon(verbose: bool = True) -> pytexrecon.TexRecon: | |
| """单独初始化TexRecon实例(优先验证核心依赖)""" | |
| if verbose: | |
| print("=== 步骤1/3:初始化TexRecon实例(优先验证) ===") | |
| texrecon_instance = pytexrecon.TexRecon(verbose=verbose) | |
| texrecon_instance._check_texrecon() | |
| return texrecon_instance | |
| def generate_test_data() -> Tuple[bytes, Dict[str, bytes], str, Dict[str, str]]: | |
| """生成TexRecon测试所需的模拟数据""" | |
| print("=== 步骤2/3:生成模拟测试数据 ===") | |
| # 1. 模拟PLY网格(3个顶点+1个三角形面) | |
| ply_content = """ply | |
| format ascii 1.0 | |
| element vertex 3 | |
| property float x | |
| property float y | |
| property float z | |
| element face 1 | |
| property list uchar int vertex_indices | |
| end_header | |
| 0.0 0.0 0.0 | |
| 1.0 0.0 0.0 | |
| 0.5 1.0 0.0 | |
| 3 0 1 2 | |
| """ | |
| mesh_bytes = ply_content.encode("utf-8") | |
| # 2. 模拟2张64x64纯色图像(红+蓝) | |
| images: Dict[str, bytes] = {} | |
| # 红色图像 | |
| red_img = Image.new("RGB", (64, 64), color="red") | |
| red_byteio = io.BytesIO() | |
| red_img.save(red_byteio, format="PNG") | |
| images["test1.png"] = red_byteio.getvalue() | |
| # 蓝色图像 | |
| blue_img = Image.new("RGB", (64, 64), color="blue") | |
| blue_byteio = io.BytesIO() | |
| blue_img.save(blue_byteio, format="PNG") | |
| images["test2.png"] = blue_byteio.getvalue() | |
| # 3. 模拟相机内参(针孔相机,适配64x64图像) | |
| intrinsics = "0 32.0 32.0 32.0 32.0 0.0 0.0 0.0 0.0" | |
| # 4. 模拟相机姿态(单位矩阵,相机在z轴2m处) | |
| pose_matrix = """1.0 0.0 0.0 0.0 | |
| 0.0 1.0 0.0 0.0 | |
| 0.0 0.0 1.0 2.0 | |
| 0.0 0.0 0.0 1.0""" | |
| poses = {"test1.png": pose_matrix, "test2.png": pose_matrix} | |
| return mesh_bytes, images, intrinsics, poses | |
| def run_texturing_with_test_data(texrecon_instance: pytexrecon.TexRecon) -> Tuple[bytes, bytes, Image.Image]: | |
| """用模拟数据调用TexRecon纹理重建""" | |
| print("=== 步骤3/3:执行纹理重建 ===") | |
| mesh_data, images, intrinsics, poses = generate_test_data() | |
| try: | |
| textured_mesh_bytes, texture_bytes = texrecon_instance.run_texturing( | |
| mesh_data=mesh_data, | |
| images=images, | |
| intrinsics=intrinsics, | |
| poses=poses, | |
| texture_resolution=256, | |
| fill_holes=True | |
| ) | |
| texture_img = Image.open(io.BytesIO(texture_bytes)) | |
| return textured_mesh_bytes, texture_bytes, texture_img | |
| except Exception as e: | |
| raise RuntimeError(f"纹理重建执行失败:\n{str(e)}") | |
| # -------------------------- 测试流程:分步执行,优先验证实例 -------------------------- | |
| def full_test_flow() -> Tuple[str, Optional[pytexrecon.TexRecon], Optional[bytes], Optional[bytes], Optional[Image.Image]]: | |
| """完整测试流程(分步反馈)""" | |
| status = "" | |
| texrecon_instance = None | |
| textured_mesh_bytes = None | |
| texture_bytes = None | |
| texture_img = None | |
| try: | |
| # 步骤1:优先初始化TexRecon(核心验证) | |
| texrecon_instance = init_texrecon() | |
| status += "✅ 步骤1/3:TexRecon实例初始化成功!\n" | |
| status += f"- 可执行文件路径:{texrecon_instance.texrecon_path}\n" | |
| # 步骤2+3:生成数据并执行纹理重建 | |
| textured_mesh_bytes, texture_bytes, texture_img = run_texturing_with_test_data(texrecon_instance) | |
| status += "✅ 步骤2/3:模拟测试数据生成成功!\n" | |
| status += "✅ 步骤3/3:纹理重建执行成功!\n" | |
| status += "- 已生成带纹理模型(.obj)和纹理图(.png)\n" | |
| except Exception as e: | |
| status = f"❌ 测试失败:\n{str(e)}" | |
| return status, texrecon_instance, textured_mesh_bytes, texture_bytes, texture_img | |
| # -------------------------- Gradio界面:修复File.update()错误 -------------------------- | |
| with gr.Blocks(title="pytexrecon 分步测试工具") as demo: | |
| gr.Markdown("# pytexrecon 全流程测试(优先验证TexRecon)") | |
| gr.Markdown("🔍 已修复Gradio兼容性问题,支持最新版本") | |
| # 存储TexRecon实例 | |
| texrecon_state = gr.State(None) | |
| with gr.Row(): | |
| test_btn = gr.Button("🚀 开始全流程测试", variant="primary", size="lg") | |
| # 结果展示区域 | |
| with gr.Group(): | |
| gr.Markdown("### 测试状态日志") | |
| status_box = gr.Textbox(label="状态", lines=8, interactive=False, placeholder="点击测试按钮开始...") | |
| gr.Markdown("### TexRecon可执行文件路径") | |
| texrecon_path_box = gr.Textbox(label="路径", interactive=False, placeholder="初始化成功后显示...") | |
| gr.Markdown("### 输出结果") | |
| with gr.Row(): | |
| texture_preview = gr.Image(label="纹理图预览", interactive=False) | |
| mesh_download = gr.File(label="带纹理模型(.obj)") | |
| texture_download = gr.File(label="纹理图(.png)") | |
| # 绑定按钮事件:使用新的更新方式(移除.update()) | |
| def on_test_click(): | |
| status, texrecon_inst, mesh_bytes, tex_bytes, tex_img = full_test_flow() | |
| # 1. 处理TexRecon路径显示 | |
| texrecon_path = texrecon_inst.texrecon_path if texrecon_inst else "未初始化" | |
| # 2. 处理文件下载组件(直接返回值,不使用.update()) | |
| # 对于文件组件,直接返回 (数据, 文件名) 元组或None | |
| mesh_file = (mesh_bytes, "test_textured_mesh.obj") if mesh_bytes else None | |
| texture_file = (tex_bytes, "test_texture.png") if tex_bytes else None | |
| return ( | |
| status, | |
| texrecon_inst, | |
| texrecon_path, | |
| mesh_file, | |
| texture_file, | |
| tex_img | |
| ) | |
| # 绑定输出映射 | |
| test_btn.click( | |
| fn=on_test_click, | |
| outputs=[ | |
| status_box, | |
| texrecon_state, | |
| texrecon_path_box, | |
| mesh_download, | |
| texture_download, | |
| texture_preview | |
| ] | |
| ) | |
| # 启动应用 | |
| if __name__ == "__main__": | |
| demo.launch(server_name="0.0.0.0", server_port=7860) | |