Beispiel #1
0
def sample_VOCA_template(template_fname, model_fname, out_mesh_fname):
    '''
    VOCA animates static templates in FLAME topology. Such templates can be obtained by sampling the FLAME shape space.
    This function randomly samples the FLAME identity shape space to generate new templates.
    :param template_fname:  template mesh in FLAME topology (only the face information are used)
    :param model_fname:     saved FLAME model
    :param out_mesh_fname:  filename of the VOCA template
    :return:
    '''

    template_mesh = Mesh(filename=template_fname)

    tf_trans = tf.Variable(np.zeros((1,3)), name="trans", dtype=tf.float64, trainable=True)
    tf_rot = tf.Variable(np.zeros((1,3)), name="pose", dtype=tf.float64, trainable=True)
    tf_pose = tf.Variable(np.zeros((1,12)), name="pose", dtype=tf.float64, trainable=True)
    tf_shape = tf.Variable(np.zeros((1,300)), name="shape", dtype=tf.float64, trainable=True)
    tf_exp = tf.Variable(np.zeros((1,100)), name="expression", dtype=tf.float64, trainable=True)
    smpl = SMPL(model_fname)
    tf_model = tf.squeeze(smpl(tf_trans,
                               tf.concat((tf_shape, tf_exp), axis=-1),
                               tf.concat((tf_rot, tf_pose), axis=-1)))

    with tf.Session() as session:
        session.run(tf.global_variables_initializer())

        assign_shape = tf.assign(tf_shape, np.hstack((np.random.randn(100), np.zeros(200)))[np.newaxis,:])
        session.run([assign_shape])

        Mesh(session.run(tf_model), template_mesh.f).write_ply(out_mesh_fname)
Beispiel #2
0
def fit_3D_mesh(target_3d_mesh_fname, model_fname, weights, show_fitting=True):
    '''
    Fit FLAME to 3D mesh in correspondence to the FLAME mesh (i.e. same number of vertices, same mesh topology)
    :param target_3d_mesh_fname:    target 3D mesh filename
    :param model_fname:             saved FLAME model
    :param weights:             weights of the individual objective functions
    :return: a mesh with the fitting results
    '''

    target_mesh = Mesh(filename=target_3d_mesh_fname)

    tf_trans = tf.Variable(np.zeros((1,3)), name="trans", dtype=tf.float64, trainable=True)
    tf_rot = tf.Variable(np.zeros((1,3)), name="pose", dtype=tf.float64, trainable=True)
    tf_pose = tf.Variable(np.zeros((1,12)), name="pose", dtype=tf.float64, trainable=True)
    tf_shape = tf.Variable(np.zeros((1,300)), name="shape", dtype=tf.float64, trainable=True)
    tf_exp = tf.Variable(np.zeros((1,100)), name="expression", dtype=tf.float64, trainable=True)
    smpl = SMPL(model_fname)
    tf_model = tf.squeeze(smpl(tf_trans,
                               tf.concat((tf_shape, tf_exp), axis=-1),
                               tf.concat((tf_rot, tf_pose), axis=-1)))

    with tf.Session() as session:
        session.run(tf.global_variables_initializer())

        mesh_dist = tf.reduce_sum(tf.square(tf.subtract(tf_model, target_mesh.v)))
        neck_pose_reg = tf.reduce_sum(tf.square(tf_pose[:,:3]))
        jaw_pose_reg = tf.reduce_sum(tf.square(tf_pose[:,3:6]))
        eyeballs_pose_reg = tf.reduce_sum(tf.square(tf_pose[:,6:]))
        shape_reg = tf.reduce_sum(tf.square(tf_shape))
        exp_reg = tf.reduce_sum(tf.square(tf_exp))

        # Optimize global transformation first
        vars = [tf_trans, tf_rot]
        loss = mesh_dist
        optimizer = scipy_pt(loss=loss, var_list=vars, method='BFGS', options={'disp': 1})
        print('Optimize rigid transformation')
        optimizer.minimize(session)

        # Optimize for the model parameters
        vars = [tf_trans, tf_rot, tf_pose, tf_shape, tf_exp]
        loss = weights['data'] * mesh_dist + weights['shape'] * shape_reg + weights['expr'] * exp_reg + \
               weights['neck_pose'] * neck_pose_reg + weights['jaw_pose'] * jaw_pose_reg + weights['eyeballs_pose'] * eyeballs_pose_reg

        optimizer = scipy_pt(loss=loss, var_list=vars, method='BFGS', options={'disp': 1})
        print('Optimize model parameters')
        optimizer.minimize(session)

        print('Fitting done')

        if show_fitting:
            # Visualize fitting
            mv = MeshViewer()
            fitting_mesh = Mesh(session.run(tf_model), smpl.f)
            fitting_mesh.set_vertex_colors('light sky blue')

            mv.set_static_meshes([target_mesh, fitting_mesh])
            six.moves.input('Press key to continue')

        return Mesh(session.run(tf_model), smpl.f)
