예제 #1
0
def generate_pose_data():
    # Load FLAME model (here we load the female model)
    # Make sure path is correct
    model_path = './models/female_model.pkl'
    model = load_model(
        model_path
    )  # the loaded model object is a 'chumpy' object, check https://github.com/mattloper/chumpy for details
    print "loaded model from:", model_path

    # Assign random pose and shape parameters
    model.pose[:] = np.random.randn(model.pose.size) * 0.0
    model.betas[:] = np.random.randn(model.betas.size) * 1.0
    # model.trans[:] = np.random.randn( model.trans.size ) * 0.01   # you may also manipulate the translation of mesh

    outmesh_dir = './output'
    safe_mkdir(outmesh_dir)

    # Save zero pose
    outmesh_path = join(outmesh_dir, 'pose_0.obj')
    write_simple_obj(mesh_v=model.r, mesh_f=model.f, filepath=outmesh_path)

    # Write to an .obj file
    model.pose[3:6] = np.random.randn(3) * 0.3
    outmesh_path = join(outmesh_dir, 'pose_t.obj')
    write_simple_obj(mesh_v=model.r, mesh_f=model.f, filepath=outmesh_path)
    np.savetxt('./output/pose_t.txt', model.pose.r)

    # Print message
    print 'output mesh saved to: ', outmesh_path
예제 #2
0
 def debug_result(output_path, filename):
     output_path = output_path + filename
     g_v = g_scale.r * model.r[:, :]
     g_v[:, :] = g_v[:, :] + g_trans_2d.r
     write_simple_obj(mesh_v=g_v,
                      mesh_f=model.f,
                      filepath=output_path,
                      verbose=False)
예제 #3
0
def run_fitting_demo():

    # input landmarks
    lmk_path = './data/landmark_3d.pkl'
    lmk_3d = load_binary_pickle(lmk_path)
    print "loaded 3d landmark from:", lmk_path

    # model
    model_path = './models/male_model.pkl'  # change to 'female_model.pkl' or 'generic_model.pkl', if needed
    model = load_model(
        model_path
    )  # the loaded model object is a 'chumpy' object, check https://github.com/mattloper/chumpy for details
    print "loaded model from:", model_path

    # landmark embedding
    lmk_emb_path = './data/lmk_embedding_intraface_to_flame.pkl'
    lmk_face_idx, lmk_b_coords = load_embedding(lmk_emb_path)
    print "loaded lmk embedding"

    # output
    output_dir = './output'
    safe_mkdir(output_dir)

    # weights
    weights = {}
    weights['lmk'] = 1.0
    weights['shape'] = 0.001
    weights['expr'] = 0.001
    weights['pose'] = 0.1

    # optimization options
    import scipy.sparse as sp
    opt_options = {}
    opt_options['disp'] = 1
    opt_options['delta_0'] = 0.1
    opt_options['e_3'] = 1e-4
    opt_options['maxiter'] = 100
    sparse_solver = lambda A, x: sp.linalg.cg(
        A, x, maxiter=opt_options['maxiter'])[0]
    opt_options['sparse_solver'] = sparse_solver

    # run fitting
    mesh_v, mesh_f, parms = fit_lmk3d(
        lmk_3d=lmk_3d,  # input landmark 3d
        model=model,  # model
        lmk_face_idx=lmk_face_idx,
        lmk_b_coords=lmk_b_coords,  # landmark embedding
        weights=weights,  # weights for the objectives
        shape_num=300,
        expr_num=100,
        opt_options=opt_options)  # options

    # write result
    output_path = join(output_dir, 'fit_lmk3d_result.obj')
    write_simple_obj(mesh_v=mesh_v,
                     mesh_f=mesh_f,
                     filepath=output_path,
                     verbose=False)
