Spaces:
mashroo
/
Runtime error

YoussefAnso commited on
Commit
2053232
·
1 Parent(s): 44c19b3

Refactor texture baking in vertex_color_to_uv_textured_glb function to use a hybrid approach for barycentric calculations. This change enhances accuracy while maintaining performance, replacing vectorized operations with a loop-based method for improved precision in texture generation.

Browse files
Files changed (1) hide show
  1. inference.py +17 -41
inference.py CHANGED
@@ -21,13 +21,11 @@ def vertex_color_to_uv_textured_glb(obj_path, glb_path, texture_size=512):
21
  vertex_colors = vertex_colors[vmapping]
22
  mesh.vertices = vertices
23
  mesh.faces = indices
24
- # Bake texture (vectorized)
25
  buffer_size = texture_size * 2
26
  texture_buffer = np.zeros((buffer_size, buffer_size, 4), dtype=np.uint8)
27
- # Precompute face data
28
  face_uvs = uvs[mesh.faces]
29
  face_colors = vertex_colors[mesh.faces]
30
- # Compute bounding boxes for all faces
31
  min_xy = np.floor(np.min(face_uvs, axis=1) * (buffer_size - 1)).astype(int)
32
  max_xy = np.ceil(np.max(face_uvs, axis=1) * (buffer_size - 1)).astype(int)
33
  for i in range(len(mesh.faces)):
@@ -35,44 +33,22 @@ def vertex_color_to_uv_textured_glb(obj_path, glb_path, texture_size=512):
35
  c0, c1, c2 = face_colors[i]
36
  min_x, min_y = min_xy[i]
37
  max_x, max_y = max_xy[i]
38
- # Create a grid of pixel coordinates in the bounding box
39
- xs = np.arange(min_x, max_x + 1)
40
- ys = np.arange(min_y, max_y + 1)
41
- xv, yv = np.meshgrid(xs, ys)
42
- pts = np.stack([xv, yv], axis=-1).reshape(-1, 2) + 0.5
43
- # Barycentric test (vectorized)
44
- v0, v1, v2 = uv0 * (buffer_size - 1), uv1 * (buffer_size - 1), uv2 * (buffer_size - 1)
45
- def sign(p1, p2, p3):
46
- return (p1[..., 0] - p3[0]) * (p2[1] - p3[1]) - (p2[0] - p3[0]) * (p1[..., 1] - p3[1])
47
- d1 = sign(pts, v0, v1)
48
- d2 = sign(pts, v1, v2)
49
- d3 = sign(pts, v2, v0)
50
- mask = ~((d1 < 0) | (d2 < 0) | (d3 < 0)) & ~((d1 > 0) & (d2 > 0) & (d3 > 0))
51
- inside_pts = pts[mask]
52
- if len(inside_pts) == 0:
53
- continue
54
- # Barycentric coordinates (vectorized)
55
- def barycentric(p, v0, v1, v2):
56
- v0v1 = v1 - v0
57
- v0v2 = v2 - v0
58
- v0p = p - v0
59
- d00 = np.dot(v0v1, v0v1)
60
- d01 = np.dot(v0v1, v0v2)
61
- d11 = np.dot(v0v2, v0v2)
62
- d20 = np.dot(v0p, v0v1)
63
- d21 = np.dot(v0p, v0v2)
64
- denom = d00 * d11 - d01 * d01
65
- v = (d11 * d20 - d01 * d21) / denom
66
- w = (d00 * d21 - d01 * d20) / denom
67
- u = 1.0 - v - w
68
- return np.clip(u, 0, 1), np.clip(v, 0, 1), np.clip(w, 0, 1)
69
- u, v, w = barycentric(inside_pts, v0, v1, v2)
70
- colors = (u[:, None] * c0 + v[:, None] * c1 + w[:, None] * c2)
71
- xi = inside_pts[:, 0].astype(int)
72
- yi = inside_pts[:, 1].astype(int)
73
- texture_buffer[yi, xi, :3] = np.clip(colors, 0, 255).astype(np.uint8)
74
- texture_buffer[yi, xi, 3] = 255
75
- # Inpainting, filtering, and downsampling
76
  image_bgra = texture_buffer.copy()
77
  mask = (image_bgra[:, :, 3] == 0).astype(np.uint8) * 255
78
  image_bgr = cv2.cvtColor(image_bgra, cv2.COLOR_BGRA2BGR)
 
21
  vertex_colors = vertex_colors[vmapping]
22
  mesh.vertices = vertices
23
  mesh.faces = indices
24
+ # Bake texture (hybrid: per-pixel barycentric for accuracy)
25
  buffer_size = texture_size * 2
26
  texture_buffer = np.zeros((buffer_size, buffer_size, 4), dtype=np.uint8)
 
27
  face_uvs = uvs[mesh.faces]
28
  face_colors = vertex_colors[mesh.faces]
 
29
  min_xy = np.floor(np.min(face_uvs, axis=1) * (buffer_size - 1)).astype(int)
30
  max_xy = np.ceil(np.max(face_uvs, axis=1) * (buffer_size - 1)).astype(int)
31
  for i in range(len(mesh.faces)):
 
33
  c0, c1, c2 = face_colors[i]
34
  min_x, min_y = min_xy[i]
35
  max_x, max_y = max_xy[i]
36
+ for y in range(min_y, max_y + 1):
37
+ for x in range(min_x, max_x + 1):
38
+ p = np.array([x + 0.5, y + 0.5]) / (buffer_size - 1)
39
+ # Barycentric coordinates
40
+ v0, v1, v2 = uv0, uv1, uv2
41
+ denom = (v1[1] - v2[1]) * (v0[0] - v2[0]) + (v2[0] - v1[0]) * (v0[1] - v2[1])
42
+ if denom == 0:
43
+ continue
44
+ u = ((v1[1] - v2[1]) * (p[0] - v2[0]) + (v2[0] - v1[0]) * (p[1] - v2[1])) / denom
45
+ v = ((v2[1] - v0[1]) * (p[0] - v2[0]) + (v0[0] - v2[0]) * (p[1] - v2[1])) / denom
46
+ w = 1 - u - v
47
+ if (u >= 0) and (v >= 0) and (w >= 0):
48
+ color = u * c0 + v * c1 + w * c2
49
+ texture_buffer[y, x, :3] = np.clip(color, 0, 255).astype(np.uint8)
50
+ texture_buffer[y, x, 3] = 255
51
+ # Inpainting, filtering, and downsampling (keep optimized)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  image_bgra = texture_buffer.copy()
53
  mask = (image_bgra[:, :, 3] == 0).astype(np.uint8) * 255
54
  image_bgr = cv2.cvtColor(image_bgra, cv2.COLOR_BGRA2BGR)