示例#1
0
def guess_init(
        model,  # pylint: disable=too-many-locals, too-many-arguments
        focal_length,
        j2d,
        weights,
        init_pose,
        use_gt_guess):
    """Initialize the camera depth using the torso points."""
    cids = _np.arange(0, 12)
    j2d_here = j2d[cids]
    smpl_ids = [8, 5, 2, 1, 4, 7, 21, 19, 17, 16, 18, 20]
    # The initial pose is a t-pose with all body parts planar to the camera
    # (i.e., they have their maximum length).
    opt_pose = _ch.array(init_pose)  # pylint: disable=no-member
    (_, A_global) = _global_rigid_transformation(opt_pose,
                                                 model.J,
                                                 model.kintree_table,
                                                 xp=_ch)
    Jtr = _ch.vstack([g[:3, 3] for g in A_global])  # pylint: disable=no-member
    Jtr = Jtr[smpl_ids].r

    if use_gt_guess:
        # More robust estimate:
        # Since there is no fore'lengthening', only foreshortening, take the longest
        # visible body part as a robust estimate in the case of noise-free data.
        longest_part = None
        longest_part_length = -1.
        for conn in connections_lsp:
            if (conn[0] < 12 and conn[1] < 12 and weights[conn[0]] > 0.
                    and weights[conn[1]] > 0.):
                part_length_proj_gt = _np.sqrt(
                    _np.sum(_np.array(j2d_here[conn[0]] -
                                      j2d_here[conn[1]])**2,
                            axis=0))
                if part_length_proj_gt > longest_part_length:
                    longest_part_length = part_length_proj_gt
                    longest_part = conn
        #length2d = _np.sqrt(_np.sum(
        #    _np.array(j2d_here[longest_part[0]] - j2d_here[longest_part[1]])**2, axis=0))
        part_length_3D = _np.sqrt(
            _np.sum(_np.array(Jtr[longest_part[0]] - Jtr[longest_part[1]])**2,
                    axis=0))
        est_d = focal_length * (part_length_3D / longest_part_length)
    else:
        diff3d = _np.array([Jtr[9] - Jtr[3], Jtr[8] - Jtr[2]])
        mean_height3d = _np.mean(_np.sqrt(_np.sum(diff3d**2, axis=1)))
        diff2d = _np.array(
            [j2d_here[9] - j2d_here[3], j2d_here[8] - j2d_here[2]])
        mean_height2d = _np.mean(_np.sqrt(_np.sum(diff2d**2, axis=1)))
        f = focal_length  # pylint: disable=redefined-outer-name
        if mean_height2d == 0.:
            _LOGGER.warn(
                "Depth can not be correctly estimated. Guessing wildly.")
            est_d = 60.
        else:
            est_d = f * (mean_height3d / mean_height2d)
    init_t = _np.array([0., 0., est_d])
    return init_t