예제 #4
0
def run_fitting():
    # input landmarks
    lmk_path = './data/scan_lmks.npy'
    # measurement unit of landmarks ['m', 'cm', 'mm']
    unit = 'mm' 

    scale_factor = get_unit_factor('m') / get_unit_factor(unit)
    lmk_3d = scale_factor*np.load(lmk_path)
    print("loaded 3d landmark from:", lmk_path)

    # model
    model_path = './models/generic_model.pkl' # change to 'female_model.pkl' or 'male_model.pkl', if gender is known
    model = load_model(model_path)       # the loaded model object is a 'chumpy' object, check https://github.com/mattloper/chumpy for details
    print("loaded model from:", model_path)

    # landmark embedding
    lmk_emb_path = './models/flame_static_embedding.pkl' 
    lmk_face_idx, lmk_b_coords = load_embedding(lmk_emb_path)
    print("loaded lmk embedding")

    # output
    output_dir = './output'
    safe_mkdir(output_dir)

    # weights
    weights = {}
    # landmark term
    weights['lmk']   = 1.0   
    # shape regularizer (weight higher to regularize face shape more towards the mean)
    weights['shape'] = 0.001
    # expression regularizer (weight higher to regularize facial expression more towards the mean)
    weights['expr']  = 0.001
    # regularization of head rotation around the neck and jaw opening (weight higher for more regularization)
    weights['pose']  = 0.1
    
    # optimization options
    import scipy.sparse as sp
    opt_options = {}
    opt_options['disp']    = 1
    opt_options['delta_0'] = 0.1
    opt_options['e_3']     = 1e-4
    opt_options['maxiter'] = 100
    sparse_solver = lambda A, x: sp.linalg.cg(A, x, maxiter=opt_options['maxiter'])[0]
    opt_options['sparse_solver'] = sparse_solver

    # run fitting
    mesh_v, mesh_f, parms = fit_lmk3d( lmk_3d=lmk_3d,                                         # input landmark 3d
                                       model=model,                                           # model
                                       lmk_face_idx=lmk_face_idx, lmk_b_coords=lmk_b_coords,  # landmark embedding
                                       weights=weights,                                       # weights for the objectives
                                       shape_num=300, expr_num=100, opt_options=opt_options ) # options

    # write result
    output_path = join( output_dir, 'fit_lmk3d_result.obj' )
    write_simple_obj( mesh_v=mesh_v, mesh_f=mesh_f, filepath=output_path, verbose=False )
예제 #5
0
def generate_exp_sequence(output_dir):
    # Load FLAME model (here we load the female model)
    # Make sure path is correct
    model_path = './models/generic_model.pkl'
    model = load_model(
        model_path
    )  # the loaded model object is a 'chumpy' object, check https://github.com/mattloper/chumpy for details
    print "loaded model from:", model_path

    safe_mkdir(output_dir)
    safe_mkdir(output_dir + '/gtcoeff')
    safe_mkdir(output_dir + '/gtcoeff/pose_coeff')
    safe_mkdir(output_dir + '/gtcoeff/exp_coeff')

    # Assign random pose and shape parameters
    model.pose[:] = np.random.randn(model.pose.size) * 0.0
    model.betas[:] = np.random.randn(model.betas.size) * 0.0

    save_model_joints_info(model, output_dir)
    save_model_pose_bs(model, output_dir + "/pose_bs.txt")

    model.betas[0:300] = np.random.randn(300) * 0.5
    save_model_joints_info(model, output_dir + "/gtcoeff")

    # model.trans[:] = np.random.randn( model.trans.size ) * 0.01   # you may also manipulate the translation of mesh

    # Save zero pose
    outmesh_path = join(output_dir, '0000.obj')
    write_simple_obj(mesh_v=model.r, mesh_f=model.f, filepath=outmesh_path)
    np.savetxt(output_dir + '/gtcoeff/beta.txt', model.betas.r, fmt='%.8f')
    save_model_pose_info(model, output_dir + "/gtcoeff/pose_coeff/0000.txt")
    save_model_exp_info(model, output_dir + '/gtcoeff/exp_coeff/0000.txt')

    # Write to an .obj file
    for idx in range(1, 10):
        model.pose[0:5] = np.random.randn(5) * 0.01
        model.pose[6] = abs(np.random.randn(1)) * 0.3
        model.pose[7:9] = np.random.randn(2) * 0.01
        model.trans[:] = np.random.randn(model.trans.size) * 0.01
        model.betas[300:] = np.random.randn(100) * 1
        outmesh_path = join(output_dir, '{:04d}.obj'.format(idx))
        write_simple_obj(mesh_v=model.r, mesh_f=model.f, filepath=outmesh_path)
        save_model_pose_info(
            model, output_dir + "/gtcoeff/pose_coeff/{:04d}.txt".format(idx))
        save_model_exp_info(
            model, output_dir + "/gtcoeff/exp_coeff/{:04d}.txt".format(idx))

        # Print message
        print 'output mesh saved to: ', outmesh_path
