Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -475,10 +475,22 @@ def render_single_frame(
|
|
| 475 |
if not np.isfinite(verts).all():
|
| 476 |
blank = np.ones((frame_height, frame_width, 3), dtype=np.uint8) * 200
|
| 477 |
return blank
|
| 478 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 479 |
# Create scene
|
| 480 |
scene = pyrender.Scene(bg_color=bg_color, ambient_light=[0.4, 0.4, 0.4])
|
| 481 |
-
|
| 482 |
# Material
|
| 483 |
material = pyrender.MetallicRoughnessMaterial(
|
| 484 |
metallicFactor=0.0,
|
|
@@ -486,16 +498,12 @@ def render_single_frame(
|
|
| 486 |
alphaMode='OPAQUE',
|
| 487 |
baseColorFactor=color
|
| 488 |
)
|
| 489 |
-
|
| 490 |
-
# Create mesh
|
| 491 |
-
mesh = trimesh.Trimesh(vertices=
|
| 492 |
mesh_render = pyrender.Mesh.from_trimesh(mesh, material=material, smooth=True)
|
| 493 |
scene.add(mesh_render)
|
| 494 |
|
| 495 |
-
# Compute center for camera positioning
|
| 496 |
-
mesh_center = verts.mean(axis=0)
|
| 497 |
-
camera_target = fixed_center if fixed_center is not None else mesh_center
|
| 498 |
-
|
| 499 |
# Camera setup
|
| 500 |
camera = pyrender.IntrinsicsCamera(
|
| 501 |
fx=focal_length, fy=focal_length,
|
|
@@ -503,21 +511,13 @@ def render_single_frame(
|
|
| 503 |
znear=0.1, zfar=20.0
|
| 504 |
)
|
| 505 |
|
| 506 |
-
# Camera pose:
|
| 507 |
-
#
|
| 508 |
-
# This matches visualize.py and ensures proper face visibility
|
| 509 |
camera_pose = np.eye(4)
|
| 510 |
camera_pose[0, 3] = camera_target[0] # Center X
|
| 511 |
-
camera_pose[1, 3] = camera_target[1] # Center Y
|
| 512 |
-
camera_pose[2, 3] = camera_target[2]
|
| 513 |
-
|
| 514 |
-
# Camera orientation: flip to look at subject (SOKE-style)
|
| 515 |
-
# This rotation makes camera look toward +Z (at the subject)
|
| 516 |
-
camera_pose[:3, :3] = np.array([
|
| 517 |
-
[1, 0, 0],
|
| 518 |
-
[0, -1, 0],
|
| 519 |
-
[0, 0, -1]
|
| 520 |
-
])
|
| 521 |
|
| 522 |
scene.add(camera, pose=camera_pose)
|
| 523 |
|
|
@@ -619,12 +619,16 @@ def render_video(
|
|
| 619 |
# Apply rotation to all frames
|
| 620 |
# (T, V, 3) dot (3, 3) -> (T, V, 3)
|
| 621 |
verts = np.matmul(verts, rot_matrix[:3, :3].T)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 622 |
# Trim last few frames to remove end-of-sequence artifacts
|
| 623 |
T_total = verts.shape[0]
|
| 624 |
trim_amount = min(8, int(T_total * 0.15))
|
| 625 |
T = max(5, T_total - trim_amount)
|
| 626 |
|
| 627 |
-
# Compute fixed camera target from first frame
|
| 628 |
fixed_center = verts[0].mean(axis=0)
|
| 629 |
|
| 630 |
frames = []
|
|
@@ -664,16 +668,11 @@ def render_comparison_video(
|
|
| 664 |
if not ensure_pyrender():
|
| 665 |
raise RuntimeError("PyRender not available")
|
| 666 |
|
| 667 |
-
# Apply orientation fix
|
| 668 |
verts1 = verts1.copy()
|
| 669 |
verts2 = verts2.copy()
|
| 670 |
-
|
| 671 |
-
|
| 672 |
-
rot_matrix = trimesh.transformations.rotation_matrix(np.radians(180), [1, 0, 0])
|
| 673 |
-
|
| 674 |
-
# Apply to both vertex sets
|
| 675 |
-
verts1 = np.matmul(verts1, rot_matrix[:3, :3].T)
|
| 676 |
-
verts2 = np.matmul(verts2, rot_matrix[:3, :3].T)
|
| 677 |
|
| 678 |
# Match lengths and trim
|
| 679 |
T_total = min(verts1.shape[0], verts2.shape[0])
|
|
@@ -925,4 +924,4 @@ if __name__ == "__main__":
|
|
| 925 |
server_name="0.0.0.0",
|
| 926 |
server_port=7860,
|
| 927 |
share=False
|
| 928 |
-
)
|
|
|
|
| 475 |
if not np.isfinite(verts).all():
|
| 476 |
blank = np.ones((frame_height, frame_width, 3), dtype=np.uint8) * 200
|
| 477 |
return blank
|
| 478 |
+
|
| 479 |
+
# Use vertices as-is (rotation should be applied before calling this function)
|
| 480 |
+
# But if fixed_center is None, we need to compute from unrotated vertices
|
| 481 |
+
# If fixed_center is provided, it should be from rotated vertices
|
| 482 |
+
verts_used = verts.copy()
|
| 483 |
+
|
| 484 |
+
# Compute center for camera positioning
|
| 485 |
+
mesh_center = verts_used.mean(axis=0)
|
| 486 |
+
if fixed_center is not None:
|
| 487 |
+
camera_target = fixed_center
|
| 488 |
+
else:
|
| 489 |
+
camera_target = mesh_center
|
| 490 |
+
|
| 491 |
# Create scene
|
| 492 |
scene = pyrender.Scene(bg_color=bg_color, ambient_light=[0.4, 0.4, 0.4])
|
| 493 |
+
|
| 494 |
# Material
|
| 495 |
material = pyrender.MetallicRoughnessMaterial(
|
| 496 |
metallicFactor=0.0,
|
|
|
|
| 498 |
alphaMode='OPAQUE',
|
| 499 |
baseColorFactor=color
|
| 500 |
)
|
| 501 |
+
|
| 502 |
+
# Create mesh (exactly like compare_vqvae.py)
|
| 503 |
+
mesh = trimesh.Trimesh(vertices=verts_used, faces=faces)
|
| 504 |
mesh_render = pyrender.Mesh.from_trimesh(mesh, material=material, smooth=True)
|
| 505 |
scene.add(mesh_render)
|
| 506 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 507 |
# Camera setup
|
| 508 |
camera = pyrender.IntrinsicsCamera(
|
| 509 |
fx=focal_length, fy=focal_length,
|
|
|
|
| 511 |
znear=0.1, zfar=20.0
|
| 512 |
)
|
| 513 |
|
| 514 |
+
# Camera pose: positioned BEHIND the subject (at +Z), looking at -Z (toward face)
|
| 515 |
+
# This matches compare_vqvae.py exactly
|
|
|
|
| 516 |
camera_pose = np.eye(4)
|
| 517 |
camera_pose[0, 3] = camera_target[0] # Center X
|
| 518 |
+
camera_pose[1, 3] = camera_target[1] # Center Y
|
| 519 |
+
camera_pose[2, 3] = camera_target[2] + camera_distance # BEHIND (positive Z)
|
| 520 |
+
camera_pose[:3, :3] = np.eye(3) # Identity = look at -Z
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 521 |
|
| 522 |
scene.add(camera, pose=camera_pose)
|
| 523 |
|
|
|
|
| 619 |
# Apply rotation to all frames
|
| 620 |
# (T, V, 3) dot (3, 3) -> (T, V, 3)
|
| 621 |
verts = np.matmul(verts, rot_matrix[:3, :3].T)
|
| 622 |
+
# Apply orientation fix: rotate 180 degrees around X-axis (like compare_vqvae.py)
|
| 623 |
+
verts = verts.copy()
|
| 624 |
+
verts[..., 1:] *= -1
|
| 625 |
+
|
| 626 |
# Trim last few frames to remove end-of-sequence artifacts
|
| 627 |
T_total = verts.shape[0]
|
| 628 |
trim_amount = min(8, int(T_total * 0.15))
|
| 629 |
T = max(5, T_total - trim_amount)
|
| 630 |
|
| 631 |
+
# Compute fixed camera target from first frame (using rotated vertices)
|
| 632 |
fixed_center = verts[0].mean(axis=0)
|
| 633 |
|
| 634 |
frames = []
|
|
|
|
| 668 |
if not ensure_pyrender():
|
| 669 |
raise RuntimeError("PyRender not available")
|
| 670 |
|
| 671 |
+
# Apply orientation fix: rotate 180 degrees around X-axis (like compare_vqvae.py)
|
| 672 |
verts1 = verts1.copy()
|
| 673 |
verts2 = verts2.copy()
|
| 674 |
+
verts1[..., 1:] *= -1
|
| 675 |
+
verts2[..., 1:] *= -1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 676 |
|
| 677 |
# Match lengths and trim
|
| 678 |
T_total = min(verts1.shape[0], verts2.shape[0])
|
|
|
|
| 924 |
server_name="0.0.0.0",
|
| 925 |
server_port=7860,
|
| 926 |
share=False
|
| 927 |
+
)
|