Beispiel #3
0
def fit_lmk3d(target_3d_lmks, model_fname, lmk_face_idx, lmk_b_coords, weights, show_fitting=True):
    '''
    Fit FLAME to 3D landmarks
    :param target_3d_lmks:      target 3D landmarks provided as (num_lmks x 3) matrix
    :param model_fname:         saved Tensorflow FLAME model
    :param lmk_face_idx:        face indices of the landmark embedding in the FLAME topology
    :param lmk_b_coords:        barycentric coordinates of the landmark embedding in the FLAME topology
                                (i.e. weighting of the three vertices for the trinagle, the landmark is embedded in
    :param weights:             weights of the individual objective functions
    :return: a mesh with the fitting results
    '''

    tf_trans = tf.Variable(np.zeros((1,3)), name="trans", dtype=tf.float64, trainable=True)
    tf_rot = tf.Variable(np.zeros((1,3)), name="pose", dtype=tf.float64, trainable=True)
    tf_pose = tf.Variable(np.zeros((1,12)), name="pose", dtype=tf.float64, trainable=True)
    tf_shape = tf.Variable(np.zeros((1,300)), name="shape", dtype=tf.float64, trainable=True)
    tf_exp = tf.Variable(np.zeros((1,100)), name="expression", dtype=tf.float64, trainable=True)
    smpl = SMPL(model_fname)
    tf_model = tf.squeeze(smpl(tf_trans,
                               tf.concat((tf_shape, tf_exp), axis=-1),
                               tf.concat((tf_rot, tf_pose), axis=-1)))
    with tf.Session() as session:
        session.run(tf.global_variables_initializer())

        lmks = tf_get_model_lmks(tf_model, smpl.f, lmk_face_idx, lmk_b_coords)
        lmk_dist = tf.reduce_sum(tf.square(1000 * tf.subtract(lmks, target_3d_lmks)))
        neck_pose_reg = tf.reduce_sum(tf.square(tf_pose[:,:3]))
        jaw_pose_reg = tf.reduce_sum(tf.square(tf_pose[:,3:6]))
        eyeballs_pose_reg = tf.reduce_sum(tf.square(tf_pose[:,6:]))
        shape_reg = tf.reduce_sum(tf.square(tf_shape))
        exp_reg = tf.reduce_sum(tf.square(tf_exp))

        # Optimize global transformation first
        vars = [tf_trans, tf_rot]
        loss = weights['lmk'] * lmk_dist
        optimizer = scipy_pt(loss=loss, var_list=vars, method='L-BFGS-B', options={'disp': 1, 'ftol': 5e-6})
        print('Optimize rigid transformation')
        optimizer.minimize(session)

        # Optimize for the model parameters
        vars = [tf_trans, tf_rot, tf_pose, tf_shape, tf_exp]
        loss = weights['lmk'] * lmk_dist + weights['shape'] * shape_reg + weights['expr'] * exp_reg + \
               weights['neck_pose'] * neck_pose_reg + weights['jaw_pose'] * jaw_pose_reg + weights['eyeballs_pose'] * eyeballs_pose_reg

        optimizer = scipy_pt(loss=loss, var_list=vars, method='L-BFGS-B', options={'disp': 1, 'ftol': 5e-6})
        print('Optimize model parameters')
        optimizer.minimize(session)

        print('Fitting done')

        if show_fitting:
            # Visualize landmark fitting
            mv = MeshViewer()
            mv.set_static_meshes(create_lmk_spheres(target_3d_lmks, 0.001, [255.0, 0.0, 0.0]))
            mv.set_dynamic_meshes([Mesh(session.run(tf_model), smpl.f)] + create_lmk_spheres(session.run(lmks), 0.001, [0.0, 0.0, 255.0]), blocking=True)
            six.moves.input('Press key to continue')

        return Mesh(session.run(tf_model), smpl.f)
Beispiel #4
0
def sample_texture(model_fname, texture_fname, num_samples, out_path):
    '''
    Sample the FLAME model to demonstrate how to vary the model parameters.FLAME has parameters to
        - model identity-dependent shape variations (paramters: shape),
        - articulation of neck (paramters: pose[0:3]), jaw (paramters: pose[3:6]), and eyeballs (paramters: pose[6:12])
        - model facial expressions, i.e. all expression motion that does not involve opening the mouth (paramters: exp)
        - global translation (paramters: trans)
        - global rotation (paramters: rot)
    :param model_fname          saved FLAME model
    :param num_samples          number of samples
    :param out_path             output path to save the generated templates (no templates are saved if path is empty)
    '''

    tf_trans = tf.Variable(np.zeros((1,3)), name="trans", dtype=tf.float64, trainable=True)
    tf_rot = tf.Variable(np.zeros((1,3)), name="pose", dtype=tf.float64, trainable=True)
    tf_pose = tf.Variable(np.zeros((1,12)), name="pose", dtype=tf.float64, trainable=True)
    tf_shape = tf.Variable(np.zeros((1,300)), name="shape", dtype=tf.float64, trainable=True)
    tf_exp = tf.Variable(np.zeros((1,100)), name="expression", dtype=tf.float64, trainable=True)
    smpl = SMPL(model_fname)
    tf_model = tf.squeeze(smpl(tf_trans,
                               tf.concat((tf_shape, tf_exp), axis=-1),
                               tf.concat((tf_rot, tf_pose), axis=-1)))

    texture_model = np.load(texture_fname)
    tex_dim = texture_model['tex_dir'].shape[-1]
    tf_tex_params = tf.Variable(np.zeros((1,tex_dim)), name="pose", dtype=tf.float64, trainable=True)
    tf_tex_mean = tf.Variable(np.reshape(texture_model['mean'], (1,-1)), name='tex_mean', dtype=tf.float64, trainable=False)
    tf_tex_dir = tf.Variable(np.reshape(texture_model['tex_dir'], (-1, tex_dim)).T, name='tex_dir', dtype=tf.float64, trainable=False)
    
    tf_tex = tf.add(tf_tex_mean, tf.matmul(tf_tex_params, tf_tex_dir)),
    tf_tex = tf.reshape(tf_tex, (texture_model['tex_dir'].shape[0], texture_model['tex_dir'].shape[1], texture_model['tex_dir'].shape[2]))
    tf_tex = tf.cast(tf.clip_by_value(tf_tex, 0.0, 255.0), tf.int64)

    with tf.Session() as session:
        session.run(tf.global_variables_initializer())
        mv = MeshViewer()

        for i in range(num_samples):
            assign_tex = tf.assign(tf_tex_params, np.random.randn(tex_dim)[np.newaxis,:])
            session.run([assign_tex])

            v, tex = session.run([tf_model, tf_tex])
            out_mesh = Mesh(v, smpl.f)
            out_mesh.vt = texture_model['vt']
            out_mesh.ft = texture_model['ft']

            mv.set_dynamic_meshes([out_mesh], blocking=True)
            key = six.moves.input('Press (s) to save sample, any other key to continue ')
            if key == 's':
                out_mesh_fname = os.path.join(out_path, 'tex_sample_%02d.obj' % (i+1))
                out_tex_fname = out_mesh_fname.replace('obj', 'png')
                cv2.imwrite(out_tex_fname, tex)
                out_mesh.set_texture_image(out_tex_fname)
                out_mesh.write_obj(out_mesh_fname)