예제 #6
0
def hello_world():
    # Load FLAME model (here we load the female model)
    # Make sure path is correct
    model_path = './models/female_model.pkl'
    model = load_model(
        model_path
    )  # the loaded model object is a 'chumpy' object, check https://github.com/mattloper/chumpy for details
    print "loaded model from:", model_path

    # Show component number
    print "\nFLAME coefficients:"
    print "shape (identity) coefficient shape =", model.betas[
        0:300].shape  # valid shape component range in "betas": 0-299
    print "expression coefficient shape       =", model.betas[
        300:].shape  # valid expression component range in "betas": 300-399
    print "pose coefficient shape             =", model.pose.shape

    print "\nFLAME model components:"
    print "shape (identity) component shape =", model.shapedirs[:, :,
                                                                0:300].shape
    print "expression component shape       =", model.shapedirs[:, :,
                                                                300:].shape
    print "pose corrective blendshape shape =", model.posedirs.shape
    print ""

    # -----------------------------------------------------------------------------

    # Assign random pose and shape parameters
    model.pose[:] = np.random.randn(model.pose.size) * 0.05
    model.pose[3:6] = np.random.randn(3) * 0.5
    model.betas[:] = np.random.randn(model.betas.size) * 1.0
    # model.trans[:] = np.random.randn( model.trans.size ) * 0.01   # you may also manipulate the translation of mesh

    # Write to an .obj file
    outmesh_dir = './output'
    safe_mkdir(outmesh_dir)
    outmesh_path = join(outmesh_dir, 'hello_flame.obj')
    write_simple_obj(mesh_v=model.r, mesh_f=model.f, filepath=outmesh_path)

    # Print message
    print 'output mesh saved to: ', outmesh_path
예제 #7
0
def run_fitting():

    # input landmarks
    lmk_path = './data/landmark_3d.pkl'
    lmk_3d = load_binary_pickle(lmk_path)

    q1 = quaternion.from_rotation_vector([0, 0, 0])
    #   quaternion.from_euler_angles(20,0,0)
    g_r = quaternion.as_rotation_matrix(q1)
    lmk_3d = np.asmatrix((lmk_3d + [0, 0.01, -0.01])) * np.asmatrix(g_r)
    lmk_3d = np.asarray(lmk_3d)
    print "loaded 3d landmark from:", lmk_path
    fig = plt.figure(figsize=plt.figaspect(1))
    ax = plt.subplot(111, projection='3d')
    ax.scatter(lmk_3d[:, 0], lmk_3d[:, 1], lmk_3d[:, 2], c='r')
    ax.set_zlabel('Z')
    ax.set_ylabel('Y')
    ax.set_xlabel('X')
    ax.set_xlim(ax.get_xlim()[::-1])
    #    plt.show()

    # model
    model_path = './models/male_model.pkl'  # change to 'female_model.pkl' or 'generic_model.pkl', if needed
    model = load_model(
        model_path
    )  # the loaded model object is a 'chumpy' object, check https://github.com/mattloper/chumpy for details
    print "loaded model from:", model_path

    # landmark embedding
    lmk_emb_path = './data/lmk_embedding_intraface_to_flame.pkl'
    lmk_face_idx, lmk_b_coords = load_embedding(lmk_emb_path)

    mat_save({'lmk_face_idx': lmk_face_idx}, 'lmk_face_idx.mat')
    mat_save({'lmk_b_coord': lmk_b_coords}, 'lmk_b_coords.mat')
    print "loaded lmk embedding"

    # output
    output_dir = './output'
    safe_mkdir(output_dir)

    # weights
    weights = {}
    weights['lmk'] = 1.0
    weights['shape'] = 0.001
    weights['expr'] = 0.001
    weights['pose'] = 0.1

    # optimization options
    import scipy.sparse as sp
    opt_options = {}
    opt_options['disp'] = 1
    opt_options['delta_0'] = 0.1
    opt_options['e_3'] = 1e-4
    opt_options['maxiter'] = 100
    sparse_solver = lambda A, x: sp.linalg.cg(
        A, x, maxiter=opt_options['maxiter'])[0]
    opt_options['sparse_solver'] = sparse_solver

    # run fitting
    mesh_v, mesh_f, parms = fit_lmk3d(
        lmk_3d=lmk_3d,  # input landmark 3d
        model=model,  # model
        lmk_face_idx=lmk_face_idx,
        lmk_b_coords=lmk_b_coords,  # landmark embedding
        weights=weights,  # weights for the objectives
        shape_num=300,
        expr_num=100,
        opt_options=opt_options)  # options
    #    vp.trisurf(align_v, align_f, rendertype='wireframe')
    #    vp.scatter(pts=lmk_3d,alpha=1,mode='sphere',scale=0.001)
    # vp.trisurf(v_final, f_final, rendertype='wireframe', color3f=(0,0,0), alpha=0.3)
    #    vp.show()
    # write result
    output_path = join(output_dir, 'fit_lmk3d_result.obj')

    vp.trisurf(mesh_v, mesh_f, rendertype='wireframe')
    vp.scatter(pts=lmk_3d, alpha=1, mode='sphere', scale=0.001)
    # vp.trisurf(v_final, f_final, rendertype='wireframe', color3f=(0,0,0), alpha=0.3)
    vp.show()
    write_simple_obj(mesh_v=mesh_v,
                     mesh_f=mesh_f,
                     filepath=output_path,
                     verbose=False)
