pytexrecon / app.py
adsfda's picture
Update app.py
da98f58 verified
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)