PressureGen / src /generate_utils /generate.py
yolozyk's picture
Update src/generate_utils/generate.py
d24edb6 verified
Raw
History Blame Contribute Delete
4.54 kB
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
@torch.no_grad()
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