예제 #8
0
def run_fitting():
    # input scan
    scan_path = './data/scan.obj'
    # landmarks of the scan
    scan_lmk_path = './data/scan_lmks.npy'
    # measurement unit of landmarks ['m', 'cm', 'mm']
    scan_unit = 'm'

    scale_factor = get_unit_factor('m') / get_unit_factor(scan_unit)
    scan = Mesh(filename=scan_path)
    scan.v[:] *= scale_factor
    print("loaded scan from:", scan_path)

    lmk_3d = scale_factor * np.load(scan_lmk_path)
    print("loaded scan landmark from:", scan_lmk_path)

    # model
    model_path = './models/generic_model.pkl'  # change to 'female_model.pkl' or 'male_model.pkl', if gender is known
    model = load_model(
        model_path
    )  # the loaded model object is a 'chumpy' object, check https://github.com/mattloper/chumpy for details
    print("loaded model from:", model_path)

    # landmark embedding
    lmk_emb_path = './models/flame_static_embedding.pkl'
    lmk_face_idx, lmk_b_coords = load_embedding(lmk_emb_path)
    print("loaded lmk embedding")

    # output
    output_dir = './output'
    safe_mkdir(output_dir)

    # weights
    weights = {}
    # scan vertex to model surface distance term
    weights['s2m'] = 2.0
    # landmark term
    weights['lmk'] = 1e-2
    # shape regularizer (weight higher to regularize face shape more towards the mean)
    weights['shape'] = 1e-4
    # expression regularizer (weight higher to regularize facial expression more towards the mean)
    weights['expr'] = 1e-4
    # regularization of head rotation around the neck and jaw opening (weight higher for more regularization)
    weights['pose'] = 1e-3
    # Parameter of the Geman-McClure robustifier (higher weight for a larger bassin of attraction which makes it less robust to outliers)
    gmo_sigma = 1e-4

    # optimization options
    import scipy.sparse as sp
    opt_options = {}
    opt_options['disp'] = 1
    opt_options['delta_0'] = 0.1
    opt_options['e_3'] = 1e-4
    opt_options['maxiter'] = 2000
    sparse_solver = lambda A, x: sp.linalg.cg(
        A, x, maxiter=opt_options['maxiter'])[0]
    opt_options['sparse_solver'] = sparse_solver

    # run fitting
    mesh_v, mesh_f, parms = fit_scan(
        scan=scan,  # input scan
        lmk_3d=lmk_3d,  # input landmark 3d
        model=model,  # model
        lmk_face_idx=lmk_face_idx,
        lmk_b_coords=lmk_b_coords,  # landmark embedding
        weights=weights,  # weights for the objectives
        gmo_sigma=gmo_sigma,  # parameter of the regularizer
        shape_num=300,
        expr_num=100,
        opt_options=opt_options)  # options

    # write result
    output_path = join(output_dir, 'fit_scan_result.obj')
    write_simple_obj(mesh_v=mesh_v,
                     mesh_f=mesh_f,
                     filepath=output_path,
                     verbose=False)

    print('output mesh saved to: ', output_path)
예제 #9
0
    print("loaded model from:", model_path)

    # Show component number
    print("\nFLAME coefficients:")
    print("shape (identity) coefficient shape =", model.betas[0:300].shape) # valid shape component range in "betas": 0-299
    print("expression coefficient shape       =", model.betas[300:].shape)  # valid expression component range in "betas": 300-399
    print("pose coefficient shape             =", model.pose.shape)

    print("\nFLAME model components:")
    print("shape (identity) component shape =", model.shapedirs[:,:,0:300].shape)
    print("expression component shape       =", model.shapedirs[:,:,300:].shape)
    print("pose corrective blendshape shape =", model.posedirs.shape)
    print("")

    # -----------------------------------------------------------------------------

    # Assign random pose and shape parameters
    model.pose[:]  = np.random.randn( model.pose.size ) * 0.05
    model.betas[:] = np.random.randn( model.betas.size ) * 1.0
    # model.trans[:] = np.random.randn( model.trans.size ) * 0.01   # you may also manipulate the translation of mesh

    # Write to an .obj file
    outmesh_dir = './output'
    safe_mkdir( outmesh_dir )
    outmesh_path = join( outmesh_dir, 'hello_flame.obj' )
    write_simple_obj( mesh_v=model.r, mesh_f=model.f, filepath=outmesh_path )

    # Print(message
    print('output mesh saved to: ', outmesh_path )