示例#2
0
def optimize_on_joints(j2d,
                       model,
                       cam,
                       img,
                       prior,
                       try_both_orient,
                       body_orient,
                       exp_logistic,
                       n_betas=10,
                       inner_penetration=False,
                       silh=None,
                       conf=None,
                       viz=False):
    """Run the optimization."""
    if silh is not None:
        raise NotImplementedError("Silhouette fitting is not supported in "
                                  "this code release due to dependencies on "
                                  "proprietary code for the "
                                  "distance computation.")
    t0 = _time()
    # define the mapping LSP joints -> SMPL joints
    if j2d.shape[0] == 14:
        cids = range(12) + [13]
    elif j2d.shape[0] == 91:
        cids = range(j2d.shape[0])
    else:
        raise Exception("Unknown number of joints: %d! Mapping not defined!" %
                        j2d.shape[0])
    # joint ids for SMPL
    smpl_ids = [8, 5, 2, 1, 4, 7, 21, 19, 17, 16, 18, 20]
    # weight given to each joint during optimization;
    if j2d.shape[0] == 14:
        weights = [1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1]
    else:
        weights = [1] * (len(smpl_ids) + len(landmark_mesh_91))
    # The non-skeleton vertex ids are added later.

    if try_both_orient:
        flipped_orient = _cv2.Rodrigues(body_orient)[0].dot(
            _cv2.Rodrigues(_np.array([0., _np.pi, 0]))[0])
        flipped_orient = _cv2.Rodrigues(flipped_orient)[0].ravel()
        orientations = [body_orient, flipped_orient]
    else:
        orientations = [body_orient]

    if try_both_orient:
        errors = []
    svs = []
    cams = []
    # rends = []
    for o_id, orient in enumerate(orientations):
        # initialize betas
        betas = _ch.zeros(n_betas)  # pylint: disable=no-member

        init_pose = _np.hstack((orient, prior.weights.dot(prior.means)))

        # 2D joint error term
        # make the SMPL joint depend on betas
        Jdirs = _np.dstack([
            model.J_regressor.dot(model.shapedirs[:, :, i])
            for i in range(len(betas))
        ])
        # pylint: disable=no-member
        J_onbetas = _ch.array(Jdirs).dot(betas) + model.J_regressor.dot(
            model.v_template.r)

        # instantiate the model
        sv = verts_decorated(trans=_ch.zeros(3),
                             pose=_ch.array(init_pose),
                             v_template=model.v_template,
                             J=model.J_regressor,
                             betas=betas,
                             shapedirs=model.shapedirs[:, :, :n_betas],
                             weights=model.weights,
                             kintree_table=model.kintree_table,
                             bs_style=model.bs_style,
                             f=model.f,
                             bs_type=model.bs_type,
                             posedirs=model.posedirs)

        # get joint positions as a function of model pose, betas and trans
        (_, A_global) = _global_rigid_transformation(sv.pose,
                                                     J_onbetas,
                                                     model.kintree_table,
                                                     xp=_ch)
        Jtr = _ch.vstack([g[:3, 3] for g in A_global]) + sv.trans

        if j2d.shape[0] == 14:
            # add the "fake" joint for the head
            head_id = _HEAD_REGR[0]
            Jtr = _ch.vstack((Jtr, sv[head_id]))
            if o_id == 0:
                smpl_ids.append(len(Jtr) - 1)
        else:
            # add the plain vertex IDs on the mesh surface.
            for vertex_id in landmark_mesh_91.values():
                Jtr = _ch.vstack((Jtr, sv[vertex_id]))
                # add the joint id
                # for SMPL it's the last one added
                if o_id == 0:
                    smpl_ids.append(len(Jtr) - 1)
        weights = _np.array(weights, dtype=_np.float64)
        if conf is not None:
            weights *= conf[cids]

        # we'll project the joints on the image plane
        cam.v = Jtr

        # data term: difference between observed and estimated joints
        obj_j2d = lambda w, sigma: (w * weights.reshape((-1, 1)) * _GMOf(
            (j2d[cids] - cam[smpl_ids]), sigma))
        # pose prior
        pprior = lambda w: w * prior(sv.pose)  # pylint: disable=cell-var-from-loop
        # joint angles prior
        # 55: left elbow, should bend -np.pi/2
        # 58: right elbow, should bend np.pi/2
        # 12: left knee, should bend np.pi/2
        # 15: right knee, should bend np.pi/2
        if exp_logistic:
            _LOGGER.info('USING LOGISTIC')
            # Skinny Logistic function. as 50-> inf we get a step function at
            # 0.1. (0.1) is a margin bc 0 is still ok.
            my_exp = lambda x: 1 / (1 + _ch.exp(100 * (0.1 + -x)))
        else:
            x_0 = 0  #10
            alpha = 10
            my_exp = lambda x: alpha * _ch.exp((x - x_0))  # pylint: disable=cell-var-from-loop

        obj_angle = lambda w: w * _ch.concatenate([
            my_exp(sv.pose[55]),  # pylint: disable=cell-var-from-loop
            my_exp(-sv.pose[58]),  # pylint: disable=cell-var-from-loop
            my_exp(-sv.pose[12]),  # pylint: disable=cell-var-from-loop
            my_exp(-sv.pose[15])
        ])  # pylint: disable=cell-var-from-loop

        if viz:
            from body.mesh.sphere import Sphere
            from body.mesh.meshviewer import MeshViewer
            import matplotlib.pyplot as plt

            # set up visualization
            # openGL window
            mv = MeshViewer(window_width=120, window_height=120)

            # and ids
            show_ids = _np.array(smpl_ids)[weights > 0]
            vc = _np.ones((len(Jtr), 3))
            vc[show_ids] = [0, 1, 0]

            plt.ion()

            def on_step(_):
                """Create visualization."""
                # show optimized joints in 3D
                # pylint: disable=cell-var-from-loop
                mv.set_dynamic_meshes([_Mesh(v=sv.r, f=[]),
                                       Sphere(center=cam.t.r,
                                              radius=.1).to_mesh()] \
                        + [Sphere(center=jc, radius=.01).to_mesh(vc[ijc])
                           for ijc, jc in enumerate(Jtr.r)])
                plt.figure(1, figsize=(10, 10))
                plt.subplot(1, 2, 1)
                # show optimized joints in 2D
                tmp_img = img.copy()
                for coord, target_coord in zip(
                        _np.around(cam.r[smpl_ids]).astype(int),
                        _np.around(j2d[cids]).astype(int)):
                    if (coord[0] < tmp_img.shape[1] and coord[0] >= 0
                            and coord[1] < tmp_img.shape[0] and coord[1] >= 0):
                        _cv2.circle(tmp_img, tuple(coord), 3, [0, 0, 255])
                    if (target_coord[0] < tmp_img.shape[1]
                            and target_coord[0] >= 0
                            and target_coord[1] < tmp_img.shape[0]
                            and target_coord[1] >= 0):
                        _cv2.circle(tmp_img, tuple(target_coord), 3,
                                    [0, 255, 0])
                plt.imshow(tmp_img)
                plt.draw()
                plt.show()

            on_step(_)
        else:
            on_step = None

        sp = _SphereCollisions(pose=sv.pose,
                               betas=sv.betas,
                               model=model,
                               regs=_REGRESSORS)
        sp.no_hands = True
        # configuration used with conf joints
        opt_weights = zip([4.04 * 1e2, 4.04 * 1e2, 57.4, 4.78],
                          [1e2, 5 * 1e1, 1e1, .5 * 1e1])

        for stage, (w, wbetas) in enumerate(opt_weights):
            _LOGGER.info('stage %01d', stage)
            objs = {}
            #if stage < 2:
            objs['j2d'] = obj_j2d(1., 100)  # TODO: evaluate.

            objs['pose'] = pprior(w)

            # WEIGHT FOR ANGLE
            if exp_logistic:
                # Set to high weight always.
                objs['pose_exp'] = obj_angle(5 * 1e3)
            else:
                objs['pose_exp'] = obj_angle(0.317 * w)

            objs['betas'] = wbetas * betas
            if inner_penetration:
                objs['sph_coll'] = 1e3 * sp
            try:
                _ch.minimize(objs.values(),
                             x0=[sv.betas, sv.pose],
                             method='dogleg',
                             callback=on_step,
                             options={
                                 'maxiter': 100,
                                 'e_3': .0001,
                                 'disp': 0
                             })
            except AssertionError:
                # Divergence detected.
                _LOGGER.warn("Diverging optimization! Breaking!")
                break
        t1 = _time()
        _LOGGER.info('elapsed %.05f', (t1 - t0))
        if try_both_orient:
            errors.append((objs['j2d'].r**2).sum())
        svs.append(sv)
        cams.append(cam)
        # rends.append(rend)
    if try_both_orient and errors[0] > errors[1]:
        choose_id = 1
    else:
        choose_id = 0
    if viz:
        plt.ioff()
    return (svs[choose_id], cams[choose_id].r, cams[choose_id].t.r,
            cams[choose_id].rt.r)