Beispiel #5
0
def sample_FLAME(model_fname, num_samples, out_path, visualize, sample_VOCA_template=False):
    '''
    Sample the FLAME model to demonstrate how to vary the model parameters.FLAME has parameters to
        - model identity-dependent shape variations (paramters: shape),
        - articulation of neck (paramters: pose[0:3]), jaw (paramters: pose[3:6]), and eyeballs (paramters: pose[6:12])
        - model facial expressions, i.e. all expression motion that does not involve opening the mouth (paramters: exp)
        - global translation (paramters: trans)
        - global rotation (paramters: rot)
    :param model_fname              saved FLAME model
    :param num_samples              number of samples
    :param out_path                 output path to save the generated templates (no templates are saved if path is empty)
    :param visualize                visualize samples
    :param sample_VOCA_template     sample template in 'zero pose' that can be used e.g. for speech-driven animation in VOCA
    '''

    tf_trans = tf.Variable(np.zeros((1,3)), name="trans", dtype=tf.float64, trainable=True)
    tf_rot = tf.Variable(np.zeros((1,3)), name="pose", dtype=tf.float64, trainable=True)
    tf_pose = tf.Variable(np.zeros((1,12)), name="pose", dtype=tf.float64, trainable=True)
    tf_shape = tf.Variable(np.zeros((1,300)), name="shape", dtype=tf.float64, trainable=True)
    tf_exp = tf.Variable(np.zeros((1,100)), name="expression", dtype=tf.float64, trainable=True)
    smpl = SMPL(model_fname)
    tf_model = tf.squeeze(smpl(tf_trans,
                               tf.concat((tf_shape, tf_exp), axis=-1),
                               tf.concat((tf_rot, tf_pose), axis=-1)))

    with tf.Session() as session:
        session.run(tf.global_variables_initializer())

        if visualize:
            mv = MeshViewer()
        for i in range(num_samples):
            if sample_VOCA_template:
                assign_shape = tf.assign(tf_shape, np.hstack((np.random.randn(100), np.zeros(200)))[np.newaxis,:])
                session.run([assign_shape])
                out_fname = os.path.join(out_path, 'VOCA_template_%02d.ply' % (i+1))
            else:
                # assign_trans = tf.assign(tf_trans, np.random.randn(3)[np.newaxis,:])
                assign_rot = tf.assign(tf_rot, np.random.randn(3)[np.newaxis,:] * 0.03)
                assign_pose = tf.assign(tf_pose, np.random.randn(12)[np.newaxis,:] * 0.02)
                assign_shape = tf.assign(tf_shape, np.hstack((np.random.randn(100), np.zeros(200)))[np.newaxis,:])
                assign_exp = tf.assign(tf_exp, np.hstack((0.5*np.random.randn(50), np.zeros(50)))[np.newaxis,:])
                session.run([assign_rot, assign_pose, assign_shape, assign_exp])
                out_fname = os.path.join(out_path, 'FLAME_sample_%02d.ply' % (i+1))

            sample_mesh = Mesh(session.run(tf_model), smpl.f)
            if visualize:
                mv.set_dynamic_meshes([sample_mesh], blocking=True)
                key = six.moves.input('Press (s) to save sample, any other key to continue ')
                if key == 's':
                    sample_mesh.write_ply(out_fname)
            else:
                sample_mesh.write_ply(out_fname)
Beispiel #6
0
def sample_FLAME(template_fname, model_fname, num_samples):
    '''
    Sample the FLAME model to demonstrate how to vary the model parameters.FLAME has parameters to
        - model identity-dependent shape variations (paramters: shape),
        - articulation of neck (paramters: pose[0:3]), jaw (paramters: pose[3:6]), and eyeballs (paramters: pose[6:12])
        - model facial expressions, i.e. all expression motion that does not involve opening the mouth (paramters: exp)
        - global translation (paramters: trans)
        - global rotation (paramters: rot)
    :param template_fname:      template mesh in FLAME topology (only the face information are used)
    :param model_fname:         saved FLAME model
    '''

    template_mesh = Mesh(filename=template_fname)

    tf_trans = tf.Variable(np.zeros((1,3)), name="trans", dtype=tf.float64, trainable=True)
    tf_rot = tf.Variable(np.zeros((1,3)), name="pose", dtype=tf.float64, trainable=True)
    tf_pose = tf.Variable(np.zeros((1,12)), name="pose", dtype=tf.float64, trainable=True)
    tf_shape = tf.Variable(np.zeros((1,300)), name="shape", dtype=tf.float64, trainable=True)
    tf_exp = tf.Variable(np.zeros((1,100)), name="expression", dtype=tf.float64, trainable=True)
    smpl = SMPL(model_fname)
    tf_model = tf.squeeze(smpl(tf_trans,
                               tf.concat((tf_shape, tf_exp), axis=-1),
                               tf.concat((tf_rot, tf_pose), axis=-1)))

    with tf.Session() as session:
        session.run(tf.global_variables_initializer())

        mv = MeshViewer()

        for i in range(num_samples):
            assign_trans = tf.assign(tf_trans, np.random.randn(3)[np.newaxis,:])
            assign_rot = tf.assign(tf_rot, np.random.randn(3)[np.newaxis,:] * 0.03)
            assign_pose = tf.assign(tf_pose, np.random.randn(12)[np.newaxis,:] * 0.03)
            assign_shape = tf.assign(tf_shape, np.random.randn(300)[np.newaxis,:] * 1.0)
            assign_exp = tf.assign(tf_exp, np.random.randn(100)[np.newaxis,:] * 0.5)
            session.run([assign_trans, assign_rot, assign_pose, assign_shape, assign_exp])

            mv.set_dynamic_meshes([Mesh(session.run(tf_model), template_mesh.f)], blocking=True)
            six.moves.input('Press key to continue')
