adsfda commited on
Commit
744ff8d
·
1 Parent(s): 615ac66

fix: fix app

Browse files
Files changed (1) hide show
  1. app.py +129 -86
app.py CHANGED
@@ -1,17 +1,34 @@
1
  import gradio as gr
2
- import pytexrecon # 导入你之前的pytexrecon封装
3
  import numpy as np
4
  from PIL import Image
5
  import io
6
  from typing import Dict, Tuple, Optional
7
 
8
 
9
- def generate_test_data() -> Tuple[bytes, Dict[str, bytes], str, Dict[str, str]]:
 
10
  """
11
- 生成TexRecon测试所需的模拟数据(无需真上传
12
- 返回:(网格文件二进制, 图像字典, 内参字符串, 姿态字典)
13
  """
14
- # 1. 模拟网格数据:最小化PLY格式文件(一个三角形面,3个顶点)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  ply_content = """ply
16
  format ascii 1.0
17
  element vertex 3
@@ -26,59 +43,42 @@ end_header
26
  0.5 1.0 0.0
27
  3 0 1 2
28
  """
29
- mesh_bytes = ply_content.encode("utf-8") # 转为二进制,符合pytexrecon输入要求
30
 
31
- # 2. 模拟图像数据:2张64x64纯色图像(红+蓝色,避免空文件
32
  images: Dict[str, bytes] = {}
33
- # 第一张图:红色
34
  red_img = Image.new("RGB", (64, 64), color="red")
35
- red_img_byteio = io.BytesIO()
36
- red_img.save(red_img_byteio, format="PNG")
37
- images["test1.png"] = red_img_byteio.getvalue()
38
- # 第二张图:蓝色
39
  blue_img = Image.new("RGB", (64, 64), color="blue")
40
- blue_img_byteio = io.BytesIO()
41
- blue_img.save(blue_img_byteio, format="PNG")
42
- images["test2.png"] = blue_img_byteio.getvalue()
43
 
44
- # 3. 模拟相机内参:简单针孔相机参数(适配64x64图像)
45
- # 格式:相机ID fx fy cx cy k1 k2 p1 p2 (k1-k2为畸变系数,p1-p2为切向畸变,此处设为0)
46
- intrinsics = "0 32.0 32.0 32.0 32.0 0.0 0.0 0.0 0.0"
47
 
48
- # 4. 模拟相机姿态:2个图像对应的简单位姿(单位矩阵,代表相机在原点
49
- # 姿态格式:4x4齐次变换矩阵(每行用空格分隔,最后一行固定为0 0 0 1)
50
  pose_matrix = """1.0 0.0 0.0 0.0
51
  0.0 1.0 0.0 0.0
