smplify-x笔记

SMPL模型

关节点定义如下图
smplify-x笔记_第1张图片

每个不同的2d数据集都会涉及到joint_mapper,即re-order the SMPL joints to some other convention, 例如coco数据集。

from .vertex_ids import vertex_ids as VERTEX_IDS
if vertex_ids is None:
	# SMPL and SMPL-H share the same topology, so any extra joints can be drawn from the same place.
	vertex_ids = VERTEX_IDS['smplh']
self.vertex_joint_selector = VertexJointSelector(vertex_ids=vertex_ids, **kwargs)
joints = self.vertex_joint_selector(vertices, joints)
# Map the joints to the current dataset
if self.joint_mapper is not None:
	joints = self.joint_mapper(joints)
vertex_ids = {
	'smplh': {
		'nose': 332, 'reye': 6260, 'leye': 2800, 'rear': 4071, 'lear': 583, 'rthumb': 6191, 'rindex': 5782,
		'rmiddle': 5905, 'rring': 6016, 'rpinky': 6133, 'lthumb': 2746, 'lindex': 2319, 'lmiddle': 2445, 'lring': 2556,
		'lpinky': 2673, 'LBigToe': 3216, 'LSmallToe': 3326, 'LHeel': 3387, 'RBigToe': 6617, 'RSmallToe': 6624,
		'RHeel': 6787
	},
	'smplx': {
		'nose': 9120, 'reye': 9929, 'leye': 9448, 'rear': 616, 'lear': 6, 'rthumb': 8079, 'rindex': 7669, 
		'rmiddle': 7794, 'rring': 7905, 'rpinky': 8022, 'lthumb': 5361, 'lindex': 4933, 'lmiddle': 5058, 'lring': 5169,
		'lpinky': 5286, 'LBigToe': 5770, 'LSmallToe': 5780, 'LHeel': 8846, 'RBigToe': 8463, 'RSmallToe': 8474,
		'RHeel': 8635
	},
	'mano': {
		'thumb': 744, 'index': 320, 'middle': 443, 'ring': 554, 'pinky': 671
	}

看了下VertexJointsSelector,其中的逻辑就是在官方定义的joints基础上,从组成mesh的vertexes中再挑选出若干有实质语义的点,补充进joints中,接在后面。默认会把面部的nose, reye, leye, rear, lear五点补充进去,再选择把哪些点补充进去,就取决于初始化参数。当use_feet_keypoints为True时,会把脚部6点补充进去。当use_hands为True时,会把手部10点补充进去。

官方定义的joints,

SMPL: NUM_BODY_JOINTS = 23, NUM_JOINTS = 23
SMPLH: NUM_BODY_JOINTS = 21, NUM_HAND_JOINTS = 15, NUM_JOINTS = NUM_BODY_JOINTS + 2 * NUM_HAND_JOINTS = 51
SMPLX: NUM_BODY_JOINTS = 21, NUM_HAND_JOINTS = 15, NUM_FACE_JOINTS = 3, NUM_JOINTS = NUM_BODY_JOINTS + 2 * NUM_HAND_JOINTS + NUM_FACE_JOINTS = 54

FLAME模型

FLAME:Faces Learned with an Articulated Model and Expressions,是头部模型,有68个landmarks,前17个landmark为人脸轮廓点,后51个landmark为人脸内部关键点。

openpose模型

smplify-x用到了openpose的body/face/hand三个部分的点位,生成json结果的结构化定义如下。body为25点,具体点位定义如下图所示。hand分左右手,每只手21个关键点,face用的是FLAME模型的68点位。
smplify-x笔记_第2张图片

"people": [{
	"pose_keypoint_2d": [25*3],
	"hand_left_keypoints_2d": [20*3],
	"hand_right_keypoints_2d": [20*3],
	"face_keypoints_2d": [68*3],
	"gender_pd":,
	"gender_gt":,
}]

想要将smpl/smplh/smplx模型的joints映射为openpose的点位格式时,index的映射关系如下

if model_type == 'smpl':
	return np.array([24, 12, 17, 19, 21, 16, 18, 20, 0, 2, 5, 8, 1, 4,
                     7, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34], dtype=np.int32)
elif model_type == 'smplh':
	mapping = [body_mapping, lhand_mapping, rhand_mapping]
elif model_type == 'smplx':
	mapping = [body_mapping, lhand_mapping, rhand_mapping, face_mapping]

相机模型

class PerspectiveCamera(nn.Module):
	def __init__(self, rotation=None, translation=None,
					focal_length_x=None, focal_length_y=None, batch_size=1,
					center=None, dtype=torch.float32, **kwargs):
		rotation = nn.Parameter(rotation, requires_grad=True)
		translation = nn.Parameters(translation, requires_grad=True)
	def forward(self, points):

创建一个透视变换相机,初始化参数为rotation旋转矩阵,translation平移向量,focal_length_x x方向焦距,focal_length_y y方向焦距,batch_size相机个数,center相平面的中心坐标。如果没主动设置,默认焦距为5000。
在这个相机模型里,需要梯度的有rotation,translation。前向部分,完成3d点投影的工作。主要是根据rotation和translation将坐标从世界坐标系转至相机坐标系,再根据相机投影矩阵,将坐标从相机坐标系转换至像素坐标系。

训练损失

E ( β , θ , ψ ) = E J ( β , θ ; K , J e s t ) + E θ b ( θ b ) + E θ f ( θ f ) + E θ h ( θ h ) + E α ( θ b ) + E β ( β ) + E ε ( ψ ) + E ς ( β , θ , ψ ) \begin{aligned} E(\beta, \theta, \psi) &= E_J(\beta, \theta; K, J_{est}) \\ &+ E_{\theta_b}(\theta_b) + E_{\theta_f}(\theta_f) + E_{\theta_h}(\theta_h) + E_{\alpha}(\theta_b) \\ &+ E_{\beta}(\beta) + E_\varepsilon(\psi) \\ &+ E_{\varsigma}(\beta, \theta, \psi) \end{aligned} E(β,θ,ψ)=EJ(β,θ;K,Jest)+Eθb(θb)+Eθf(θf)+Eθh(θh)+Eα(θb)+Eβ(β)+Eε(ψ)+Eς(β,θ,ψ)
第1个data_term是关节点2d投影误差,K是相机投影矩阵。第2~5是Pose Priors, 第6~7是Shape和Expression Priors,最后一个是interpenetration penalty。

你可能感兴趣的:(smpl,python,机器学习,人工智能)