Beispiel #7
0
def fit_lmk2d(target_img, target_2d_lmks, template_fname, model_fname,
              lmk_face_idx, lmk_b_coords, weights):
    '''
    Fit FLAME to 2D landmarks
    :param target_2d_lmks:      target 2D landmarks provided as (num_lmks x 3) matrix
    :param template_fname:      template mesh in FLAME topology (only the face information are used)
    :param model_fname:         saved FLAME model
    :param lmk_face_idx:        face indices of the landmark embedding in the FLAME topology
    :param lmk_b_coords:        barycentric coordinates of the landmark embedding in the FLAME topology
                                (i.e. weighting of the three vertices for the trinagle, the landmark is embedded in
    :param weights:             weights of the individual objective functions
    :return: a mesh with the fitting results
    '''

    template_mesh = Mesh(filename=template_fname)

    tf_trans = tf.Variable(np.zeros((1, 3)),
                           name="trans",
                           dtype=tf.float64,
                           trainable=True)
    tf_rot = tf.Variable(np.zeros((1, 3)),
                         name="pose",
                         dtype=tf.float64,
                         trainable=True)
    tf_pose = tf.Variable(np.zeros((1, 12)),
                          name="pose",
                          dtype=tf.float64,
                          trainable=True)
    tf_shape = tf.Variable(np.zeros((1, 300)),
                           name="shape",
                           dtype=tf.float64,
                           trainable=True)
    tf_exp = tf.Variable(np.zeros((1, 100)),
                         name="expression",
                         dtype=tf.float64,
                         trainable=True)
    smpl = SMPL(model_fname)
    tf_model = tf.squeeze(
        smpl(tf_trans, tf.concat((tf_shape, tf_exp), axis=-1),
             tf.concat((tf_rot, tf_pose), axis=-1)))

    with tf.Session() as session:
        session.run(tf.global_variables_initializer())

        # Mirror landmark y-coordinates
        target_2d_lmks[:, 1] = target_img.shape[0] - target_2d_lmks[:, 1]

        lmks_3d = tf_get_model_lmks(tf_model, template_mesh, lmk_face_idx,
                                    lmk_b_coords)

        s2d = np.mean(
            np.linalg.norm(target_2d_lmks - np.mean(target_2d_lmks, axis=0),
                           axis=1))
        s3d = tf.reduce_mean(
            tf.sqrt(
                tf.reduce_sum(
                    tf.square(lmks_3d -
                              tf.reduce_mean(lmks_3d, axis=0))[:, :2],
                    axis=1)))
        tf_scale = tf.Variable(s2d / s3d, dtype=lmks_3d.dtype)

        # trans = 0.5*np.array((target_img.shape[0], target_img.shape[1]))/tf_scale
        # trans = 0.5 * s3d * np.array((target_img.shape[0], target_img.shape[1])) / s2d
        lmks_proj_2d = tf_project_points(lmks_3d, tf_scale, np.zeros(2))

        factor = max(
            max(target_2d_lmks[:, 0]) - min(target_2d_lmks[:, 0]),
            max(target_2d_lmks[:, 1]) - min(target_2d_lmks[:, 1]))
        lmk_dist = weights['lmk'] * tf.reduce_sum(
            tf.square(tf.subtract(lmks_proj_2d, target_2d_lmks))) / (factor**2)
        neck_pose_reg = weights['neck_pose'] * tf.reduce_sum(
            tf.square(tf_pose[:3]))
        jaw_pose_reg = weights['jaw_pose'] * tf.reduce_sum(
            tf.square(tf_pose[3:6]))
        eyeballs_pose_reg = weights['eyeballs_pose'] * tf.reduce_sum(
            tf.square(tf_pose[6:]))
        shape_reg = weights['shape'] * tf.reduce_sum(tf.square(tf_shape))
        exp_reg = weights['expr'] * tf.reduce_sum(tf.square(tf_exp))

        session.run(tf.global_variables_initializer())

        def on_step(verts,
                    scale,
                    faces,
                    target_img,
                    target_lmks,
                    opt_lmks,
                    lmk_dist=0.0,
                    shape_reg=0.0,
                    exp_reg=0.0,
                    neck_pose_reg=0.0,
                    jaw_pose_reg=0.0,
                    eyeballs_pose_reg=0.0):
            import cv2
            import sys
            import numpy as np
            from psbody.mesh import Mesh
            from utils.render_mesh import render_mesh

            if lmk_dist > 0.0 or shape_reg > 0.0 or exp_reg > 0.0 or neck_pose_reg > 0.0 or jaw_pose_reg > 0.0 or eyeballs_pose_reg > 0.0:
                print(
                    'lmk_dist: %f, shape_reg: %f, exp_reg: %f, neck_pose_reg: %f, jaw_pose_reg: %f, eyeballs_pose_reg: %f'
                    % (lmk_dist, shape_reg, exp_reg, neck_pose_reg,
                       jaw_pose_reg, eyeballs_pose_reg))

            plt_target_lmks = target_lmks.copy()
            plt_target_lmks[:, 1] = target_img.shape[0] - plt_target_lmks[:, 1]
            for (x, y) in plt_target_lmks:
                cv2.circle(target_img, (int(x), int(y)), 4, (0, 0, 255), -1)

            plt_opt_lmks = opt_lmks.copy()
            plt_opt_lmks[:, 1] = target_img.shape[0] - plt_opt_lmks[:, 1]
            for (x, y) in plt_opt_lmks:
                cv2.circle(target_img, (int(x), int(y)), 4, (255, 0, 0), -1)

            if sys.version_info >= (3, 0):
                rendered_img = render_mesh(Mesh(scale * verts, faces),
                                           height=target_img.shape[0],
                                           width=target_img.shape[1])
                for (x, y) in plt_opt_lmks:
                    cv2.circle(rendered_img, (int(x), int(y)), 4, (255, 0, 0),
                               -1)
                target_img = np.hstack((target_img, rendered_img))

            cv2.imshow('img', target_img)
            cv2.waitKey(10)

        print('Optimize rigid transformation')
        vars = [tf_scale, tf_trans, tf_rot]
        loss = lmk_dist
        optimizer = scipy_pt(loss=loss,
                             var_list=vars,
                             method='L-BFGS-B',
                             options={
                                 'disp': 1,
                                 'ftol': 5e-6
                             })
        optimizer.minimize(session,
                           fetches=[
                               tf_model, tf_scale,
                               tf.constant(template_mesh.f),
                               tf.constant(target_img),
                               tf.constant(target_2d_lmks), lmks_proj_2d
                           ],
                           loss_callback=on_step)

        print('Optimize model parameters')
        vars = [tf_scale, tf_trans[:2], tf_rot, tf_pose, tf_shape, tf_exp]
        loss = lmk_dist + shape_reg + exp_reg + neck_pose_reg + jaw_pose_reg + eyeballs_pose_reg

        optimizer = scipy_pt(loss=loss,
                             var_list=vars,
                             method='L-BFGS-B',
                             options={
                                 'disp': 0,
                                 'ftol': 1e-7
                             })
        optimizer.minimize(session,
                           fetches=[
                               tf_model, tf_scale,
                               tf.constant(template_mesh.f),
                               tf.constant(target_img),
                               tf.constant(target_2d_lmks), lmks_proj_2d,
                               lmk_dist, shape_reg, exp_reg, neck_pose_reg,
                               jaw_pose_reg, eyeballs_pose_reg
                           ],
                           loss_callback=on_step)

        print('Fitting done')
        np_verts, np_scale = session.run([tf_model, tf_scale])

        def _get_verts(expr):
            assign_expr = tf.assign(tf_exp, expr[np.newaxis, :])
            session.run([assign_expr])
            _verts, _scale = session.run([tf_model, tf_scale])
            return _verts

        expr_basis = []
        neutral_verts = _get_verts(np.zeros((100), np.float64))
        for i in range(100):
            expr_i = np.zeros((100), np.float64)
            expr_i[i] = 1
            verts_i = _get_verts(expr_i) - neutral_verts
            expr_basis.append(verts_i.flatten())
        expr_basis = np.asarray(expr_basis, np.float32).transpose(1, 0)

        return Mesh(np_verts, template_mesh.f), np_scale, expr_basis