示例#3
0
def initialize_camera(
        model,  # pylint: disable=too-many-arguments, too-many-locals
        j2d,
        center,
        img,
        init_t,
        init_pose,
        conf,
        is_gt,
        flength=1000.,
        pix_thsh=25.,
        viz=False):
    """Initialize the camera."""
    # try to optimize camera translation and rotation based on torso joints
    # right shoulder, left shoulder, right hip, left hip
    torso_cids = _CID_TORSO
    torso_smpl_ids = [2, 1, 17, 16]

    # initialize camera rotation and translation
    rt = _ch.zeros(3)  # pylint: disable=no-member
    _LOGGER.info('Initializing camera: guessing translation via similarity')
    init_t = guess_init(model, flength, j2d, conf, init_pose, is_gt)
    t = _ch.array(init_t)  # pylint: disable=no-member

    # check how close the shoulders are
    try_both_orient = _np.linalg.norm(j2d[8] - j2d[9]) < pix_thsh

    opt_pose = _ch.array(init_pose)  # pylint: disable=no-member
    (_, A_global) = _global_rigid_transformation(opt_pose,
                                                 model.J,
                                                 model.kintree_table,
                                                 xp=_ch)
    Jtr = _ch.vstack([g[:3, 3] for g in A_global])  # pylint: disable=no-member

    # initialize the camera
    cam = _ProjectPoints(f=_np.array([flength, flength]),
                         rt=rt,
                         t=t,
                         k=_np.zeros(5),
                         c=center)

    # we are going to project the SMPL joints
    cam.v = Jtr

    if viz:
        viz_img = img.copy()

        # draw the target joints
        for coord in _np.around(j2d).astype(int):
            if (coord[0] < img.shape[1] and coord[0] >= 0
                    and coord[1] < img.shape[0] and coord[1] >= 0):
                _cv2.circle(viz_img, tuple(coord), 3, [0, 255, 0])

        import matplotlib.pyplot as plt
        plt.ion()

        # draw optimized joints at each iteration
        def on_step(_):
            """Draw a visualization."""
            plt.figure(1, figsize=(5, 5))
            plt.subplot(1, 1, 1)
            viz_img = img.copy()
            for coord in _np.around(cam.r[torso_smpl_ids]).astype(int):
                if (coord[0] < viz_img.shape[1] and coord[0] >= 0
                        and coord[1] < viz_img.shape[0] and coord[1] >= 0):
                    _cv2.circle(viz_img, tuple(coord), 3, [0, 0, 255])
            plt.imshow(viz_img[:, :, ::-1])
            plt.draw()
            plt.show()
    else:
        on_step = None
    free_variables = [cam.t, opt_pose[:3]]  # pylint: disable=no-member
    _ch.minimize(
        [(j2d[torso_cids] - cam[torso_smpl_ids]).T * conf[torso_cids], 1e2 *
         (cam.t[2] - init_t[2])],  # pylint: disable=no-member
        # The same for verbose output.
        #{'cam': (j2d[torso_cids] - cam[torso_smpl_ids]).T * conf[torso_cids],
        # # Reduce the weight here to avoid the 'small people' problem.
        # 'cam_t': 1e2*(cam.t[2]-init_t[2])},  # pylint: disable=no-member
        x0=free_variables,
        method='dogleg',
        callback=on_step,
        options={
            'maxiter': 100,
            'e_3': .0001,
            'disp': 0
        })
    if viz:
        plt.ioff()
    return (cam, try_both_orient, opt_pose[:3].r)