52
- 0.0 0.0 1.0 2.0 # 相机在z轴2m处,朝向原点
53
  0.0 0.0 0.0 1.0"""
54
- poses: Dict[str, str] = {
55
- "test1.png": pose_matrix, # 第一张图的姿态
56
- "test2.png": pose_matrix # 第二张图的姿态(简化用同一姿态)
57
- }
58
 
59
  return mesh_bytes, images, intrinsics, poses
60
 
61
 
62
- def test_texrecon_flow(verbose: bool = True) -> Tuple[str, Optional[bytes], Optional[bytes], Optional[Image.Image]]:
63
- """
64
- 完整测试pytexrecon流程生成模拟数据 → 调用TexRecon → 返回结果
65
- 返回:(测试状态, 带纹理型二进制, 纹理图二进制, 纹理图PIL对象)
66
- """
67
  try:
68
- # 步骤1:生成模拟测试数据
69
- if verbose:
70
- print("=== 步骤1:生成模拟测试数据 ===")
71
- mesh_data, images, intrinsics, poses = generate_test_data()
72
-
73
- # 步骤2:初始化pytexrecon(自动检查/编译TexRecon)
74
- if verbose:
75
- print("=== 步骤2:初始化pytexrecon ===")
76
- texrecon = pytexrecon.TexRecon(verbose=verbose)
77
-
78
- # 步骤3:调用TexRecon纹理重建(核心测试)
79
- if verbose:
80
- print("=== 步骤3:调用TexRecon纹理重建 ===")
81
- textured_mesh_bytes, texture_bytes = texrecon.run_texturing(
82
  mesh_data=mesh_data,
83
  images=images,
84
  intrinsics=intrinsics,
@@ -86,74 +86,117 @@ def test_texrecon_flow(verbose: bool = True) -> Tuple[str, Optional[bytes], Opti
86
  texture_resolution=256, # 小分辨率加速测试
87
  fill_holes=True
88
  )
 
 
 
 
 
89
 
90
- # 步骤4:处理纹理图(转为PIL对象,方便Gradio显示)
91
- texture_img = Image.open(io.BytesIO(texture_bytes)) if texture_bytes else None
92
 
93
- # 步骤5返回成功结果
94
- status = (
95
- "✅ 全流程测试成功!\n"
96
- "- TexRecon可执行文件正常已找到/编译\n"
97
- "- 模拟数据生成正常\n"
98
- "- 纹理重建命令执行功\n"
99
- "- 已生成带纹理模型和纹理图"
100
- )
101
- return status, textured_mesh_bytes, texture_bytes, texture_img
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
 
103
  except Exception as e:
104
- # 捕获所有异常,返回错误信息
105
  status = f"❌ 测试失败:\n{str(e)}"
106
- return status, None, None, None
107
 
 
 
 
 
 
 
 
108
 
109
- # 构建Gradio界面:一键测试+结果展示
110
- with gr.Blocks(title="pytexrecon 模拟测试工具") as demo:
111
- gr.Markdown("# pytexrecon 全流程模拟测试")
112
- gr.Markdown("无需上传真实数据,点击按钮即可测试封装是否正常工作(自动生成模拟数据)")
113
 
114
  with gr.Row():
115
- # 测试按钮(点击触发全流程
116
- test_btn = gr.Button("🚀 开始模拟测试", variant="primary", size="lg")
117
 
118
- # 结果展示区域
119
  with gr.Group():
120
- gr.Markdown("### 测试状态")
121
- status_box = gr.Textbox(label="状态日志", lines=5, interactive=False)
122
 
123
- gr.Markdown("### 输出结果预览")
 
 
 
124
  with gr.Row():
125
- # 纹理图预览(可视化验证)
126
- texture_preview = gr.Image(label="生成的纹理图", interactive=False)
127
- # 带纹理模型下载(验证文件是否正常生成)
128
  mesh_download = gr.File(label="下载带纹理模型(.obj)", interactive=False)
129
- # 纹理图下载
130
  texture_download = gr.File(label="下载纹理图(.png)", interactive=False)
131
 
132
- # 绑定按钮事件:点击后跑测试,更新结果
133
  def on_test_click():
134
- status, mesh_bytes, texture_bytes, texture_img = test_texrecon_flow()
135
- # 处理下载文件(Gradio需要文件路径或二进制+文件名)
 
 
 
 
 
136
  mesh_file = gr.File.update(
137
  value=mesh_bytes,
138
- label="下载带纹理模型(.obj",
139
- file_name="test_textured_mesh.obj"
140
  ) if mesh_bytes else gr.File.update(value=None, label="下载带纹理模型(.obj)")
141
 
142
- texture_file = gr.File.update(
143
- value=texture_bytes,
144
- label="下载纹理图(.png",
145
- file_name="test_texture.png"
146
- ) if texture_bytes else gr.File.update(value=None, label="下载纹理图(.png)")
147
-
148
- return status, mesh_file, texture_file, texture_img
 
 
 
 
 
 
 
 
149
 
150
- # 绑定点击事件(无入,直接触发
151
  test_btn.click(
152
  fn=on_test_click,
153
- outputs=[status_box, mesh_download, texture_download, texture_preview]
 
 
 
 
 
 
 
154
  )
155
 
156
 
157
- # 启动应用(适配Hugging Face Space,默认使用0.0.0.0地址
158
  if __name__ == "__main__":
159
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
1
  import gradio as gr
2
+ import pytexrecon # 导入你的pytexrecon封装
3
  import numpy as np
4
  from PIL import Image
5
  import io
6
  from typing import Dict, Tuple, Optional
7
 
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
33
  format ascii 1.0
34
  element vertex 3
 
43
  0.5 1.0 0.0
44
  3 0 1 2
45
  """
