示例#1
0
                                                models_sym[obj_id])
                            ]

                        elif p['error_type'] in ['ad', 'add', 'adi']:
                            if not spheres_overlap:
                                # Infinite error if the bounding spheres do not overlap. With
                                # typically used values of the correctness threshold for the AD
                                # error (e.g. k*diameter, where k = 0.1), such pose estimates
                                # would be considered incorrect anyway.
                                e = [float('inf')]
                            else:
                                if p['error_type'] == 'ad':
                                    if obj_id in dp_model['symmetric_obj_ids']:
                                        e = [
                                            pose_error.adi(
                                                R_e, t_e, R_g, t_g,
                                                models[obj_id]['pts'])
                                        ]
                                    else:
                                        e = [
                                            pose_error.add(
                                                R_e, t_e, R_g, t_g,
                                                models[obj_id]['pts'])
                                        ]

                                elif p['error_type'] == 'add':
                                    e = [
                                        pose_error.add(R_e, t_e, R_g, t_g,
                                                       models[obj_id]['pts'])
                                    ]
示例#2
0
def find_closest(Re, te, Rs, ts, metric, pts, syms, r2):
    """
    Given a pose estimate [Re, te], finds the closest plausible pose in [Rs, ts] wrt [metric].
    :param Re: Rotation estimate.
    :param te: translation estimate.
    :param Rs: Plausible rotations.
    :param ts: Plausible translations.
    :param metric: Pose-error function to be used. Valid choices are [te, frobenius, add, adi, mssd].
    :param pts: Point cloud [xyz] of the target object.
    :param syms: Set of transformations representing the symmetric poses of the object. Used by [frobenius, adi, mssd].
    :param r2: Scaling parameter for the rotation term in the Frobenius-based metric.
    :return: Rotation, translation and distance wrt [metric] of the closest plausible pose.
    """

    if metric == 'te':
        dist = np.linalg.norm(ts.reshape(-1, 3) - te.reshape(-1, 3), axis=1, ord=2)
    elif metric == 'frobenius':
        # eval metric defined in Brégier et al., "Defining the Pose of any 3D Rigid Object and an Associated Distance"
        # dist = np.sqrt(np.linalg.norm(ts.reshape(-1, 3) - te.reshape(-1, 3), axis=1, ord=2)**2
        #                + r2*np.linalg.norm(Rs - Re, axis=(1, 2), ord='fro')**2)

        # symmetric version
        dists = []
        for sym in syms:
            # symmetric pose candidate
            Rsym = Re @ sym['R']
            tsym = (Re @ sym['t']).reshape(3, 1) + te.reshape(3, 1)

            dists.append(np.sqrt(np.linalg.norm(ts.reshape(-1, 3) - tsym.reshape(-1, 3), axis=1, ord=2) ** 2
                                 + r2 * np.linalg.norm(Rs - Rsym, axis=(1, 2), ord='fro') ** 2))
        dist = np.min(dists, axis=0)

    elif metric == 'add':
        # serial evaluation (takes twice as long)
        # dist = [error.add(R.reshape(3, 3), t.reshape(3, 1), Re, te, pts) for R, t in zip(Rs, ts.T)]

        # precompute relative rotation and relative translation of all plausible poses to speed-up computation
        R_ = (Re - Rs).reshape(-1, 3, 3)
        t_ = (te.reshape(1, 3) - ts.reshape(-1, 3))
        dist = [np.linalg.norm(R @ pts.T + t.reshape(3, 1), axis=0, ord=2).mean() for R, t in zip(R_, t_)]
    elif metric == 'adi':
        dist = [error.adi(R.reshape(3, 3), t.reshape(3, 1), Re, te, pts) for R, t in zip(Rs, ts)]
    elif metric == 'mssd':
        # serial evaluation (takes twice as long)
        # dist = [error.mssd(R.reshape(3, 3), t.reshape(3, 1), Re, te, pts, syms) for R, t in zip(Rs, ts)]

        dists = []
        for sym in syms:
            # symmetric pose candidate
            Rsym = Re @ sym['R']
            tsym = (Re @ sym['t']).reshape(3, 1) + te.reshape(3, 1)

            # precompute relative rotation and relative translation of all plausible poses to speed-up computation
            R_ = (Rsym - Rs).reshape(-1, 3, 3)
            t_ = (tsym.reshape(1, 3) - ts.reshape(-1, 3))
            dists.append([np.linalg.norm(R @ pts.T + t.reshape(3, 1), axis=0, ord=2).max() for R, t in zip(R_, t_)])
        dist = np.min(dists, axis=0)
    else:
        raise ValueError(f"Parameter 'metric' must be one of 'te', 'frobenius', 'add', 'adi' or 'mssd'.")

    closest = np.argmin(dist)
    return Rs[closest], ts[closest], np.min(dist)