mambazjp's picture
Upload 82 files
8870024
raw
history blame
3.51 kB
"""
Copyright 2016 Max Planck Society, Federica Bogo, Angjoo Kanazawa. All rights reserved.
This software is provided for research purposes only.
By using this software you agree to the terms of the SMPLify license here:
http://smplify.is.tue.mpg.de/license
This script implements the interpenetration error term. It uses the capsule
approximation provided in capsule_body.py, and is differentiable with respect
to body shape and pose.
"""
import numpy as np
import chumpy as ch
from vendor.smpl.lbs import verts_core
from capsule_body import get_capsules, set_sphere_centers,\
get_sphere_bweights, collisions,\
capsule_dist
class SphereCollisions(ch.Ch):
dterms = ('pose', 'betas')
terms = ('regs', 'model')
def update_capsules_and_centers(self):
centers = [set_sphere_centers(capsule) for capsule in self.capsules]
count = 0
for capsule in self.capsules:
capsule.center_id = count
count += len(capsule.centers)
self.sph_vs = ch.vstack(centers)
self.sph_weights = get_sphere_bweights(self.sph_vs, self.capsules)
self.ids0 = []
self.ids1 = []
self.radiuss = []
self.caps_pairs = []
for collision in collisions:
if hasattr(self, 'no_hands'):
(id0, id1, rd) = capsule_dist(
self.capsules[collision[0]],
self.capsules[collision[1]],
increase_hand=False)
else:
(id0, id1, rd) = capsule_dist(self.capsules[collision[0]],
self.capsules[collision[1]])
self.ids0.append(id0.r)
self.ids1.append(id1.r)
self.radiuss.append(rd)
self.caps_pairs.append(['%02d_%02d' % (collision[0], collision[1])]
* len(id0))
self.ids0 = np.concatenate(self.ids0).astype(int)
self.ids1 = np.concatenate(self.ids1).astype(int)
self.radiuss = np.concatenate(self.radiuss)
self.caps_pairs = np.concatenate(self.caps_pairs)
assert (self.caps_pairs.size == self.ids0.size)
assert (self.radiuss.size == self.ids0.size)
def update_pose(self):
self.sph_v = verts_core(
self.pose,
self.sph_vs,
self.model.J,
self.sph_weights,
self.model.kintree_table,
want_Jtr=False)
def get_objective(self):
return ch.sum((ch.exp(
-((ch.sum((self.sph_v[self.ids0] - self.sph_v[self.ids1])**2,
axis=1)) / (self.radiuss)) / 2.))**2)**.5
def compute_r(self):
return self.get_objective().r
def compute_dr_wrt(self, wrt):
# we consider derivatives only with respect to pose here,
# to avoid bias towards thin body shapes
if wrt is self.pose:
return self.get_objective().dr_wrt(wrt)
def on_changed(self, which):
if 'regs' in which:
self.length_regs = self.regs['betas2lens']
self.rad_regs = self.regs['betas2rads']
if 'betas' in which:
if not hasattr(self, 'capsules'):
self.capsules = get_capsules(
self.model,
wrt_betas=self.betas,
length_regs=self.length_regs,
rad_regs=self.rad_regs)
self.update_capsules_and_centers()
if 'pose' in which:
self.update_pose()