46
+ mesh_bytes = ply_content.encode("utf-8")
47
 
48
+ # 2. 模拟2张64x64纯色图像(红+蓝)
49
  images: Dict[str, bytes] = {}
50
+ # 红色图像
51
  red_img = Image.new("RGB", (64, 64), color="red")
52
+ red_byteio = io.BytesIO()
53
+ red_img.save(red_byteio, format="PNG")
54
+ images["test1.png"] = red_byteio.getvalue()
55
+ # 蓝色图像
56
  blue_img = Image.new("RGB", (64, 64), color="blue")
57
+ blue_byteio = io.BytesIO()
58
+ blue_img.save(blue_byteio, format="PNG")
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" # 相机ID fx fy cx cy k1 k2 p1 p2
 
63
 
64
+ # 4. 模拟相机姿态(单位矩阵,相机在z轴2m处
 
65
  pose_matrix = """1.0 0.0 0.0 0.0
66
  0.0 1.0 0.0 0.0
67
+ 0.0 0.0 1.0 2.0
68
  0.0 0.0 0.0 1.0"""
69
+ poses = {"test1.png": pose_matrix, "test2.png": pose_matrix}
 
 
 
70
 
71
  return mesh_bytes, images, intrinsics, poses
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,
 
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:
93
+ raise RuntimeError(f"纹理重建执行失败:\n{str(e)}")
94
 
 
 
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
108
+ texture_bytes = None
109
+ texture_img = None
110
+
111
+ try:
112
+ # 步骤1:优先初始化TexRecon(核心验证)
113
+ texrecon_instance = init_texrecon()
114
+ status += "✅ 步骤1/3:TexRecon实例初始化成功!\n"
115
+ status += f"- 可执行文件路径:{texrecon_instance.texrecon_path}\n"
116
+
117
+ # 步骤2+3:生成数据并执行纹理重建
118
+ textured_mesh_bytes, texture_bytes, texture_img = run_texturing_with_test_data(texrecon_instance)
119
+ status += "✅ 步骤2/3:模拟测试数据生成成功!\n"
120
+ status += "✅ 步骤3/3:纹理重建执行成功!\n"
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("🔍 逻辑优化:**先验证TexRecon实例可用性,再执行后续流程**,更早定位核心问题")
134
 
135
+ # 存储TexRecon实例(用gr.State保存,避免重复初始化)
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("### 核心验证结果(TexRecon实例)")
147
+ texrecon_path_box = gr.Textbox(label="TexRecon可执行文件路径", interactive=False, placeholder="初始化成功后显示...")
148
+
149
+ gr.Markdown("### 最终输出结果")
150
  with gr.Row():
151
+ texture_preview = gr.Image(label="纹理图预览", interactive=False, placeholder="重建成功后显示...")
 
 
152
  mesh_download = gr.File(label="下载带纹理模型(.obj)", interactive=False)
 
153
  texture_download = gr.File(label="下载纹理图(.png)", interactive=False)
154
 
155
+ # 绑定按钮事件:分步更新结果
156
  def on_test_click():
157
+ # 执行全流程测试(优先验证实例)
158
+ status, texrecon_inst, mesh_bytes, tex_bytes, tex_img = full_test_flow()
159
+
160
+ # 整理TexRecon实例信息(仅当初始化成功时显示)
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, # 保存实例到State
180
+ texrecon_path, # 显示可执行文件路径
181
+ mesh_file, # 模型下载
182
+ tex_file, # 纹理图下载
183
+ tex_img # 纹理图预览
184
+ )
185
 
186
+ # 绑定输出映射(顺序对应on_test_click的返回值
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
+ # 启动应用(适配Hugging Face Space)
201
  if __name__ == "__main__":
202
  demo.launch(server_name="0.0.0.0", server_port=7860)