Spaces:
Runtime error
Runtime error
| import os | |
| import yaml | |
| import smplx | |
| import torch | |
| from .lib.model.cvae import SMPL2PressureCVAE | |
| class PressureGenerator: | |
| # 静态配置数据 | |
| DATASET_META = { | |
| 'tip': { | |
| 'max_p': 512.0, | |
| 'crop_size': [56, 40], | |
| 'path': "/workspace/zyk/public_data/wzy_opt_dataset_w_feats" | |
| }, | |
| 'pressurepose': { | |
| 'max_p': 100.0, | |
| 'crop_size': [64, 27], | |
| 'path': "/workspace/zyk/public_data/pressurepose/synth" | |
| }, | |
| 'moyo': { | |
| 'max_p': 64.0, | |
| 'crop_size': [110, 37], | |
| 'path': "/workspace/zyk/public_data/moyo" | |
| } | |
| } | |
| def __init__(self, | |
| ckpt_dir="src/generate_utils/lib/ckpt/pressurepose_20251222_180032", | |
| smpl_model_dir="src/smpl_models", | |
| device="cpu"): | |
| """ | |
| 初始化生成器:加载配置、权重和 SMPL 模型。 | |
| """ | |
| self.device = torch.device(device) | |
| self.ckpt_dir = ckpt_dir | |
| self.smpl_model_dir = smpl_model_dir | |
| # 1. 加载配置 | |
| self.cfg = self._load_config() | |
| # 2. 设置数据集相关参数 | |
| dataset_name = self.cfg['dataset']['name'] | |
| if dataset_name not in self.DATASET_META: | |
| raise ValueError(f"Unknown dataset name: {dataset_name}") | |
| self.max_pressure = self.DATASET_META[dataset_name]['max_p'] | |
| self.is_normalized = self.cfg['dataset'].get('normal', False) | |
| # 3. 加载 CVAE 模型 | |
| self.cvae_model = self._load_cvae() | |
| # 4. 加载 SMPL 模型 | |
| self.smpl_model = self._load_smpl() | |
| print(f"Pressure Generator loaded successfully from {self.ckpt_dir}") | |
| def _load_config(self): | |
| config_path = os.path.join(self.ckpt_dir, 'config.yaml') | |
| if not os.path.exists(config_path): | |
| from huggingface_hub import snapshot_download | |
| snapshot_download( | |
| "yolozyk/PaGe", | |
| local_dir="src/generate_utils/lib/ckpt/", | |
| local_dir_use_symlinks=False, | |
| ignore_patterns=["*.safetensors", ".gitattributes"], | |
| ) | |
| with open(config_path, 'r') as f: | |
| return yaml.safe_load(f) | |
| def _load_cvae(self): | |
| model = SMPL2PressureCVAE(self.cfg).to(self.device) | |
| ckpt_path = os.path.join(self.ckpt_dir, 'ckpts', 'best_model.pth') | |
| if not os.path.exists(ckpt_path): | |
| from huggingface_hub import snapshot_download | |
| snapshot_download( | |
| "yolozyk/PaGe", | |
| local_dir="src/generate_utils/lib/ckpt/", | |
| local_dir_use_symlinks=False, | |
| ignore_patterns=["*.safetensors", ".gitattributes"], | |
| ) | |
| checkpoint = torch.load(ckpt_path, map_location=self.device) | |
| model.load_state_dict(checkpoint['model_state_dict']) | |
| model.eval() | |
| return model | |
| def _load_smpl(self): | |
| # 创建 SMPL 模型 (这是一个比较耗时的操作) | |
| smpl = smplx.create( | |
| self.smpl_model_dir, | |
| model_type='smpl', | |
| gender='neutral', | |
| ext='pkl' | |
| ).to(self.device) | |
| return smpl | |
| def generate(self, betas, transl, poses, transfer=False): | |
| """ | |
| 执行推理。 | |
| 输入参数应该是 Tensor, 维度需符合模型要求 (Batch Size, ...)。 | |
| """ | |
| # 确保输入在正确的设备上 | |
| if betas.device != self.device: betas = betas.to(self.device) | |
| if transl.device != self.device: transl = transl.to(self.device) | |
| if poses.device != self.device: poses = poses.to(self.device) | |
| # 1. 获取 SMPL 顶点 (Vertices) | |
| output = self.smpl_model( | |
| betas=betas, | |
| global_orient=poses[:, :3], # 前3位是全局旋转 | |
| body_pose=poses[:, 3:], # 后69位是身体姿态 | |
| transl=transl, | |
| ) | |
| vertices = output.vertices | |
| if transfer: | |
| vertices[:, :, 1] = 1.80 - vertices[:, :, 1] | |
| vertices[:, :, 2] = -vertices[:, :, 2] | |
| # 2. 预测压力图 | |
| pred_pmap = self.cvae_model.inference(vertices) | |
| # 3. 后处理 (反归一化 & 阈值过滤) | |
| if self.is_normalized: | |
| pred_pmap = pred_pmap * self.max_pressure | |
| # 这里的 0.1 是硬编码的阈值,也可以提取为参数 | |
| pred_pmap[pred_pmap < 0.1] = 0 | |
| return pred_pmap | |