示例#4
0
def get_mesh_to_deformation(filename, model, cam, label_folder):

    image = cv2.imread(filename, -1)
    #if image.shape[2] != 4:
    #    print "No segmented image "
    #    exit()

    mesh = copy(_TEMPLATE_MESH)
    mesh.vc = _COLORS['pink']
    # render ply
    model.betas[:len(cam['betas'])] = cam['betas']
    model.pose[:] = cam['pose']
    model.trans[:] = cam['trans']
    mesh.v = model.r

    # transformation for each v [4,4,6890]

    inv_trasformation = np.zeros((4, 4, 6890))

    (A, A_global) = _global_rigid_transformation(model.pose,
                                                 model.J,
                                                 model.kintree_table,
                                                 xp=ch)
    T = A.dot(model.weights.T)
    T0 = np.array(T)

    for i in range(6890):
        m_inv = np.linalg.inv(T0[:, :, i])
        inv_trasformation[:, :, i] = m_inv
        #inv_trasformation.append(m_inv.tolist())

    #pdb.set_trace()

    contor_list = []
    list_path = filename.split("/")
    path = ''.join(e + "/" for e in list_path[:-2])

    todo_vertices = [0] * mesh.v.shape[0]
    new_vertices_u_v = []
    vertices_u_v = []
    dist_vertices = [0.0] * mesh.v.shape[0]

    my_normals = np.array(
        compute_normals.compute_normals(mesh.v.copy().astype(float).tolist(),
                                        mesh.f.copy().astype(int).tolist()))

    for v in range(mesh.v.shape[0]):
        vtx1 = (((mesh.v[v, 0] + cam['t'][0]) * cam['f']) /
                (mesh.v[v, 2] + cam['t'][2]) + image.shape[1] / 2.0)
        vty1 = (((mesh.v[v, 1] + cam['t'][1]) * cam['f']) /
                (mesh.v[v, 2] + cam['t'][2]) + image.shape[0] / 2.0)
        new_vertices_u_v.append([vtx1, vty1, mesh.v[v, 2]])
        vertices_u_v.append([vtx1, vty1, mesh.v[v, 2]])

    image_label = cv2.imread(path + label_folder + list_path[-1][:-4] + ".png",
                             0)

    to_draw = np.ones(image.shape, dtype=np.uint8)

    for i in range(14):

        label = np.where(image_label == label_map_cnn[i + 1],
                         np.ones(image_label.shape, dtype=np.uint8) * 255,
                         np.zeros(image_label.shape, dtype=np.uint8))
        contours, hierarchy = cv2.findContours(label, cv2.RETR_TREE,
                                               cv2.CHAIN_APPROX_SIMPLE)
        to_draw = np.zeros(image.shape, dtype=np.uint8)
        cv2.drawContours(to_draw, contours, -1, label_colours[i], 3)
        #cv2.imshow('ImageWindow', label)
        #cv2.waitKey()
        for s, c in enumerate(contours):
            for p, point in enumerate(c):
                dist = limit_deformation[i + 1]
                id_close = -1
                for v in range(mesh.v.shape[0]):
                    if ((int(pose_partes[v]) == (i + 1))):
                        d = distancia(
                            vertices_u_v[v],
                            [point[0][0], point[0][1], vertices_u_v[v][2]])
                        d = (d * vertices_u_v[v][2]) / cam['f']
                        if d < dist:
                            id_close = v
                            dist = d

                if id_close > -1 and intersect_is_valid(
                        s, p, contours, vertices_u_v[id_close], point[0]):
                    if dist > dist_vertices[id_close]:
                        dist_vertices[id_close] = dist
                        todo_vertices[id_close] = 1
                        new_vertices_u_v[id_close][0] = point[0][0]
                        new_vertices_u_v[id_close][1] = point[0][1]
                        #cv2.line(image, (int(new_vertices_u_v[id_close][0]), int(new_vertices_u_v[id_close][1])), (int(vertices_u_v[id_close][0]), int(vertices_u_v[id_close][1])), label_colours[i], 2)

        #cv2.imshow('ImageWindow', image)
        #cv2.waitKey()

    new_vertices = mesh.v.copy().astype(float).tolist()

    label_map_cnn_color = [1, 6, 19, 1, 12, 13, 11, 5, 4, 7, 10, 14, 13, 3, 8]

    #image = np.ones_like(image)*255

    for v in range(mesh.v.shape[0]):
        if todo_vertices[v] == 1:
            new_vertices[v][0] = (
                (new_vertices_u_v[v][0] - image.shape[1] / 2.0) *
                (mesh.v[v, 2] + cam['t'][2])) / cam['f'] - cam['t'][0]
            new_vertices[v][1] = (
                (new_vertices_u_v[v][1] - image.shape[0] / 2.0) *
                (mesh.v[v, 2] + cam['t'][2])) / cam['f'] - cam['t'][1]
            lineThickness = 2
            #cv2.line(image, (int(new_vertices_u_v[v][0]), int(new_vertices_u_v[v][1])), (int(vertices_u_v[v][0]), int(vertices_u_v[v][1])), label_colours[label_map_cnn_color[int(pose_partes[v])]], lineThickness)

    #cv2.imwrite(filename + "deform.jpg", image)

    return mesh.v.copy().astype(float).tolist(), new_vertices, mesh.f.copy(
    ).astype(int).tolist(), todo_vertices, inv_trasformation