Beispiel #8
0
import pkg_resources

import tf_smpl
from tf_smpl.batch_smpl import SMPL
from tf_mesh_renderer import mesh_renderer
from pose_3d import utils


if __name__ == '__main__':
    if len(sys.argv) != 2:
        print("Usage: python3 test_runner.py <path-to-SMPL-model>")
        sys.exit()

    dirpath = os.path.dirname(os.path.realpath(__file__))
    smpl_path = os.path.realpath(sys.argv[1])
    smpl_model = SMPL(smpl_path)

    betas = tf.random_normal([1, 10], stddev=0.3)
    thetas = tf.random_normal([1, 72], stddev=0.15)

    verts, _, _ = smpl_model(betas, thetas, get_skin=True)
    verts = verts[0]

    config = tf.ConfigProto()
    config.gpu_options.allow_growth = True  # pylint: disable=no-member
    sess = tf.Session(config=config)
    result = sess.run(verts)

    faces_path = pkg_resources.resource_filename(
        tf_smpl.__name__, 'smpl_faces.npy')
    faces = np.load(faces_path)
Beispiel #9
0
def fit_lmk2d(target_img, target_2d_lmks, model_fname, lmk_face_idx, lmk_b_coords, weights, visualize):
    '''
    Fit FLAME to 2D landmarks
    :param target_2d_lmks      target 2D landmarks provided as (num_lmks x 3) matrix
    :param model_fname         saved FLAME model
    :param lmk_face_idx        face indices of the landmark embedding in the FLAME topology
    :param lmk_b_coords        barycentric coordinates of the landmark embedding in the FLAME topology
                                (i.e. weighting of the three vertices for the trinagle, the landmark is embedded in
    :param weights             weights of the individual objective functions
    :param visualize           visualize fitting progress
    :return: a mesh with the fitting results
    '''

    '''
    pred_types = {'face': pred_type(slice(0, 17), (0.682, 0.780, 0.909, 0.5)),
              'eyebrow1': pred_type(slice(17, 22), (1.0, 0.498, 0.055, 0.4)),
              'eyebrow2': pred_type(slice(22, 27), (1.0, 0.498, 0.055, 0.4)),
              'nose': pred_type(slice(27, 31), (0.345, 0.239, 0.443, 0.4)),
              'nostril': pred_type(slice(31, 36), (0.345, 0.239, 0.443, 0.4)),
              'eye1': pred_type(slice(36, 42), (0.596, 0.875, 0.541, 0.3)),
              'eye2': pred_type(slice(42, 48), (0.596, 0.875, 0.541, 0.3)),
              'lips': pred_type(slice(48, 60), (0.596, 0.875, 0.541, 0.3)),
              'teeth': pred_type(slice(60, 68), (0.596, 0.875, 0.541, 0.4))
              }
    '''

    lmks_weights = [[1,1]] * 68
    for idx in range(36, 48):
      lmks_weights[idx] = [100, 100]

    tf_lmks_weights = tf.constant(
        lmks_weights,
        tf.float64
    )

    tf_trans = tf.Variable(np.zeros((1,3)), name="trans", dtype=tf.float64, trainable=True)
    tf_rot = tf.Variable(np.zeros((1,3)), name="rot", dtype=tf.float64, trainable=True)
    tf_pose = tf.Variable(np.zeros((1,12)), name="pose", dtype=tf.float64, trainable=True)
    tf_shape = tf.Variable(np.zeros((1,300)), name="shape", dtype=tf.float64, trainable=True)
    tf_exp = tf.Variable(np.zeros((1,100)), name="expression", dtype=tf.float64, trainable=True)
    smpl = SMPL(model_fname)
    tf_model = tf.squeeze(smpl(tf_trans,
                               tf.concat((tf_shape, tf_exp), axis=-1),
                               tf.concat((tf_rot, tf_pose), axis=-1)))

    with tf.Session() as session:
        # session.run(tf.global_variables_initializer())

        # Mirror landmark y-coordinates
        target_2d_lmks[:,1] = target_img.shape[0]-target_2d_lmks[:,1]

        lmks_3d = tf_get_model_lmks(tf_model, smpl.f, lmk_face_idx, lmk_b_coords)

        s2d = np.mean(np.linalg.norm(target_2d_lmks-np.mean(target_2d_lmks, axis=0), axis=1))
        s3d = tf.reduce_mean(tf.sqrt(tf.reduce_sum(tf.square(lmks_3d-tf.reduce_mean(lmks_3d, axis=0))[:, :2], axis=1)))
        tf_scale = tf.Variable(s2d/s3d, dtype=lmks_3d.dtype)

        # trans = 0.5*np.array((target_img.shape[0], target_img.shape[1]))/tf_scale
        # trans = 0.5 * s3d * np.array((target_img.shape[0], target_img.shape[1])) / s2d
        lmks_proj_2d = tf_project_points(lmks_3d, tf_scale, np.zeros(2))

        factor = max(max(target_2d_lmks[:,0]) - min(target_2d_lmks[:,0]),max(target_2d_lmks[:,1]) - min(target_2d_lmks[:,1]))
        #lmk_dist = weights['lmk']*tf.reduce_sum(tf.square(tf.subtract(lmks_proj_2d, target_2d_lmks))) / (factor ** 2)
        lmk_dist = weights['lmk']*tf.reduce_sum(
            tf.square(tf.subtract(lmks_proj_2d, target_2d_lmks)) * tf_lmks_weights
        ) / (factor ** 2)

        neck_pose_reg = weights['neck_pose']*tf.reduce_sum(tf.square(tf_pose[:,:3]))
        jaw_pose_reg = weights['jaw_pose']*tf.reduce_sum(tf.square(tf_pose[:,3:6]))
        eyeballs_pose_reg = weights['eyeballs_pose']*tf.reduce_sum(tf.square(tf_pose[:,6:]))
        shape_reg = weights['shape']*tf.reduce_sum(tf.square(tf_shape))
        exp_reg = weights['expr']*tf.reduce_sum(tf.square(tf_exp))

        session.run(tf.global_variables_initializer())

        if visualize:
            def on_step(verts, scale, faces, target_img, target_lmks, opt_lmks, lmk_dist=0.0, shape_reg=0.0, exp_reg=0.0, neck_pose_reg=0.0, jaw_pose_reg=0.0, eyeballs_pose_reg=0.0):
                import cv2
                import sys
                import numpy as np
                from psbody.mesh import Mesh
                from utils.render_mesh import render_mesh

                if lmk_dist>0.0 or shape_reg>0.0 or exp_reg>0.0 or neck_pose_reg>0.0 or jaw_pose_reg>0.0 or eyeballs_pose_reg>0.0:
                    print('lmk_dist: %f, shape_reg: %f, exp_reg: %f, neck_pose_reg: %f, jaw_pose_reg: %f, eyeballs_pose_reg: %f' % (lmk_dist, shape_reg, exp_reg, neck_pose_reg, jaw_pose_reg, eyeballs_pose_reg))

                plt_target_lmks = target_lmks.copy()
                plt_target_lmks[:, 1] = target_img.shape[0] - plt_target_lmks[:, 1]
                for (x, y) in plt_target_lmks:
                    cv2.circle(target_img, (int(x), int(y)), 4, (0, 0, 255), -1)

                plt_opt_lmks = opt_lmks.copy()
                plt_opt_lmks[:,1] = target_img.shape[0] - plt_opt_lmks[:,1]
                for (x, y) in plt_opt_lmks:
                    cv2.circle(target_img, (int(x), int(y)), 4, (255, 0, 0), -1)

                if sys.version_info >= (3, 0):
                    rendered_img = render_mesh(Mesh(scale*verts, faces), height=target_img.shape[0], width=target_img.shape[1])
                    for (x, y) in plt_opt_lmks:
                        cv2.circle(rendered_img, (int(x), int(y)), 4, (255, 0, 0), -1)
                    target_img = np.hstack((target_img, rendered_img))

                #cv2.imshow('img', target_img)
                #cv2.waitKey(10)
        else:
            def on_step(*_):
                pass

        print('Optimize rigid transformation')
        vars = [tf_scale, tf_trans, tf_rot]
        loss = lmk_dist
        optimizer = scipy_pt(loss=loss, var_list=vars, method='L-BFGS-B', options={'disp': 1, 'ftol': 5e-6})
        optimizer.minimize(session, fetches=[tf_model, tf_scale, tf.constant(smpl.f), tf.constant(target_img), tf.constant(target_2d_lmks), lmks_proj_2d], loss_callback=on_step)

        print('Optimize model parameters')
        vars = [tf_scale, tf_trans[:2], tf_rot, tf_pose, tf_shape, tf_exp]
        loss = lmk_dist + shape_reg + exp_reg + neck_pose_reg + jaw_pose_reg + eyeballs_pose_reg

        optimizer = scipy_pt(loss=loss, var_list=vars, method='L-BFGS-B', options={'disp': 0, 'ftol': 1e-7})
        optimizer.minimize(session, fetches=[tf_model, tf_scale, tf.constant(smpl.f), tf.constant(target_img), tf.constant(target_2d_lmks), lmks_proj_2d,
                                             lmk_dist, shape_reg, exp_reg, neck_pose_reg, jaw_pose_reg, eyeballs_pose_reg], loss_callback=on_step)

        print('Fitting done')
        np_verts, np_scale = session.run([tf_model, tf_scale])
        return Mesh(np_verts, smpl.f), np_scale