예제 #10
0
def run_fitting():
    # input landmarks
    '''
    lmk_path = './data/landmark_3d.pkl'
    lmk_3d = load_binary_pickle(lmk_path)

    q1 = quaternion.from_rotation_vector([0, 0, 0])
    #   quaternion.from_euler_angles(20,0,0)
    g_r = quaternion.as_rotation_matrix(q1)
    lmk_3d = np.asmatrix((lmk_3d + [0, 0.01, -0.01])) * np.asmatrix(g_r)
    lmk_3d = np.asarray(lmk_3d)
    print "loaded 3d landmark from:", lmk_path
    fig = plt.figure(figsize=plt.figaspect(1))
    ax = plt.subplot(111, projection='3d')
    ax.scatter(lmk_3d[:, 0], lmk_3d[:, 1], lmk_3d[:, 2], c='r')
    ax.set_zlabel('Z')
    ax.set_ylabel('Y')
    ax.set_xlabel('X')
    ax.set_xlim(ax.get_xlim()[::-1])
    plt.show()
    '''
    # model
    model_path = './models/generic_model.pkl'  # change to 'female_model.pkl' or 'generic_model.pkl', if needed
    model = load_model(
        model_path
    )  # the loaded model object is a 'chumpy' object, check https://github.com/mattloper/chumpy for details
    print "loaded model from:", model_path

    # landmark embedding
    lmk_emb_path = './data/lmk_embedding_intraface_to_flame.pkl'
    lmk_face_idx, lmk_b_coords = load_embedding(lmk_emb_path)
    lmk_v = igl.eigen.MatrixXd()
    lmk_f = igl.eigen.MatrixXi()
    igl.readOBJ('C:/Users/hehua2015/Pictures/niutou/seg/maya_6.obj', lmk_v,
                lmk_f)
    lmk_v = IglMatrixTonpArray(lmk_v)
    #    mat_save({'lmk_face_idx': lmk_face_idx}, 'lmk_face_idx.mat')
    #    mat_save({'lmk_b_coord': lmk_b_coords}, 'lmk_b_coords.mat')
    #    print "loaded lmk embedding"
    face_select_lmk = np.array([
        2210, 1963, 3486, 3382, 3385, 3389, 3392, 3396, 3400, 3599, 3594, 3587,
        3581, 3578, 3757, 568, 728, 3764, 3158, 335, 3705, 2178, 673, 3863, 16,
        2139, 3893, 3553, 3561, 3501, 3564, 2747, 2749, 3552, 1617, 1611, 2428,
        2383, 2493, 2488, 2292, 2335, 1337, 1342, 1034, 1154, 959, 880, 2712,
        2850, 2811, 3543, 1694, 1735, 1576, 1770, 1801, 3511, 2904, 2878, 2715,
        2852, 3531, 1737, 1579, 1793, 3504, 2896
    ])
    #逆时针 ,前到后
    body_select_lmk = np.array([3277, 3240, 3222, 3341])
    target_face_lmk_v = lmk_v[face_select_lmk, 0:2]
    target_body_lmk_v = lmk_v[body_select_lmk, 0:2]
    # output
    output_dir = './output'
    safe_mkdir(output_dir)

    # weights
    weights = {}
    weights['lmk'] = 1.0
    weights['shape'] = 0.001
    weights['expr'] = 0.001
    weights['pose'] = 0.1

    # optimization options
    import scipy.sparse as sp
    opt_options = {}
    opt_options['disp'] = 1
    opt_options['delta_0'] = 0.1
    opt_options['e_3'] = 1e-4
    opt_options['maxiter'] = 10
    sparse_solver = lambda A, x: sp.linalg.cg(
        A, x, maxiter=opt_options['maxiter'])[0]
    opt_options['sparse_solver'] = sparse_solver
    target_lmk_v = np.concatenate((target_face_lmk_v, target_body_lmk_v))

    landmark_v = igl.eigen.MatrixXd()
    landmark_f = igl.eigen.MatrixXi()
    igl.readOBJ(
        'L:/yuanqing/imgs/imgs/vrn_result/niutou/01' +
        '/01_corr_landmark_cast_sym' + '.obj', landmark_v, landmark_f)
    landmark_v = np.array(landmark_v)
    landmark_body = np.array([[586, 336, 130], [562, 369, 150],
                              [709, 295, 160], [727, 262, 150]])
    landmark_body[:, 1] = 683 - landmark_body[:, 1]
    #    landmark_body_f = np.array([[0,1,2],[0,2,3]])
    #    igl.writeOBJ('L:/yuanqing/imgs/imgs/vrn_result/niutou/01' + '/01_landmark_body_plane' + '.obj', igl.eigen.MatrixXd(landmark_body.astype('float64')),
    #                igl.eigen.MatrixXi(landmark_body_f.astype('intc')))

    target_lmk_v = np.concatenate((landmark_v[:, :], landmark_body[:, :]))

    # run fitting
    mesh_v, mesh_f, parms = fit_lmk3d(
        lmk_3d=target_lmk_v,  # input landmark 3d
        model=model,  # model
        mesh_faces=model.f,
        lmk_face_idx=lmk_face_idx,
        lmk_b_coords=lmk_b_coords,
        lmk_facevtx_idx=face_select_lmk,
        lmk_bodyvtx_idx=body_select_lmk,  # landmark embedding
        weights=weights,  # weights for the objectives
        shape_num=300,
        expr_num=100,
        opt_options=opt_options)  # options
    #    vp.trisurf(align_v, align_f, rendertype='wireframe')
    #    vp.scatter(pts=lmk_3d,alpha=1,mode='sphere',scale=0.001)
    # vp.trisurf(v_final, f_final, rendertype='wireframe', color3f=(0,0,0), alpha=0.3)
    #    vp.show()
    # write result
    output_dir = 'L:/yuanqing/imgs/imgs/vrn_result/niutou/01/'
    output_path = join(output_dir, 'fit_lmk3d_result_01.obj')
    write_simple_obj(mesh_v=mesh_v,
                     mesh_f=mesh_f,
                     filepath=output_path,
                     verbose=False)
    return
    vp.trisurf(mesh_v, mesh_f, rendertype='wireframe')
    vp.scatter(pts=target_lmk_v, alpha=1, mode='sphere', scale=0.001)
    # vp.trisurf(v_final, f_final, rendertype='wireframe', color3f=(0,0,0), alpha=0.3)
    vp.show()
    write_simple_obj(mesh_v=mesh_v,
                     mesh_f=mesh_f,
                     filepath=output_path,
                     verbose=False)
