Spaces:
Sleeping
Sleeping
fix:gradio version
Browse files
app.py
CHANGED
|
@@ -8,25 +8,19 @@ from typing import Dict, Tuple, Optional
|
|
| 8 |
|
| 9 |
# -------------------------- 核心功能:拆分步骤,优先验证TexRecon实例 --------------------------
|
| 10 |
def init_texrecon(verbose: bool = True) -> pytexrecon.TexRecon:
|
| 11 |
-
"""
|
| 12 |
-
单独初始化TexRecon实例(优先验证核心依赖)
|
| 13 |
-
若初始化失败(如编译失败、可执行文件无效),直接抛出异常
|
| 14 |
-
"""
|
| 15 |
if verbose:
|
| 16 |
print("=== 步骤1/3:初始化TexRecon实例(优先验证) ===")
|
| 17 |
try:
|
| 18 |
-
# 调用pytexrecon的构造函数,内部会自动检查/编译TexRecon
|
| 19 |
texrecon_instance = pytexrecon.TexRecon(verbose=verbose)
|
| 20 |
-
# 额外验证一次可执行文件(双重保险)
|
| 21 |
texrecon_instance._check_texrecon()
|
| 22 |
return texrecon_instance
|
| 23 |
except Exception as e:
|
| 24 |
-
# 明确标注是“初始化失败”,方便定位
|
| 25 |
raise RuntimeError(f"TexRecon实例初始化失败(核心依赖问题):\n{str(e)}")
|
| 26 |
|
| 27 |
|
| 28 |
def generate_test_data() -> Tuple[bytes, Dict[str, bytes], str, Dict[str, str]]:
|
| 29 |
-
"""生成TexRecon
|
| 30 |
print("=== 步骤2/3:生成模拟测试数据 ===")
|
| 31 |
# 1. 模拟PLY网格(3个顶点+1个三角形面)
|
| 32 |
ply_content = """ply
|
|
@@ -59,7 +53,7 @@ end_header
|
|
| 59 |
images["test2.png"] = blue_byteio.getvalue()
|
| 60 |
|
| 61 |
# 3. 模拟相机内参(针孔相机,适配64x64图像)
|
| 62 |
-
intrinsics = "0 32.0 32.0 32.0 32.0 0.0 0.0 0.0 0.0"
|
| 63 |
|
| 64 |
# 4. 模拟相机姿态(单位矩阵,相机在z轴2m处)
|
| 65 |
pose_matrix = """1.0 0.0 0.0 0.0
|
|
@@ -72,21 +66,18 @@ end_header
|
|
| 72 |
|
| 73 |
|
| 74 |
def run_texturing_with_test_data(texrecon_instance: pytexrecon.TexRecon) -> Tuple[bytes, bytes, Image.Image]:
|
| 75 |
-
"""用模拟数据调用TexRecon
|
| 76 |
print("=== 步骤3/3:执行纹理重建 ===")
|
| 77 |
-
# 生成模拟数据
|
| 78 |
mesh_data, images, intrinsics, poses = generate_test_data()
|
| 79 |
try:
|
| 80 |
-
# 调用pytexrecon的核心功能
|
| 81 |
textured_mesh_bytes, texture_bytes = texrecon_instance.run_texturing(
|
| 82 |
mesh_data=mesh_data,
|
| 83 |
images=images,
|
| 84 |
intrinsics=intrinsics,
|
| 85 |
poses=poses,
|
| 86 |
-
texture_resolution=256,
|
| 87 |
fill_holes=True
|
| 88 |
)
|
| 89 |
-
# 转换纹理图为PIL对象(用于预览)
|
| 90 |
texture_img = Image.open(io.BytesIO(texture_bytes))
|
| 91 |
return textured_mesh_bytes, texture_bytes, texture_img
|
| 92 |
except Exception as e:
|
|
@@ -95,13 +86,7 @@ def run_texturing_with_test_data(texrecon_instance: pytexrecon.TexRecon) -> Tupl
|
|
| 95 |
|
| 96 |
# -------------------------- 测试流程:分步执行,优先验证实例 --------------------------
|
| 97 |
def full_test_flow() -> Tuple[str, Optional[pytexrecon.TexRecon], Optional[bytes], Optional[bytes], Optional[Image.Image]]:
|
| 98 |
-
"""
|
| 99 |
-
完整测试流程(分步反馈):
|
| 100 |
-
1. 优先初始化TexRecon实例(验证核心依赖)
|
| 101 |
-
2. 生成模拟数据
|
| 102 |
-
3. 执行纹理重建
|
| 103 |
-
返回:(状态日志, TexRecon实例, 带纹理模型, 纹理图, 纹理图预览)
|
| 104 |
-
"""
|
| 105 |
status = ""
|
| 106 |
texrecon_instance = None
|
| 107 |
textured_mesh_bytes = None
|
|
@@ -121,82 +106,71 @@ def full_test_flow() -> Tuple[str, Optional[pytexrecon.TexRecon], Optional[bytes
|
|
| 121 |
status += "- 已生成带纹理模型(.obj)和纹理图(.png)\n"
|
| 122 |
|
| 123 |
except Exception as e:
|
| 124 |
-
# 捕获不同阶段的错误,明确标注
|
| 125 |
status = f"❌ 测试失败:\n{str(e)}"
|
| 126 |
|
| 127 |
return status, texrecon_instance, textured_mesh_bytes, texture_bytes, texture_img
|
| 128 |
|
| 129 |
|
| 130 |
-
# -------------------------- Gradio
|
| 131 |
with gr.Blocks(title="pytexrecon 分步测试工具") as demo:
|
| 132 |
gr.Markdown("# pytexrecon 全流程测试(优先验证TexRecon)")
|
| 133 |
-
gr.Markdown("🔍
|
| 134 |
|
| 135 |
-
# 存储TexRecon
|
| 136 |
texrecon_state = gr.State(None)
|
| 137 |
|
| 138 |
with gr.Row():
|
| 139 |
test_btn = gr.Button("🚀 开始全流程测试", variant="primary", size="lg")
|
| 140 |
|
| 141 |
-
#
|
| 142 |
with gr.Group():
|
| 143 |
-
gr.Markdown("###
|
| 144 |
status_box = gr.Textbox(label="状态", lines=8, interactive=False, placeholder="点击���试按钮开始...")
|
| 145 |
|
| 146 |
-
gr.Markdown("###
|
| 147 |
-
texrecon_path_box = gr.Textbox(label="
|
| 148 |
|
| 149 |
-
gr.Markdown("###
|
| 150 |
with gr.Row():
|
| 151 |
-
texture_preview = gr.Image(label="纹理图预览", interactive=False
|
| 152 |
-
mesh_download = gr.File(label="
|
| 153 |
-
texture_download = gr.File(label="
|
| 154 |
|
| 155 |
-
#
|
| 156 |
def on_test_click():
|
| 157 |
-
# 执行全流程测试(优先验证实例)
|
| 158 |
status, texrecon_inst, mesh_bytes, tex_bytes, tex_img = full_test_flow()
|
| 159 |
-
|
| 160 |
-
#
|
| 161 |
texrecon_path = texrecon_inst.texrecon_path if texrecon_inst else "未初始化"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 162 |
|
| 163 |
-
# 整理下载文件(仅当重建成功时提供)
|
| 164 |
-
mesh_file = gr.File.update(
|
| 165 |
-
value=mesh_bytes,
|
| 166 |
-
file_name="test_textured_mesh.obj",
|
| 167 |
-
label="下载带纹理模型(.obj)"
|
| 168 |
-
) if mesh_bytes else gr.File.update(value=None, label="下载带纹理模型(.obj)")
|
| 169 |
-
|
| 170 |
-
tex_file = gr.File.update(
|
| 171 |
-
value=tex_bytes,
|
| 172 |
-
file_name="test_texture.png",
|
| 173 |
-
label="下载纹理图(.png)"
|
| 174 |
-
) if tex_bytes else gr.File.update(value=None, label="下载纹理图(.png)")
|
| 175 |
-
|
| 176 |
-
# 更新界面状态
|
| 177 |
return (
|
| 178 |
-
status,
|
| 179 |
-
texrecon_inst,
|
| 180 |
-
texrecon_path,
|
| 181 |
-
mesh_file,
|
| 182 |
-
|
| 183 |
-
tex_img
|
| 184 |
)
|
| 185 |
|
| 186 |
-
#
|
| 187 |
test_btn.click(
|
| 188 |
fn=on_test_click,
|
| 189 |
outputs=[
|
| 190 |
-
status_box,
|
| 191 |
-
texrecon_state,
|
| 192 |
-
texrecon_path_box,
|
| 193 |
-
mesh_download,
|
| 194 |
-
texture_download,
|
| 195 |
-
texture_preview
|
| 196 |
]
|
| 197 |
)
|
| 198 |
|
| 199 |
|
| 200 |
-
#
|
| 201 |
if __name__ == "__main__":
|
| 202 |
-
demo.launch(server_name="0.0.0.0", server_port=7860)
|
|
|
|
| 8 |
|
| 9 |
# -------------------------- 核心功能:拆分步骤,优先验证TexRecon实例 --------------------------
|
| 10 |
def init_texrecon(verbose: bool = True) -> pytexrecon.TexRecon:
|
| 11 |
+
"""单独初始化TexRecon实例(优先验证核心依赖)"""
|
|
|
|
|
|
|
|
|
|
| 12 |
if verbose:
|
| 13 |
print("=== 步骤1/3:初始化TexRecon实例(优先验证) ===")
|
| 14 |
try:
|
|
|
|
| 15 |
texrecon_instance = pytexrecon.TexRecon(verbose=verbose)
|
|
|
|
| 16 |
texrecon_instance._check_texrecon()
|
| 17 |
return texrecon_instance
|
| 18 |
except Exception as e:
|
|
|
|
| 19 |
raise RuntimeError(f"TexRecon实例初始化失败(核心依赖问题):\n{str(e)}")
|
| 20 |
|
| 21 |
|
| 22 |
def generate_test_data() -> Tuple[bytes, Dict[str, bytes], str, Dict[str, str]]:
|
| 23 |
+
"""生成TexRecon测试所需的模拟数据"""
|
| 24 |
print("=== 步骤2/3:生成模拟测试数据 ===")
|
| 25 |
# 1. 模拟PLY网格(3个顶点+1个三角形面)
|
| 26 |
ply_content = """ply
|
|
|
|
| 53 |
images["test2.png"] = blue_byteio.getvalue()
|
| 54 |
|
| 55 |
# 3. 模拟相机内参(针孔相机,适配64x64图像)
|
| 56 |
+
intrinsics = "0 32.0 32.0 32.0 32.0 0.0 0.0 0.0 0.0"
|
| 57 |
|
| 58 |
# 4. 模拟相机姿态(单位矩阵,相机在z轴2m处)
|
| 59 |
pose_matrix = """1.0 0.0 0.0 0.0
|
|
|
|
| 66 |
|
| 67 |
|
| 68 |
def run_texturing_with_test_data(texrecon_instance: pytexrecon.TexRecon) -> Tuple[bytes, bytes, Image.Image]:
|
| 69 |
+
"""用模拟数据调用TexRecon纹理重建"""
|
| 70 |
print("=== 步骤3/3:执行纹理重建 ===")
|
|
|
|
| 71 |
mesh_data, images, intrinsics, poses = generate_test_data()
|
| 72 |
try:
|
|
|
|
| 73 |
textured_mesh_bytes, texture_bytes = texrecon_instance.run_texturing(
|
| 74 |
mesh_data=mesh_data,
|
| 75 |
images=images,
|
| 76 |
intrinsics=intrinsics,
|
| 77 |
poses=poses,
|
| 78 |
+
texture_resolution=256,
|
| 79 |
fill_holes=True
|
| 80 |
)
|
|
|
|
| 81 |
texture_img = Image.open(io.BytesIO(texture_bytes))
|
| 82 |
return textured_mesh_bytes, texture_bytes, texture_img
|
| 83 |
except Exception as e:
|
|
|
|
| 86 |
|
| 87 |
# -------------------------- 测试流程:分步执行,优先验证实例 --------------------------
|
| 88 |
def full_test_flow() -> Tuple[str, Optional[pytexrecon.TexRecon], Optional[bytes], Optional[bytes], Optional[Image.Image]]:
|
| 89 |
+
"""完整测试流程(分步反馈)"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
status = ""
|
| 91 |
texrecon_instance = None
|
| 92 |
textured_mesh_bytes = None
|
|
|
|
| 106 |
status += "- 已生成带纹理模型(.obj)和纹理图(.png)\n"
|
| 107 |
|
| 108 |
except Exception as e:
|
|
|
|
| 109 |
status = f"❌ 测试失败:\n{str(e)}"
|
| 110 |
|
| 111 |
return status, texrecon_instance, textured_mesh_bytes, texture_bytes, texture_img
|
| 112 |
|
| 113 |
|
| 114 |
+
# -------------------------- Gradio界面:修复File.update()错误 --------------------------
|
| 115 |
with gr.Blocks(title="pytexrecon 分步测试工具") as demo:
|
| 116 |
gr.Markdown("# pytexrecon 全流程测试(优先验证TexRecon)")
|
| 117 |
+
gr.Markdown("🔍 已修复Gradio兼容性问题,支持最新版本")
|
| 118 |
|
| 119 |
+
# 存储TexRecon实例
|
| 120 |
texrecon_state = gr.State(None)
|
| 121 |
|
| 122 |
with gr.Row():
|
| 123 |
test_btn = gr.Button("🚀 开始全流程测试", variant="primary", size="lg")
|
| 124 |
|
| 125 |
+
# 结果展示区域
|
| 126 |
with gr.Group():
|
| 127 |
+
gr.Markdown("### 测试状态日志")
|
| 128 |
status_box = gr.Textbox(label="状态", lines=8, interactive=False, placeholder="点击���试按钮开始...")
|
| 129 |
|
| 130 |
+
gr.Markdown("### TexRecon可执行文件路径")
|
| 131 |
+
texrecon_path_box = gr.Textbox(label="路径", interactive=False, placeholder="初始化成功后显示...")
|
| 132 |
|
| 133 |
+
gr.Markdown("### 输出结果")
|
| 134 |
with gr.Row():
|
| 135 |
+
texture_preview = gr.Image(label="纹理图预览", interactive=False)
|
| 136 |
+
mesh_download = gr.File(label="带纹理模型(.obj)")
|
| 137 |
+
texture_download = gr.File(label="纹理图(.png)")
|
| 138 |
|
| 139 |
+
# 绑定按钮事件:使用新的更新方式(移除.update())
|
| 140 |
def on_test_click():
|
|
|
|
| 141 |
status, texrecon_inst, mesh_bytes, tex_bytes, tex_img = full_test_flow()
|
| 142 |
+
|
| 143 |
+
# 1. 处理TexRecon路径显示
|
| 144 |
texrecon_path = texrecon_inst.texrecon_path if texrecon_inst else "未初始化"
|
| 145 |
+
|
| 146 |
+
# 2. 处理文件下载组件(直接返回值,不使用.update())
|
| 147 |
+
# 对于文件组件,直接返回 (数据, 文件名) 元组或None
|
| 148 |
+
mesh_file = (mesh_bytes, "test_textured_mesh.obj") if mesh_bytes else None
|
| 149 |
+
texture_file = (tex_bytes, "test_texture.png") if tex_bytes else None
|
| 150 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
return (
|
| 152 |
+
status,
|
| 153 |
+
texrecon_inst,
|
| 154 |
+
texrecon_path,
|
| 155 |
+
mesh_file,
|
| 156 |
+
texture_file,
|
| 157 |
+
tex_img
|
| 158 |
)
|
| 159 |
|
| 160 |
+
# 绑定输出映射
|
| 161 |
test_btn.click(
|
| 162 |
fn=on_test_click,
|
| 163 |
outputs=[
|
| 164 |
+
status_box,
|
| 165 |
+
texrecon_state,
|
| 166 |
+
texrecon_path_box,
|
| 167 |
+
mesh_download,
|
| 168 |
+
texture_download,
|
| 169 |
+
texture_preview
|
| 170 |
]
|
| 171 |
)
|
| 172 |
|
| 173 |
|
| 174 |
+
# 启动应用
|
| 175 |
if __name__ == "__main__":
|
| 176 |
+
demo.launch(server_name="0.0.0.0", server_port=7860)
|