Beispiel #10
0
num_stage = 3
num_theta = 72
coeff_num = 85

smpl_neutral_path = "./tf_smpl/neutral_smpl_with_cocoplus_reg.pkl"
joint_type = "cocoplus"

f_len = 366.474487
rend_size = 256.
intrinsic = np.array([[f_len / 480 * 256, 0, rend_size / 2],
                      [0, f_len / 480 * 256, rend_size / 2], [0, 0, 1]])

# some predefined functions
# ===========================================================

smpl = SMPL(smpl_neutral_path, joint_type=joint_type)


# render predicted coefficients - hmr
def render_hmr_smpl(hmr_coeff, f_len=500., rend_size=224., req_model=False):
    # hmr_coeff is a 85-vector, named as theta in hmr
    hmr_coeff = np.asarray(hmr_coeff).tolist()

    # make scene
    scene = pyrender.Scene()

    # initialize camera
    camera = pyrender.PerspectiveCamera(
        yfov=np.arctan(rend_size * 0.5 / f_len) * 2, aspectRatio=1)
    camera_pose = np.array([[1.0, 0.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0],
                            [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 0.0, 1.0]])
Beispiel #11
0
from tf_smpl.batch_smpl import SMPL
from tf_smpl.batch_lbs import batch_rodrigues, batch_global_rigid_transformation
import tensorflow as tf
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