예제 #11
0
def fit_lmk3d_old(lmk_3d,  # input landmark 3d
              model,  # model
              lmk_facevtx_idx, lmk_bodyvtx_idx,  # landmark embedding
              weights,  # weights for the objectives
              shape_num=300, expr_num=100, opt_options=None):
    """ function: fit FLAME model to 3d landmarks

    input:
        lmk_3d: input landmark 3d, in shape (N,3)
        model: FLAME face model
        lmk_face_idx, lmk_b_coords: landmark embedding, in face indices and barycentric coordinates
        weights: weights for each objective
        shape_num, expr_num: numbers of shape and expression compoenents used
        opt_options: optimizaton options

    output:
        model.r: fitted result vertices
        model.f: fitted result triangulations (fixed in this code)
        parms: fitted model parameters

    """

    # variables
    shape_idx = np.arange(0, min(300, shape_num))  # valid shape component range in "betas": 0-299
    expr_idx = np.arange(300, 300 + min(100, expr_num))  # valid expression component range in "betas": 300-399
    used_idx = np.union1d(shape_idx, expr_idx)
    model.betas[:] = np.random.rand(model.betas.size) * 0.0  # initialized to zero
    model.pose[:] = np.random.rand(model.pose.size) * 0.0  # initialized to zero
    # free_variables = [ model.trans, model.pose, model.betas[used_idx] ]
    free_variables = [model.pose, model.betas[used_idx]]
    # weights
    print "fit_lmk3d(): use the following weights:"
    for kk in weights.keys():
        print "fit_lmk3d(): weights['%s'] = %f" % (kk, weights[kk])

        # objectives
    # lmk
    scale = ch.array([1])

    # options
    if opt_options is None:
        print "fit_lmk3d(): no 'opt_options' provided, use default settings."
        import scipy.sparse as sp
        opt_options = {}
        opt_options['disp'] = 1
        opt_options['delta_0'] = 0.1
        opt_options['e_3'] = 1e-4
        opt_options['maxiter'] = 100
        sparse_solver = lambda A, x: sp.linalg.cg(A, x, maxiter=opt_options['maxiter'])[0]
        opt_options['sparse_solver'] = sparse_solver

    # on_step callback
    def on_step(_):
        pass

    # optimize
    # step 1: rigid alignment
    from time import time
    timer_start = time()
    '''

    print "\nstep 1: start rigid fitting..."
    ch.minimize( fun      = lmk_err,
                 x0       = [ model.trans, model.pose[0:3],scale ],
                 method   = 'dogleg',
                 callback = on_step,
                 options  = opt_options )
    timer_end = time()
    align_v = scale*model.r
    align_f = model.f
    print "step 1: fitting done, in %f sec\n" % ( timer_end - timer_start )
    print "scale: %f\n" % scale
    print "model.trans"
    print model.trans
    print "model.rot"
    print model.pose[0:3]
    '''
    # optimize
    # step 1: rigid alignment

    g_scale = ch.array([1000])
    g_trans_2d = ch.array([0,0])
    print "\nstep 1: update global pose..."
    lmk_err = landmark_error_3d(
                                scale = g_scale,
                                trans_2d = g_trans_2d,
                                mesh_verts=model,
                                target_lmk_3d_face=lmk_3d[0:68,:],
                                target_lmk_3d_body=lmk_3d[68:72,:],
                                lmk_facevtx_idx=lmk_facevtx_idx,
                                lmk_bodyvtx_idx=lmk_bodyvtx_idx,
                                face_weight=0,
                                body_weight= 1
                                )
    # regularizer
    shape_err = weights['shape'] * model.betas[shape_idx]
    expr_err = weights['expr'] * model.betas[expr_idx]
    pose_err = weights['pose'] * model.pose[3:6]  # exclude global rotation
    objectives = {}
    objectives.update({'lmk': lmk_err, 'shape': shape_err, 'expr': expr_err, 'pose': pose_err})
    objectives_pose = {}
    objectives_pose.update({'lmk': lmk_err})
    ch.minimize( fun      = objectives_pose,
                 x0       = [ model.trans,g_trans_2d,model.pose[0:3]],
                 method   = 'dogleg',
                 callback = on_step,
                 options  = opt_options )
    timer_end = time()
    print "step 1: global pose fitting done, in %f sec\n" % ( timer_end - timer_start )
    print "model.trans"
    print model.trans
    print "head.rot"
    print model.pose[3:6]
    print "all pose"
    print model.pose[:]
    print "g_scale"
    print g_scale
    print "g_trans_2d"
    print g_trans_2d
    output_dir = 'L:/yuanqing/imgs/imgs/vrn_result/niutou/01/'
    output_path = join(output_dir, 'step_1.obj')
    g_v =  g_scale.r*model.r[:,:]
    g_v[:,0:2] = g_v[:,0:2]+g_trans_2d.r
    write_simple_obj(mesh_v=g_v, mesh_f=model.f, filepath=output_path, verbose=False)
    # step 2: update head pose
    lmk_err = landmark_error_3d(mesh_verts=model,
                                scale=g_scale,
                                trans_2d=g_trans_2d,
                                target_lmk_3d_face=lmk_3d[0:68,:],
                                target_lmk_3d_body=lmk_3d[68:72,:],
                                lmk_facevtx_idx=lmk_facevtx_idx,
                                lmk_bodyvtx_idx=lmk_bodyvtx_idx,
                                face_weight=1,
                                body_weight= 0
                                )
    objectives_pose.update({'lmk': lmk_err})
    print "\nstep 2: update head pose..."
    ch.minimize( fun      = objectives_pose,
                 x0       = [ g_scale,g_trans_2d,model.pose[3:6]],
                 method   = 'dogleg',
                 callback = on_step,
                 options  = opt_options )
    timer_end = time()
    print "step 2: head pose fitting done, in %f sec\n" % ( timer_end - timer_start )
    print "model.trans"
    print model.trans
    print "head.rot"
    print model.pose[3:6]
    print "all pose"
    print model.pose[:]
    print "g_scale"
    print g_scale
    print "g_trans_2d"
    print g_trans_2d
    output_dir = 'L:/yuanqing/imgs/imgs/vrn_result/niutou/01/'
    output_path = join(output_dir, 'step_2.obj')
    g_v =  g_scale.r*model.r[:,:]
    g_v[:,0:2] = g_v[:,0:2]+g_trans_2d.r
    write_simple_obj(mesh_v=g_v, mesh_f=model.f, filepath=output_path, verbose=False)
    # step 3: update all pose

    lmk_err = landmark_error_3d(mesh_verts=model,
                                scale=g_scale,
                                trans_2d=g_trans_2d,
                                target_lmk_3d_face=lmk_3d[0:68,:],
                                target_lmk_3d_body=lmk_3d[68:72,:],
                                lmk_facevtx_idx=lmk_facevtx_idx,
                                lmk_bodyvtx_idx=lmk_bodyvtx_idx,
                                face_weight=1,
                                body_weight= 1
                                )
    objectives_pose.update({'lmk': lmk_err})
    print "\nstep 3: update all pose..."
    ch.minimize( fun      = objectives_pose,
                 x0       = [ g_scale,g_trans_2d,model.pose[0:6]],
                 method   = 'dogleg',
                 callback = on_step,
                 options  = opt_options )
    timer_end = time()
    print "step 3: head pose fitting done, in %f sec\n" % ( timer_end - timer_start )
    print "model.trans"
    print model.trans
    print "head.rot"
    print model.pose[3:6]
    print "all pose"
    print model.pose[:]
    print "g_scale"
    print g_scale
    print "g_trans_2d"
    print g_trans_2d
    output_dir = 'L:/yuanqing/imgs/imgs/vrn_result/niutou/01/'
    output_path = join(output_dir, 'step_3.obj')
    g_v =  g_scale.r*model.r[:,:]
    g_v[:,0:2] = g_v[:,0:2]+g_trans_2d.r
    write_simple_obj(mesh_v=g_v, mesh_f=model.f, filepath=output_path, verbose=False)

    '''
    # step 2: non-rigid alignment
    timer_start = time()
    print "step 2: start non-rigid fitting..."
    ch.minimize(fun=objectives,
                x0=free_variables,
                method='dogleg',
                callback=on_step,
                options=opt_options)
    timer_end = time()
    print "step 2: fitting done, in %f sec\n" % (timer_end - timer_start)
    '''
    # return results
    parms = {'trans': model.trans.r, 'pose': model.pose.r, 'betas': model.betas.r}

    return g_v, model.f, parms  # ,align_v,align_f
    #return model.r, model.f, parms  # ,align_v,align_f
