RealDenseFace / engine.py
LinzhouLi's picture
Update RealDenseFace image reconstruction demo (part 3)
7826761 verified
Raw History Blame Contribute Delete
3.34 kB
"""Inference adapters shared by the Gradio app and local verification."""
import gc
from pathlib import Path
import time
import common.fix_chumpy # noqa: F401
import numpy as np
import torch
from camera import PerspectiveCamera
from common.config import (FLAMEConfig, FaceBoxConfig, RealDenseFaceInferenceConfig,
GNFlameOptimizerConfig, load_fitting_config)
from tracker import RealDenseFaceInferencer, GNFlameOptimizer
from visualization import Visualizer
class ReconstructionEngine:
def __init__(self, root: Path, model_weights: str, facebox_weights: str, flame_assets: str, flame_model: str):
self.root = root
self.flame = FLAMEConfig(flame_model_path=flame_model, flame_assets_path=flame_assets)
self.inferencer = RealDenseFaceInferencer(
RealDenseFaceInferenceConfig(
model_config_path=str(root / "configs/model/vitb.yaml"),
model_weights_path=model_weights, flame=self.flame,
compile_model=False, defer_native_context=True,
), FaceBoxConfig(model_weights_path=facebox_weights),
)
self.fitting_config = load_fitting_config(root / "configs/fitting/single_image.yaml", GNFlameOptimizerConfig,
flame=self.flame, device="cuda")
@torch.inference_mode()
def reconstruct(self, image: np.ndarray):
started = time.perf_counter()
# Preserve the official pipeline's bbox refinement and fallback: some
# heavily occluded teaser faces are missed by the separate detector.
inference = self.inferencer.infer_image(image, face_bbox=None)
optimizer = None
visualizer = None
try:
optimizer = GNFlameOptimizer(self.fitting_config)
fit = optimizer.fit_frame(inference, camera=None)
vertices, _ = optimizer.decode(fit)
if not torch.isfinite(vertices).all().item():
raise RuntimeError("Fitting produced non-finite vertices")
camera = PerspectiveCamera(
fov_y=np.radians(float(fit.camera_fov_y)),
rot=self.fitting_config.camera_rotation, pos=self.fitting_config.camera_position,
width=image.shape[1], height=image.shape[0],
)
visualizer = Visualizer(flame_assets_path=self.flame.flame_assets_path)
dense = visualizer.vis_align(image, inference.vertex_coord)
dense = visualizer.vis_contour(dense, inference.vertex_coord)
overlay, mesh = visualizer.vis_flame_shading_overlay(camera, image, vertices, return_shading=True)
torch.cuda.synchronize()
return dense, overlay, mesh, {
"seconds": round(time.perf_counter() - started, 3),
"gpu": torch.cuda.get_device_name(0),
"fov_y": float(fit.camera_fov_y),
"vertices": int(vertices.shape[0]),
}
finally:
torch.cuda.synchronize()
if optimizer is not None:
ops = optimizer.solver_ops.extension
ops.destroy_cublas_handle(optimizer.solver_context.cublas_handle)
ops.destroy_cusolver_handle(optimizer.solver_context.cusolver_handle)
del optimizer, visualizer
gc.collect()