if __name__ == '__main__':
    smpl = SMPL('../models/neutral_smpl_with_cocoplus_reg.pkl')
    beta = tf.zeros([1, 10], dtype=tf.float32)
    npose = np.zeros([1, 72])
    pose = tf.constant(npose, dtype=tf.float32)
    verts, joints, Rs = smpl(beta, pose, get_skin=True)

    sess = tf.Session()
    sess.run(tf.global_variables_initializer())
    V, J, R = sess.run([verts, joints, Rs])
    fig = plt.figure(1)
    ax = fig.add_subplot(111, projection='3d')

    ax.scatter(J[0, :, 0], J[0, :, 1], J[0, :, 2], c='r')
    ax.scatter(J[0, 18, 0], J[0, 18, 1], J[0, 18, 2], c='b')
    # ax.scatter(V[0, :, 0], V[0, :, 1], V[0, :, 2], c='b')
    ax.set_xlabel('X')
    ax.set_ylabel('Y')
    ax.set_zlabel('Z')
    ax.set_xlim(-1, 1)
    ax.set_ylim(-1, 1)
    ax.set_zlim(-1, 1)
    plt.show()
 def __init__(self, smpl_model_path, gaussians_params_path):
     self.smplModel = SMPL(smpl_model_path)
     self.gussians_prior = MaxMixtureCompletePrior(gaussians_params_path)
Beispiel #13
0
    def __init__(self, config, data_loader, mocap_loader):
        """
        Args:
          config
          if no 3D label is available,
              data_loader is a dict
          else
              data_loader is a dict
        mocap_loader is a tuple (pose, shape)
        """
        # Config + path
        self.config = config
        self.model_dir = config.model_dir
        self.load_path = config.load_path

        self.data_format = config.data_format
        self.smpl_model_path = config.smpl_model_path
        self.pretrained_model_path = config.pretrained_model_path
        self.encoder_only = config.encoder_only
        self.use_3d_label = config.use_3d_label

        # Data size
        self.img_size = config.img_size
        self.num_stage = config.num_stage
        self.batch_size = config.batch_size
        self.max_epoch = config.epoch

        self.num_cam = 3
        self.proj_fn = batch_orth_proj_idrot

        self.num_theta = 72  # 24 * 3
        self.total_params = self.num_theta + self.num_cam + 10

        # Data
        num_images = num_examples(config.datasets)
        num_mocap = num_examples(config.mocap_datasets)

        self.num_itr_per_epoch = num_images / self.batch_size
        self.num_mocap_itr_per_epoch = num_mocap / self.batch_size

        # First make sure data_format is right
        if self.data_format == 'NCHW':
            # B x H x W x 3 --> B x 3 x H x W
            data_loader['image'] = tf.transpose(data_loader['image'],
                                                [0, 3, 1, 2])

        self.image_loader = data_loader['image']
        self.kp_loader = data_loader['label']

        if self.use_3d_label:
            self.poseshape_loader = data_loader['label3d']
            # image_loader[3] is N x 2, first column is 3D_joints gt existence,
            # second column is 3D_smpl gt existence
            self.has_gt3d_joints = data_loader['has3d'][:, 0]
            self.has_gt3d_smpl = data_loader['has3d'][:, 1]

        self.pose_loader = mocap_loader[0]
        self.shape_loader = mocap_loader[1]

        self.global_step = tf.Variable(0, name='global_step', trainable=False)
        self.log_img_step = config.log_img_step

        # For visualization:
        num2show = np.minimum(6, self.batch_size)
        # Take half from front & back
        self.show_these = tf.constant(
            np.hstack(
                [np.arange(num2show / 2), self.batch_size - np.arange(3) - 1]),
            tf.int32)

        # Model spec
        self.model_type = config.model_type
        self.keypoint_loss = keypoint_l1_loss

        # Optimizer, learning rate
        self.e_lr = config.e_lr
        self.d_lr = config.d_lr
        # Weight decay
        self.e_wd = config.e_wd
        self.d_wd = config.d_wd
        self.e_loss_weight = config.e_loss_weight
        self.d_loss_weight = config.d_loss_weight
        self.e_3d_weight = config.e_3d_weight

        self.optimizer = tf.train.AdamOptimizer

        # Instantiate SMPL
        self.smpl = SMPL(self.smpl_model_path)
        self.E_var = []
        self.build_model()

        # Logging
        init_fn = None
        if self.use_pretrained():
            # Make custom init_fn
            print("Fine-tuning from %s" % self.pretrained_model_path)
            if 'resnet_v2_50' in self.pretrained_model_path:
                resnet_vars = [
                    var for var in self.E_var if 'resnet_v2_50' in var.name
                ]
                self.pre_train_saver = tf.train.Saver(resnet_vars)
            elif 'pose-tensorflow' in self.pretrained_model_path:
                resnet_vars = [
                    var for var in self.E_var if 'resnet_v1_101' in var.name
                ]
                self.pre_train_saver = tf.train.Saver(resnet_vars)
            else:
                self.pre_train_saver = tf.train.Saver()

            def load_pretrain(sess):
                self.pre_train_saver.restore(sess, self.pretrained_model_path)

            init_fn = load_pretrain

        self.saver = tf.train.Saver(keep_checkpoint_every_n_hours=5)
        self.summary_writer = tf.summary.FileWriter(self.model_dir)
        self.sv = tf.train.Supervisor(logdir=self.model_dir,
                                      global_step=self.global_step,
                                      saver=self.saver,
                                      summary_writer=self.summary_writer,
                                      init_fn=init_fn)
        gpu_options = tf.GPUOptions(allow_growth=True)
        self.sess_config = tf.ConfigProto(allow_soft_placement=False,
                                          log_device_placement=False,
                                          gpu_options=gpu_options)