예제 #12
0
def run_fitting(lmk_fid_file, lmk_bary_file, lmk_3d_file, output_dir, fix_exp):
    # input landmarks#
    lmk_3d = []
    fin = open(lmk_3d_file, 'r')
    data = fin.read()
    rows = data.split('\n')
    for row in rows:
        split_row = row.split(' ')
        if len(split_row) != 3:
            continue
        for i in range(3):
            split_row[i] = float(split_row[i])
        lmk_3d.append(split_row[0:3])
    fin.close()
    #print lmk_3d
    lmk_3d = np.array(lmk_3d)

    # model
    model_path = './models/male_model.pkl'  # change to 'female_model.pkl' or 'generic_model.pkl', if needed
    model = load_model(
        model_path
    )  # the loaded model object is a 'chumpy' object, check https://github.com/mattloper/chumpy for details
    print "loaded model from:", model_path
    #print model.J
    #print model.weights

    # landmark embedding
    lmk_face_idx = []
    fin = open(lmk_fid_file, 'r')
    data = fin.read()
    rows = data.split('\n')
    for row in rows:
        if row == '':
            continue
        lmk_face_idx.append(int(row))
    fin.close()
    lmk_face_idx = np.array(lmk_face_idx)

    lmk_b_coords = []
    fin = open(lmk_bary_file, 'r')
    data = fin.read()
    rows = data.split('\n')
    for row in rows:
        split_row = row.split(' ')
        if len(split_row) != 3:
            continue
        for i in range(3):
            split_row[i] = float(split_row[i])
        lmk_b_coords.append(split_row[0:3])
    fin.close()
    lmk_b_coords = np.array(lmk_b_coords)

    # output
    #output_dir = './output'
    safe_mkdir(output_dir)

    # weights
    weights = {}
    weights['lmk'] = 1.0
    weights['shape'] = 0.001
    weights['expr'] = 0.001
    weights['pose'] = 0.1

    # optimization options
    import scipy.sparse as sp
    opt_options = {}
    opt_options['disp'] = 1
    opt_options['delta_0'] = 0.1
    opt_options['e_3'] = 1e-4
    opt_options['maxiter'] = 100
    sparse_solver = lambda A, x: sp.linalg.cg(
        A, x, maxiter=opt_options['maxiter'])[0]
    opt_options['sparse_solver'] = sparse_solver

    # run fitting
    mesh_v, mesh_f, parms = fit_lmk3d(
        lmk_3d=lmk_3d,  # input landmark 3d
        model=model,  # model
        lmk_face_idx=lmk_face_idx,
        lmk_b_coords=lmk_b_coords,  # landmark embedding
        weights=weights,  # weights for the objectives
        shape_num=300,
        expr_num=100,
        opt_options=opt_options,
        fix_exp=fix_exp)  # options

    # write result
    output_path = join(output_dir, 'fit_lmk3d_result.obj')
    write_simple_obj(mesh_v=mesh_v,
                     mesh_f=mesh_f,
                     filepath=output_path,
                     verbose=False)

    print model.J
    j_num = len(model.J)
    fout = open(output_dir + '/vector_joints.txt', 'w')
    fout.write(str(j_num) + '\n')
    for i in range(j_num):
        for p in range(0, len(model.J[i])):
            string = str(model.J[i][p])
            string = string.replace('[', '')
            string = string.replace(']', '') + ' '
            fout.write(string)
        fout.write('\n')
    fout.close()

    #print model.weights
    v_num = len(model.weights)
    fout = open(output_dir + '/vector_weights.txt', 'w')
    fout.write(str(v_num) + '\n')
    for i in range(v_num):
        fout.write(str(len(model.weights[i])) + '\n')
        for p in range(0, len(model.weights[i])):
            string = str(model.weights[i][p])
            string = string.replace('[', '')
            string = string.replace(']', '') + '\n'
            fout.write(string)
        fout.write('\n')
    fout.close()

    #save model params
    np.savetxt(output_dir + '/beta.txt', model.betas.r, fmt='%.6f')
    np.savetxt(output_dir + '/pose.txt', model.pose.r, fmt='%.6f')