Files
SMPLer-X/data/SHAPY/mesh-mesh-intersection/body_measurements/cwh_measurements.py
T
caizhongang 857a3ecbae Init commit
2023-06-15 00:22:11 +08:00

183 lines
6.3 KiB
Python

# -*- coding: utf-8 -*-
# Max-Planck-Gesellschaft zur Förderung der Wissenschaften e.V. (MPG) is
# holder of all proprietary rights on this computer program.
# You can only use this computer program if you have closed
# a license agreement with MPG or you get the right to use the computer
# program from someone who is authorized to grant you that right.
# Any use of the computer program without a valid license is prohibited and
# liable to prosecution.
#
# Copyright©2019 Max-Planck-Gesellschaft zur Förderung
# der Wissenschaften e.V. (MPG). acting on behalf of its Max Planck Institute
# for Intelligent Systems. All rights reserved.
#
# Contact: ps-license@tuebingen.mpg.de
import sys
import os
import os.path as osp
from typing import NewType, Dict
import time
import yaml
import numpy as np
import torch
import torch.nn as nn
import torch.autograd as autograd
# from loguru import logger
from mesh_mesh_intersection import MeshMeshIntersection
from scipy.spatial import ConvexHull
Tensor = NewType('Tensor', torch.Tensor)
class ChestWaistHipsMeasurements(nn.Module):
def __init__(
self, meas_definition_path: str, meas_vertices_path: str,
max_collisions=256,
*args, **kwargs
) -> None:
super(ChestWaistHipsMeasurements, self).__init__()
meas_definition_path = osp.expanduser(
osp.expandvars(meas_definition_path))
meas_vertices_path = osp.expanduser(
osp.expandvars(meas_vertices_path))
assert osp.exists(meas_definition_path), (
'Measurement definition path does not exist:'
f' {meas_definition_path}'
)
assert osp.exists(meas_definition_path), (
'Measurement vertex path does not exist:'
f' {meas_vertices_path}'
)
with open(meas_definition_path, 'r') as f:
measurements_definitions = yaml.load(f)
with open(meas_vertices_path, 'r') as f:
meas_vertices = yaml.load(f)
action = measurements_definitions['CW_p']
chest_periphery_data = meas_vertices[action[0]]
self.chest_face_index = chest_periphery_data['face_idx']
chest_bcs = torch.tensor(
chest_periphery_data['bc'], dtype=torch.float32)
self.register_buffer('chest_bcs', chest_bcs)
action = measurements_definitions['BW_p']
belly_periphery_data = meas_vertices[action[0]]
self.belly_face_index = belly_periphery_data['face_idx']
belly_bcs = torch.tensor(
belly_periphery_data['bc'], dtype=torch.float32)
self.register_buffer('belly_bcs', belly_bcs)
action = measurements_definitions['IW_p']
hips_periphery_data = meas_vertices[action[0]]
self.hips_face_index = hips_periphery_data['face_idx']
hips_bcs = torch.tensor(
hips_periphery_data['bc'], dtype=torch.float32)
self.register_buffer('hips_bcs', hips_bcs)
self.isect_module = MeshMeshIntersection(max_collisions=max_collisions)
def _get_plane_at_heights(self, height: Tensor):
device = height.device
batch_size = height.shape[0]
verts = torch.tensor(
[[-1., 0, -1], [1, 0, -1], [1, 0, 1], [-1, 0, 1]],
device=device).unsqueeze(dim=0).expand(batch_size, -1, -1).clone()
verts[:, :, 1] = height.reshape(batch_size, -1)
faces = torch.tensor([[0, 1, 2], [0, 2, 3]], device=device,
dtype=torch.long)
return verts, faces, verts[:, faces]
def forward(
self,
triangles: Tensor
) -> Dict[str, Tensor]:
'''
Parameters
----------
triangles: BxFx3x3 torch.Tensor
Contains the triangle coordinates for a batch of meshes with
the same topology
'''
batch_size, num_triangles = triangles.shape[:2]
device = triangles.device
batch_indices = torch.arange(
batch_size, dtype=torch.long,
device=device).reshape(-1, 1) * num_triangles
meas_data = {
'chest': (self.chest_face_index, self.chest_bcs),
'belly': (self.belly_face_index, self.belly_bcs),
'hips': (self.hips_face_index, self.hips_bcs),
}
output = {}
for name, (face_index, bcs) in meas_data.items():
vertex = (
triangles[:, face_index] * bcs.reshape(1, 3, 1)).sum(axis=1)
_, _, plane_tris = self._get_plane_at_heights(vertex[:, 1])
with torch.no_grad():
collision_faces, collision_bcs = self.isect_module(
plane_tris, triangles)
selected_triangles = triangles.view(-1, 3, 3)[
(collision_faces + batch_indices).view(-1)].reshape(
batch_size, -1, 3, 3)
points = (
selected_triangles[:, :, None] *
collision_bcs[:, :, :, :, None]).sum(
axis=-2).reshape(batch_size, -1, 2, 3)
np_points = points.detach().cpu().numpy()
collision_faces = collision_faces.detach().cpu().numpy()
collision_bcs = collision_bcs.detach().cpu().numpy()
output[name] = {
'points': [],
'valid_points': [],
'value': [],
'plane_height': vertex[:, 1],
}
for ii in range(batch_size):
valid_face_idxs = np.where(collision_faces[ii] > 0)[0]
points_in_plane = np_points[
ii, valid_face_idxs, :, ][:, :, [0, 2]].reshape(
-1, 2)
hull = ConvexHull(points_in_plane)
point_indices = hull.simplices.reshape(-1)
hull_points = points[ii][valid_face_idxs].view(
-1, 3)[point_indices]
meas_value = (
hull_points[1::2] - hull_points[:-1:2]).pow(2).sum(
dim=-1).sqrt().sum()
# logger.info(f'{ii}: {name}, {meas_value}')
output[name]['valid_points'].append(
np_points[ii, valid_face_idxs])
output[name]['points'].append(hull_points)
output[name]['value'].append(meas_value)
# values.append(
# )
return output