Beispiel #14
0
def main(in_filename):
    images_path = os.path.join(__init__.project_path, 'data', 'images')
    in_im = cv2.imread(os.path.join(images_path, in_filename))
    in_im = cv2.cvtColor(in_im, cv2.COLOR_BGR2RGB)
    img_size = config.input_img_size
    expect_aspect = img_size[1] / img_size[0]
    in_shape = in_im.shape
    in_aspect = in_shape[1] / in_shape[0]
    if in_aspect != expect_aspect:
        if in_im.shape[1] >= in_im.shape[0] * expect_aspect:
            diff = int(in_im.shape[1] - in_im.shape[0] * expect_aspect)
            pad_im = cv2.copyMakeBorder(in_im, 0, diff, 0, 0,
                                        cv2.BORDER_CONSTANT, None, 0)
        else:
            diff = int(in_im.shape[0] * expect_aspect - in_im.shape[1])
            pad_im = cv2.copyMakeBorder(in_im, 0, 0, 0, diff,
                                        cv2.BORDER_CONSTANT, None, 0)
        in_im = pad_im

    in_im = cv2.resize(in_im,
                       dsize=(img_size[1], img_size[0]),
                       interpolation=cv2.INTER_AREA)

    tfconfig = tf.ConfigProto()
    tfconfig.gpu_options.allow_growth = True  # pylint: disable=no-member
    with tf.Graph().as_default():
        estimator = OpPoseEstimator(get_graph_path('cmu'),
                                    target_size=(img_size[1] * 2,
                                                 img_size[0] * 2),
                                    tf_config=tfconfig)
    humans = estimator.inference(in_im,
                                 resize_to_default=True,
                                 upsample_size=4)
    heatmaps = estimator.heatMat[:, :, :config.n_joints]
    heatmaps = data_helpers.suppress_non_largest_human(humans, heatmaps,
                                                       img_size)
    heatmaps = heatmaps[np.newaxis]  # add "batch" axis

    in_im_3d = cv2.normalize(in_im, None, 0, 1, cv2.NORM_MINMAX)
    inputs = np.concatenate([heatmaps, in_im_3d[np.newaxis]], axis=3)

    # Visualise argmaxs
    # input_locs = tf.Session().run(utils.soft_argmax_rescaled(heatmaps))
    # input_locs = input_locs[0]
    # plt.scatter(input_locs[:, 1], input_locs[:, 0])
    # plt.gca().invert_yaxis()
    # plt.show()
    # for input_loc in input_locs[0]:
    #     y, x, _ = (input_loc * 240 + np.array([120, 160, 0])).astype(np.int32)
    #     in_im = cv2.circle(in_im, (x, y), 3, (0, 255, 255))
    # plt.imshow(in_im)
    # plt.show()
    # exit()

    # with different graph so checkpoint is restored correctly
    pm_graph = tf.Graph()

    pm_3d = PoseModel3d((None, 240, 320, 3 + config.n_joints),
                        pm_graph,
                        mode='test',
                        summary_dir=SUMMARY_DIR,
                        saver_path=SAVER_PATH,
                        restore_model=True)
    out_vals = pm_3d.estimate(inputs)

    smpl_dir = os.path.join(__init__.project_path, 'data', 'SMPL_model',
                            'models_numpy')
    smpl_model_path = os.path.join(smpl_dir, 'model_neutral_np.pkl')
    faces_path = pkg_resources.resource_filename(tf_smpl.__name__,
                                                 'smpl_faces.npy')
    faces = np.load(faces_path)

    smpl = SMPL(smpl_model_path)
    beta = tf.zeros([1, 10])
    pose = tf.constant(out_vals[:, :72])

    cam_pos = tf.constant(out_vals[:, 72:75])
    cam_rot = tf.constant(out_vals[:, 75:78])
    cam_f = tf.tile([config.fl], [out_vals.shape[0]])

    verts, _, _ = smpl(beta, pose, get_skin=True)

    vert_faces = utils.vertex_faces_from_face_verts(faces)
    mesh_img = utils.render_mesh_verts_cam(
        verts, cam_pos, cam_rot,
        tf.atan2(config.ss / 2, cam_f) * 360 / np.pi,
        tf.constant(faces, dtype=tf.int32), vert_faces, cam_pos[:,
                                                                tf.newaxis, :])

    verts_eval, mesh_img_eval = tf.Session().run((verts[0], mesh_img[0]))

    dirpath = os.path.dirname(os.path.realpath(__file__))
    outmesh_path = os.path.join(dirpath, 'smpl_tf.obj')
    with open(outmesh_path, 'w') as fp:
        for v in verts_eval:
            fp.write('v %f %f %f\n' % (v[0], v[1], v[2]))

        for f in faces + 1:
            fp.write('f %d %d %d\n' % (f[0], f[1], f[2]))

    op_out_im = OpPoseEstimator.draw_humans(in_im, humans, imgcopy=True)
    plt.subplot(131)
    plt.imshow(np.sum(heatmaps[0][:, :, :config.n_joints], axis=2),
               cmap='gray')
    plt.subplot(132)
    plt.imshow(op_out_im)
    plt.subplot(133)
    plt.imshow(np.squeeze(mesh_img_eval), cmap='gray')
    plt.show()