Esempio n. 1
0
def select_gaps(argv):
    pjoin = os.path.join
    parser = argparse.ArgumentParser("Select gaps")
    parser = parser_video(parser)
    parser.add_argument('--select-gaps', action='store_true')
    parser.add_argument("-s",
                        "--d-scenelets",
                        dest='s',
                        type=argparse_check_exists,
                        help="Folder containing original PiGraphs scenelets")
    args = parser.parse_args(argv)
    d = os.path.join(args.video, args.d)
    assert os.path.exists(d), "does not exist: %s" % d

    if os.path.isdir(args.video):
        if args.video.endswith(os.sep):
            args.video = args.video[:-1]
    name_query = args.video.split(os.sep)[-1]
    assert len(name_query), args.video.split(os.sep)
    p_query = pjoin(args.video, "skel_%s_unannot.json" % name_query) \
        if os.path.isdir(args.video) else args.video
    assert p_query.endswith('.json'), "Need a skeleton file"

    # load initial video path (local poses)
    query = Scenelet.load(p_query, no_obj=True)
    frame_ids = query.skeleton.get_frames()
    centroids = Skeleton.get_resampled_centroids(start=frame_ids[0],
                                                 end=frame_ids[-1],
                                                 old_frame_ids=frame_ids,
                                                 poses=query.skeleton.poses)

    depths_times_charnesses = []
    skeleton = Skeleton()
    depths = []
    for p in sorted(os.listdir(d)):
        ch = float(p.split('charness')[1][1:])
        d_time = pjoin(d, p)
        p_skel = next(
            f for f in os.listdir(d_time) if os.path.isfile(pjoin(d_time, f))
            and f.startswith('skel') and f.endswith('json') and '_00' in f)
        sclt = Scenelet.load(pjoin(d_time, p_skel))
        mn, mx = sclt.skeleton.get_frames_min_max()
        frame_id = mn + (mx - mn) // 2
        if query.skeleton.has_pose(frame_id):
            pos_3d = query.skeleton.get_centroid_3d(frame_id)
        else:
            lin_id = frame_id - frame_ids[0]
            pos_3d = centroids[lin_id, :]
        depth = np.linalg.norm(pos_3d)
        depths.append(depth)
        depths_times_charnesses.append(
            DepthTimeCharness(depth=depth, frame_id=frame_id, charness=ch))
    hist, bin_edges = np.histogram(depths, bins=5)
    lg.debug("hist: %s" % hist)
    lg.debug("edges: %s" % bin_edges)
Esempio n. 2
0
def get_pose_distance(query3d, path_match, gap):
    skel_q = query3d.skeleton
    mid_frame = gap[0] + (gap[1] - gap[0]) // 2
    frame_q = min((frame_id for frame_id in skel_q.get_frames()),
                  key=lambda frame_id: abs(frame_id - mid_frame))
    time = skel_q.get_time(frame_id=frame_q)
    print('Closest to {} is {} with time {}'.format(mid_frame, frame_q, time))
    match = Scenelet.load(path_match)
    skel_m = match.skeleton
    frame_m = skel_m.find_time(time=time)
    time_m = skel_m.get_time(frame_id=frame_m)
    print('Closest match is {} with time {}'.format(frame_m, time_m))

    diffs = []
    for frame_id in range(frame_q - 1, frame_q + 2):
        if not skel_q.has_pose(frame_id):
            print('Skipping frame_id {} in query because missing'.format(
                frame_id))
            continue
        _time_q = skel_q.get_time(frame_id=frame_id)
        _frame_m = skel_m.find_time(time=_time_q)
        _time_m = skel_m.get_time(frame_id=_frame_m)
        if abs(_time_m - _time_q) > 1.:
            print('Skipping matched time of {} because too far from {}'.format(
                _time_m, _time_q))
            continue
        pose_q = skel_q.get_pose(frame_id=frame_id)
        pose_m = skel_m.get_pose(frame_id=_frame_m)
        diff = get_pose_diff(pose_q=pose_q, pose_m=pose_m)
        print('Diff: {}'.format(diff))
        diffs.append(diff)

    # return np.mean(diffs), len(diffs) > 0
    return np.max(diffs), len(diffs) > 0
Esempio n. 3
0
def ipol_ik(p_scenelet, postfix):
    """Uses Blender's IK engine to interpolate 3D joint positions in time.

    Sphere positions are tied to Rig endpoints, and these endpoints
    will be as close as possible to the noisy targets. Hence the Sphere
    positions are the ones we save as interpolated 3D joint positions.

    The method will try to preserve all, non-skeleton related
    information in the scenelet by only overwriting its skeleton.
    Visibility and confidence will be discarded (TODO:?).

    Args:
        p_scenelet (str):
            Path to scenelet containing skeleton to interpolate.
        postfix (str):
            Tag to append to skeleton name before the json extension.
    Returns:
        o_path (str): Path, where it saved the interpolated version.

    """

    # Load skeleton
    assert os.path.exists(p_scenelet), "Does not exist: %s" % p_scenelet
    scenelet = Scenelet.load(p_scenelet)

    # Prepare animation time
    bpy.context.scene.render.fps = 10
    bpy.context.scene.render.fps_base = 1

    # Call rig importer
    import_skeleton_animation(
        skeleton=scenelet.skeleton,
        name='Output',
        add_camera=False,
        add_trajectory=False,
        time_scale=0.1,
        skeleton_transparency=0,
    )

    # Move head back to top (2D marker is at tip of head, but visually,
    # it looks better, if it's rendered with the center of the head around
    # the nose)
    for obj in bpy.data.objects:
        if obj.name.endswith("HEAD.Sphere"):
            cnstr = next(c for c in obj.constraints
                         if c.type == 'COPY_LOCATION')
            cnstr.head_tail = 1.

    # Extract Sphere endpoints as the new skeleton positions
    scenelet.skeleton = extract_skeleton(scene=bpy.context.scene)

    # Save to disk
    stem, ext = os.path.splitext(p_scenelet)
    o_path = "%s_%s.json" % (stem, postfix)
    scenelet.save(o_path, save_obj=True)

    # Return path
    return o_path
Esempio n. 4
0
def compare_other_to_gt():
    scene = bpy.context.scene
    assert 'postfix' in globals(), "Need postfix parameter"
    name_scene = bpy.path.abspath('//').split(os.sep)[-3]
    if 'object_correspondences' not in globals():
        object_correspondences = get_correspondences(name_scene, postfix)
    p_gt = bpy.path.abspath("//../quant/skel_gt.json")
    sclt_gt = Scenelet.load(p_gt)

    p_other = bpy.path.abspath("//../quant/skel_%s.json" % postfix)
    if True or not os.path.exists(p_other):
        frame_ids = find_keyframes(lambda ob: ob.name.startswith('Output.'))
        sclt_other = save_annotated_scenelet(sc_path=p_other,
                                             scene=scene,
                                             frame_ids=frame_ids)
    else:
        sclt_other = Scenelet.load(p_other)
    compare_scenes(sclt_other, sclt_gt, object_correspondences)
Esempio n. 5
0
def read_scenelets(d_scenelets, limit=0):
    pjoin = os.path.join

    # get full pigraph scenes
    p_scenelets = [
        pjoin(d_scenelets, d) for d in os.listdir(d_scenelets)
        if os.path.isdir(pjoin(d_scenelets, d))
    ]
    # for
    p_scenelets = [
        pjoin(d, f) for d in p_scenelets for f in os.listdir(d)
        if f.startswith('skel') and f.endswith('.json')
    ]

    out = []
    for p_scenelet in p_scenelets:
        lg.info("Reading %s" % p_scenelet)
        out.append(Scenelet.load(p_scenelet))
        if limit != 0 and len(out) >= limit:
            break

    return out
Esempio n. 6
0
def main(argv):
    pjoin = os.path.join

    parser = argparse.ArgumentParser("")
    parser.add_argument('d', type=_check_exists, help="Input directory")
    parser.add_argument('db',
                        type=_check_exists,
                        help="Path to scenelets database")
    parser.add_argument(
        '-o',
        '--opt-folder',
        help="Which optimization output to process. Default: opt1",
        default='opt1')
    parser.add_argument('-limit',
                        type=int,
                        help="How many scenelets to aggregate.",
                        default=3)
    parser.add_argument('--c-threshold',
                        help='Distance threshold. Default: 0.3',
                        type=float,
                        default=0.3)
    parser.add_argument('--d-threshold',
                        help='Distance threshold. Default: 0.4',
                        type=float,
                        default=0.4)
    args = parser.parse_args(argv)
    path_scenes_root = os.path.normpath(pjoin(args.d, os.pardir))
    print("Working with %s" % args.d)
    d = pjoin(args.d, args.opt_folder)

    name_query = d.split(os.sep)[-2]
    query3d = Scenelet.load(
        os.path.join(args.d, 'skel_{:s}_unannot.json'.format(name_query)))
    n_actors = query3d.skeleton.n_actors  # type: int

    log = LoggedSequence()
    elements = [[], [], []]
    spans = []
    above = []
    for p in sorted(os.listdir(d)):
        d_time = pjoin(d, p)
        if not os.path.isdir(d_time) or 'bak' in p:
            continue
        parts = p.split('_')
        start = int(parts[0])
        end = int(parts[-1])

        sum_charness = 0.
        sum_weight = 0.
        sum_charness_unw = 0.
        sum_weight_unw = 0
        diff_succ, diff = False, 100.
        for f in glob.iglob("%s/skel_%s_*.json" % (d_time, name_query)):
            rank = int(os.path.splitext(f)[0].rpartition('_')[-1])
            if rank >= args.limit:
                continue
            # print(f)
            data = json.load(open(f, 'r'))
            charness = data['charness']
            weight = max(0., .1 - data['score_fit'])
            sum_charness += weight * charness
            sum_weight += weight
            sum_charness_unw += charness
            elements[sum_weight_unw].append(charness)
            sum_weight_unw += 1

            if rank == 0:
                diff, diff_succ = get_pose_distance(query3d=query3d,
                                                    path_match=f,
                                                    gap=(start, end))

        if sum_weight > 0.:
            sum_charness /= sum_weight
        if sum_weight_unw > 0.:
            sum_charness_unw /= sum_weight_unw
        frame_id = (start + end) // 2
        actor_id = query3d.skeleton.get_actor_id(frame_id=frame_id) \
            if n_actors > 1 else 0

        spans.append(
            Span(start, end, sum_charness, sum_charness_unw,
                 actor_id=actor_id))

        # check for pose replacement
        if diff_succ and diff > args.d_threshold:
            # time = query3d.skeleton.get_time(frame_id=frame_id)
            above.append(Span2(start=frame_id, end=frame_id, value=diff))

        if diff_succ:
            log.add_point(value=diff, time=frame_id)

    for actor_id in range(n_actors):
        cs, span_ids = zip(*[(span.charness, span_id)
                             for span_id, span in enumerate(spans)
                             if span.actor_id == actor_id])
        cs2 = gaussian_filter(cs, sigma=2.5).tolist()

        for smoothed, span_id in zip(cs2, span_ids):
            spans[span_id].smoothed_charness = smoothed

    plt.figure()
    plt.plot(cs, label="orig")
    plt.plot([span.smoothed_charness for span in spans], label="smoothed")
    # c0 = [span.charness_unw for span in spans]
    # plt.plot(c0, 'o-', label="unweighted")
    # for sigma in [2.5]:
    #     cs2 = gaussian_filter(cs, sigma=sigma)
    #     plt.plot(cs2, '+-', label="%f" % sigma)

    # for i, elem in enumerate(elements):
    #     plt.plot(elem, 'x-', label="cand%d" % i)
    plt.legend()
    # plt.show()
    p_graph = os.path.join(args.d, 'charness2.svg')
    plt.savefig(p_graph)

    log.plot(path_root=args.d)

    spans = sorted(spans, key=lambda s: s.smoothed_charness, reverse=True)

    chosen = [spans[0]]
    for span_id in range(1, len(spans)):
        span = spans[span_id]
        overlap = next((c for c in chosen if span.overlaps(c)), None)
        if overlap is not None:
            # print("Skipping %s because overlaps %s" % (span, overlap))
            continue
        elif span.start == query3d.skeleton.get_frames()[0] \
                or span.end == query3d.skeleton.get_frames()[-1]:
            print("Skipping %s because first/last frame." % span)
            continue
        else:
            chosen.append(span)

    # Spans to replace, because of quality, if not replaced already
    spans_r = group_spans(above=above)
    chosen, spans_r_filtered = filter_spans_to_replace(
        spans=spans_r, chosen=chosen, c_threshold=args.c_threshold)
    print('Filtered: {}\nchosen: {}'.format(spans_r_filtered, chosen))
    # keep at least one characteristic pose for each actor
    # actors_output = set()
    p_cmd = os.path.join(args.d, 'gap_command_new.sh')
    with open(p_cmd, 'w') as f:
        f.write('BATCH_SIZE=8\n\n')
        for actor_id in range(n_actors):
            f.write('######\n# Actor {:d}\n######\n\n'.format(actor_id))
            for span in chain(chosen, spans_r_filtered):
                if not span.actor_id == actor_id:
                    continue
                surr = find_surrounding(span, spans)
                cmd = construct_command(name_query=name_query,
                                        span=span,
                                        tc=args.c_threshold,
                                        surr=surr,
                                        path_scenes_root=path_scenes_root,
                                        path_scenelets_db=args.db)

                if isinstance(span.charness, float):
                    f.write("# charness: %g\n" % span.charness)

                # Comment out if too low
                # if span.charness < args.c_threshold \
                #         and actor_id in actors_output:
                # actors_output.add(actor_id)

                f.write('{}\n\n'.format(cmd))
            f.write('\n\n')
Esempio n. 7
0

if __name__ == 'add_constraint_to_spheres':
    add_constraint_to_spheres()
elif __name__ == 'save_annotated_scenelet':
    assert 'postfix' in globals(), "Need postfix parameter"
    print("abspath: %s" % bpy.path.abspath('//'))
    name_scene = bpy.path.abspath('//').split(os.sep)[-3]
    scene = bpy.context.scene

    # Aron commented out in Jan2019
    if 'object_correspondences' not in globals():
        object_correspondences = get_correspondences(name_scene)
    p_file = bpy.path.abspath('//../output/skel_output.json')
    assert os.path.exists(p_file), "Does not exist: %s" % p_file
    sclt_ours = Scenelet.load(p_file)
    p_out = bpy.path.abspath('//../quant/skel_output.json')
    sclt_ours.save(p_out, save_obj=True)

    p_gt = bpy.path.abspath("//../quant/skel_%s.json" % postfix)
    if not os.path.exists(p_gt):
        if 'frame_ids' not in globals():
            frame_ids = get_frame_ids(name_scene)
        # frame_ids = find_keyframes(lambda ob: ob.name.startswith('Output.'))
        sclt_gt = save_annotated_scenelet(sc_path=p_gt,
                                          scene=scene,
                                          frame_ids=frame_ids,
                                          frame_multiplier=frame_multiplier,
                                          time_multiplier=time_multiplier)
    else:
        print("NOT OVERWRITING GT")
Esempio n. 8
0
def optimize_path(skel_ours,
                  skel_ours_2d,
                  images,
                  intrinsics,
                  path_skel,
                  ground_rot,
                  shape_orig=None,
                  use_huber=False,
                  weight_smooth=0.01,
                  show=False,
                  frames_ignore=None,
                  resample=True,
                  depth_init=10.,
                  p_constraints=None,
                  smooth_mode=SmoothMode.ACCEL):
    """Optimize 3D path so that it matches the 2D corresponding observations.

    Args:
        skel_ours (Skeleton):
            3D skeleton from LFD.
        skel_ours_2d (Skeleton):
            2D feature points from LFD.
        images (dict):
            Color images for debug, keyed by frame_ids.
        camera_name (str):
            Initialize intrinsics matrix based on name of camera.
        path_skel (str):
            Path of input file from LFD on disk, used to create paths for
            intermediate result.
        shape_orig (tuple):
            Height and width of original images before LFD scaled them.
        use_huber (bool):
            Deprecated.
        weight_smooth (float):
            Smoothness term weight.
        winsorize_limit (float):
            Outlier detection parameter.
        show (bool):
            Show debug visualizations.
        frames_ignore (set):
            Deprecated.
        resample (bool):
            Fill in missing poses by interpolating using Blender's IK.
        depth_init (float):
            Initial depth for LFD poses.
        p_constraints (str):
            Path to 3D constraints scenelet file.
        smooth_mode (SmoothMode):
            Smooth velocity or acceleration.
    """

    # scale 2D detections to canonical camera coordinates
    np_poses_2d = \
        skel_ours_2d.poses[:, :2, :] \
        - np.expand_dims(intrinsics[:2, 2], axis=1)
    np_poses_2d[:, 0, :] /= intrinsics[0, 0]
    np_poses_2d[:, 1, :] /= intrinsics[1, 1]

    n_frames = skel_ours.poses.shape[0]
    np_translation = np.zeros(shape=(n_frames, 3), dtype=np.float32)
    np_translation[:, 1] = -1.
    np_translation[:, 2] = \
        np.random.uniform(-depth_init * 0.25, depth_init * 0.25,
                          np_translation.shape[0]) \
        + depth_init
    np_rotation = np.zeros(shape=(n_frames, 3), dtype=np.float32)

    frame_ids = np.array(skel_ours.get_frames(), dtype=np.float32)
    np_visibility = skel_ours_2d.get_confidence_matrix(frame_ids=frame_ids,
                                                       dtype='f4')

    if p_constraints is not None:
        sclt_cnstr = Scenelet.load(p_constraints)
        np_cnstr_mask = np.zeros(shape=(len(frame_ids),
                                        Joint.get_num_joints()),
                                 dtype=np.float32)
        np_cnstr = np.zeros(shape=(len(frame_ids), 3, Joint.get_num_joints()),
                            dtype=np.float32)
        for frame_id, confs in sclt_cnstr.confidence.items():
            lin_id = None
            for j, conf in confs.items():
                if conf > 0.5:
                    if lin_id is None:
                        lin_id = next(
                            lin_id_
                            for lin_id_, frame_id_ in enumerate(frame_ids)
                            if frame_id_ == frame_id)
                    np_cnstr_mask[lin_id, j] = conf
                    np_cnstr[lin_id, :, j] = \
                        sclt_cnstr.skeleton.get_joint_3d(
                          joint_id=j, frame_id=frame_id)
    else:
        np_cnstr_mask = None
        np_cnstr = None

    spans = skel_ours.get_actor_empty_frames()
    dt = frame_ids[1:].astype(np.float32) \
         - frame_ids[:-1].astype(np.float32)
    dt_pos_inv = np.reciprocal(dt, dtype=np.float32)
    dt_vel_inv = np.divide(np.float32(2.), dt[1:] + dt[:-1])
    # ensure smoothness weight multipliers are not affected by
    # actor-transitions
    if skel_ours.n_actors > 1 and len(spans):
        for lin_id in range(len(dt)):
            frame_id0 = frame_ids[lin_id]
            frame_id1 = frame_ids[lin_id + 1]
            span = next((span_ for span_ in spans if span_[0] == frame_id0),
                        None)
            if span is not None:
                assert frame_id1 == span[1], "No"
                dt[lin_id] = 0.
                dt_pos_inv[lin_id] = 0.
                dt_vel_inv[lin_id] = 0.
                dt_vel_inv[lin_id - 1] = 1. / dt[lin_id - 1]

    forwards = np.array([
        skel_ours.get_forward(frame_id, estimate_ok=True, k=0)
        for frame_id in skel_ours.get_frames()
    ])
    # from alignment import get_angle
    # xs = np.hstack((
    # np.ones(shape=(len(forwards), 1)),
    # np.zeros(shape=(len(forwards), 2))
    # ))
    # print(xs.shape)
    print(forwards.shape)
    unit_x = np.array((1., 0., 0.))
    np_angles = [-np.arctan2(forward[2], forward[0]) for forward in forwards]
    print(forwards, np_angles)
    # ank_diff = \
    #     np.exp(
    #        -2. * np.max(
    #           [
    #               np.linalg.norm(
    #                  (skel_ours.poses[1:, :, joint]
    #                   - skel_ours.poses[:-1, :, joint]).T
    #                  * dt_pos_inv, axis=0
    #               ).astype(np.float32)
    #               for joint in {Joint.LANK, Joint.RANK}
    #           ],
    #           axis=0
    #        )
    #     )
    # assert ank_diff.shape == (skel_ours.poses.shape[0]-1,), \
    #     "Wrong shape: %s" % repr(ank_diff.shape)

    # cam_angle = [np.deg2rad(-8.)]
    assert np.isclose(ground_rot[1], 0.) and np.isclose(ground_rot[2], 0.), \
        "Assumed only x rotation"
    # assert ground_rot[0] <= 0, "Negative means looking down, why looknig up?"
    cam_angle = [np.deg2rad(ground_rot[0])]
    # assert False, "Fixed angle!"
    device_name = '/gpu:0' if tf.test.is_gpu_available() else '/cpu:0'
    devices = {device_name}
    for device in devices:
        with Timer(device, verbose=True):
            graph = tf.Graph()
            with graph.as_default(), tf.device(device):
                tf_visibility = tf.Variable(np.tile(np_visibility, (1, 2, 1)),
                                            name='visibility',
                                            trainable=False,
                                            dtype=tf.float32)
                tf_dt_pos_inv = \
                    tf.Variable(np.tile(dt_pos_inv, (1, 3)).reshape(-1, 3),
                                name='dt_pos_inv', trainable=False,
                                dtype=tf.float32)
                tf_dt_vel_inv = \
                    tf.constant(np.tile(dt_vel_inv, (1, 3)).reshape(-1, 3),
                                name='dt_vel_inv', dtype=tf.float32)

                # input data
                pos_3d_in = tf.Variable(skel_ours.poses.astype(np.float32),
                                        trainable=False,
                                        name='pos_3d_in',
                                        dtype=tf.float32)
                pos_2d_in = tf.Variable(np_poses_2d.astype(np.float32),
                                        trainable=False,
                                        name='pos_2d_in',
                                        dtype=tf.float32)

                params_camera = tf.Variable(initial_value=cam_angle,
                                            dtype=tf.float32,
                                            trainable=True)

                cam_sn = tf.sin(params_camera)
                cam_cs = tf.cos(params_camera)
                transform_camera = tf.reshape(tf.stack([
                    1., 0., 0., 0., 0., cam_cs[0], cam_sn[0], 0., 0.,
                    -cam_sn[0], cam_cs[0], 0., 0., 0., 0., 1.
                ],
                                                       axis=0),
                                              shape=(4, 4))

                # 3D translation
                translation = tf.Variable(np_translation, name='translation')
                # 3D rotation (Euler XYZ)
                rotation = tf.Variable(np_rotation, name='rotation')
                fw_angles = tf.Variable(np_angles, name='angles')

                # rotation around y
                my_zeros = tf.zeros((n_frames, 1))
                my_ones = tf.ones((n_frames, 1))
                c = tf.cos(tf.slice(rotation, [0, 1], [n_frames, 1]))
                s = tf.sin(tf.slice(rotation, [0, 1], [n_frames, 1]))
                t0 = tf.concat([c, my_zeros, -s, my_zeros], axis=1)
                t1 = tf.concat([my_zeros, my_ones, my_zeros, my_zeros], axis=1)
                t2 = tf.concat([s, my_zeros, c, my_zeros], axis=1)
                t3 = tf.concat([my_zeros, my_zeros, my_zeros, my_ones], axis=1)
                transform = tf.stack([t0, t1, t2, t3],
                                     axis=2,
                                     name="transform")

                transform = tf.einsum('ij,ajk->aik', transform_camera,
                                      transform)[:, :3, :3]

                # transform to 3d
                pos_3d = tf.matmul(transform, pos_3d_in) \
                    + tf.tile(tf.expand_dims(translation, 2),
                              [1, 1, int(pos_3d_in.shape[2])])

                # constraints
                loss_cnstr = None
                if np_cnstr is not None:
                    constraints = tf.Variable(np_cnstr,
                                              trainable=False,
                                              name='constraints',
                                              dtype=tf.float32)
                    constraints_mask = tf.Variable(np_cnstr_mask,
                                                   trainable=False,
                                                   name='constraints_mask',
                                                   dtype=tf.float32)
                    cnstr_diff = tf.reduce_sum(tf.squared_difference(
                        pos_3d, constraints),
                                               axis=1,
                                               name='constraints_difference')
                    cnstr_diff_masked = tf.multiply(
                        constraints_mask,
                        cnstr_diff,
                        name='constraints_difference_masked')
                    loss_cnstr = tf.reduce_sum(cnstr_diff_masked,
                                               name='constraints_loss')

                # perspective divide
                pos_2d = tf.divide(
                    tf.slice(pos_3d, [0, 0, 0], [n_frames, 2, -1]),
                    tf.slice(pos_3d, [0, 2, 0], [n_frames, 1, -1]))

                if use_huber:
                    diff = huber_loss(pos_2d_in, pos_2d, 1.)
                    masked = diff * tf_visibility
                    loss_reproj = tf.nn.l2_loss(masked)
                    lg.info("Doing huber on reprojection, NOT translation")
                else:
                    # re-projection loss
                    diff = pos_2d - pos_2d_in
                    # mask loss by 2d key-point visibility
                    masked = diff * tf_visibility
                    loss_reproj = tf.nn.l2_loss(masked)
                    lg.info("NOT doing huber")

                sys.stderr.write(
                    "TODO: Move huber to translation, not reconstruction\n")

                # translation smoothness
                dx = tf.multiply(
                    x=0.5,
                    y=tf.add(
                        pos_3d[1:, :, Joint.LHIP] - pos_3d[:-1, :, Joint.LHIP],
                        pos_3d[1:, :, Joint.RHIP] - pos_3d[:-1, :, Joint.RHIP],
                    ),
                    name="average_hip_displacement_3d")
                tf_velocity = tf.multiply(dx, tf_dt_pos_inv)

                tf_acceleration_z = tf.multiply(x=dx[1:, 2:3] - dx[:-1, 2:3],
                                                y=tf_dt_vel_inv[:, 2:3],
                                                name="acceleration_z")

                if smooth_mode == SmoothMode.VELOCITY:
                    # if GT, use full smoothness to fix 2-frame flicker
                    if np_cnstr is not None:
                        print('Smoothing all velocity!')
                        loss_transl_smooth = \
                            weight_smooth * tf.nn.l2_loss(tf_velocity)
                    else:  # Normal mode, don't oversmooth screen-space
                        loss_transl_smooth = \
                            weight_smooth * tf.nn.l2_loss(tf_velocity[:, 2:3])
                elif smooth_mode == SmoothMode.ACCEL:
                    loss_transl_smooth = \
                        weight_smooth * tf.nn.l2_loss(tf_acceleration_z)
                else:
                    raise RuntimeError(
                        'Unknown smooth mode: {}'.format(smooth_mode))

                if show:
                    sqr_accel_z = weight_smooth * tf.square(tf_acceleration_z)

                if weight_smooth > 0.:
                    lg.info("Smoothing in time!")
                    loss = loss_reproj + loss_transl_smooth
                else:
                    lg.warning("Not smoothing!")
                    loss = loss_reproj

                if loss_cnstr is not None:
                    loss += 1000 * loss_cnstr

                # hip0 = tf.nn.l2_normalize(pos_3d[:-1, :, Joint.RHIP] - pos_3d[:-1, :, Joint.LHIP])
                # hip1 = tf.nn.l2_normalize(pos_3d[1:, :, Joint.RHIP] - pos_3d[1:, :, Joint.RHIP])
                # dots = tf.reduce_sum(tf.multiply(hip0, hip1), axis=1)
                # print(dots)
                # loss_dot = tf.nn.l2_loss(1. - dots)
                # loss_ang = fw_angles + rotation[:, 1]
                # print(loss_ang)
                # loss_ang = tf.square(loss_ang[1:] - loss_ang[:-1])
                # print(loss_ang)
                # two_pi_sqr = tf.constant((2. * 3.14159)**2., dtype=tf.float32)
                # print(two_pi_sqr)
                # loss_ang = tf.reduce_mean(tf.where(loss_ang > two_pi_sqr, loss_ang - two_pi_sqr, loss_ang))
                # print(loss_ang)
                # loss += loss_ang

                #
                # optimize
                #
                optimizer = ScipyOptimizerInterface(
                    loss,
                    var_list=[translation, rotation],
                    options={'gtol': 1e-12},
                    var_to_bounds={rotation: (-np.pi / 2., np.pi / 2.)})

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

                optimizer.minimize(session)
                np_pos_3d_out, np_pos_2d_out, np_transl_out, np_masked, \
                np_acceleration, np_loss_transl_smooth, np_dt_vel = \
                    session.run([pos_3d, pos_2d, translation, masked,
                                 tf_acceleration_z, loss_transl_smooth,
                                 tf_dt_vel_inv])
                if show:
                    o_sqr_accel_z = session.run(sqr_accel_z)
                o_vel = session.run(tf_velocity)
                o_dx = session.run(dx)
                o_rot = session.run(rotation)
                # o_dx, o_dx2 = session.run([accel_bak, acceleration2])
                # assert np.allclose(o_dx, o_dx2), "no"
                o_cam = session.run(fetches=[params_camera])
                print("camera angle: %s" % np.rad2deg(o_cam[0]))
                # o_losses = session.run([loss_reproj, loss_transl_smooth, loss_dot, loss_ang])
                o_losses = session.run([loss_reproj, loss_transl_smooth])
                print('losses: {}'.format(o_losses))
                # o_dots = session.run(dots)
                # with open('tmp/dots.txt', 'w') as fout:
                #     fout.write('\n'.join((str(e) for e in o_dots.tolist())))

    fixed_frames = []
    # for lin_frame_id in range(np_transl_out.shape[0]):
    #     if np_transl_out[lin_frame_id, 2] < 0.:
    #         print("Correcting frame_id %d: %s"
    #               % (skel_ours.get_lin_id_for_frame_id(lin_frame_id),
    #                  np_transl_out[lin_frame_id, :]))
    #         if lin_frame_id > 0:
    #             np_transl_out[lin_frame_id, :] = np_transl_out[lin_frame_id-1, :]
    #         else:
    #             np_transl_out[lin_frame_id, :] = np_transl_out[lin_frame_id+1, :]
    #         fixed_frames.append(lin_frame_id)

    # debug_forwards(skel_ours.poses, np_pos_3d_out, o_rot, forwards, np_angles)

    # z_jumps = np_pos_3d_out[1:, 2, Joint.PELV] - np_pos_3d_out[:-1, 2, Joint.PELV]
    # out = scipy.stats.mstats.winsorize(z_jumps, limits=1.)
    # plt.figure()
    # plt.plot(pos_3d[:, 2, Joint.PELV])
    # plt.show()
    # sys.exit(0)
    # diff = np.linalg.norm(out - displ, axis=1)
    if len(fixed_frames):
        print("Re-optimizing...")
        with tf.Session(graph=graph) as session:
            np_pos_3d_out, np_pos_2d_out, np_transl_out = \
                session.run(fetches=[pos_3d, pos_2d, translation],
                            feed_dict={transform: np_transl_out})

    if show:
        lim_fr = [105, 115, 135]
        fig = plt.figure()
        accel_thr = 0.  # np.percentile(o_sqr_accel_z, 25)

        ax = plt.subplot2grid((2, 2), (0, 0), colspan=2)
        # print("np_masked:%s" % np_masked)
        # plt.plot(np_masked[:, )
        ax.plot(np.linalg.norm(np_acceleration[lim_fr[0]:lim_fr[1]], axis=1),
                '--o',
                label='accel')
        ax.add_artist(Line2D([0, len(o_sqr_accel_z)], [accel_thr, accel_thr]))
        # plt.plot(np_dt_vel[:, 0], label='dt velocity')
        # plt.plot(np.linalg.norm(np_f_accel, axis=1), '--x', label='f_accel')
        # plt.plot(ank_diff, label='ank_diff')
        ax.plot(o_sqr_accel_z[lim_fr[0]:lim_fr[1] + 1],
                '--x',
                label='loss accel_z')
        ax.legend()

        ax2 = plt.subplot2grid((2, 2), (1, 0), aspect='equal')
        ax2.plot(np_pos_3d_out[lim_fr[0]:lim_fr[1] + 1, 0, Joint.PELV],
                 np_pos_3d_out[lim_fr[0]:lim_fr[1] + 1, 2, Joint.PELV], '--x')
        for i, vel in enumerate(o_vel):
            if not (lim_fr[0] <= i <= lim_fr[1]):
                continue

            p0 = np_pos_3d_out[i + 1, [0, 2], Joint.PELV]
            p1 = np_pos_3d_out[i, [0, 2], Joint.PELV]
            ax2.annotate(
                "%f = ((%g - %g) + (%g - %g)) * %g = %g" %
                (vel[2], np_pos_3d_out[i + 1, 2, Joint.LHIP],
                 np_pos_3d_out[i, 2, Joint.LHIP], np_pos_3d_out[i + 1, 2,
                                                                Joint.RHIP],
                 np_pos_3d_out[i, 2, Joint.RHIP], np_dt_vel[i, 2], o_dx[i, 2]),
                xy=((p0[0] + p1[0]) / 2., (p0[1] + p1[1]) / 2.))
        ax2.set_title('velocities')

        ax1 = plt.subplot2grid((2, 2), (1, 1), aspect='equal')
        ax1.plot(np_pos_3d_out[lim_fr[0]:lim_fr[1] + 1, 0, Joint.PELV],
                 np_pos_3d_out[lim_fr[0]:lim_fr[1] + 1, 2, Joint.PELV], '--x')
        for i, lacc in enumerate(o_sqr_accel_z):
            if not (lim_fr[0] <= i <= lim_fr[1]):
                continue
            if lacc > accel_thr:
                p0 = np_pos_3d_out[i + 1, [0, 2], Joint.PELV]
                ax1.annotate("%.3f" % np_acceleration[i], xy=(p0[0], p0[1]))
                ax.annotate("%.3f" % np.log10(lacc),
                            xy=(i - lim_fr[0], abs(np_acceleration[i])))
        ax1.set_title('accelerations')

        plt.show()

    np.set_printoptions(linewidth=200)
    np_pos_2d_out[:, 0, :] *= intrinsics[0, 0]
    np_pos_2d_out[:, 1, :] *= intrinsics[1, 1]
    np_pos_2d_out[:, 0, :] += intrinsics[0, 2]
    np_pos_2d_out[:, 1, :] += intrinsics[1, 2]

    np_poses_2d[:, 0, :] *= intrinsics[0, 0]
    np_poses_2d[:, 1, :] *= intrinsics[1, 1]
    np_poses_2d[:, 0, :] += intrinsics[0, 2]
    np_poses_2d[:, 1, :] += intrinsics[1, 2]

    out_images = {}
    if shape_orig is not None:
        frames_2d = skel_ours_2d.get_frames()
        for frame_id2 in frames_2d:
            try:
                lin_frame_id = skel_ours_2d.get_lin_id_for_frame_id(frame_id2)
            except KeyError:
                lin_frame_id = None
            frame_id = skel_ours_2d.mod_frame_id(frame_id=frame_id2)

            im = None
            if frame_id in out_images:
                im = out_images[frame_id]
            elif len(images):
                if frame_id not in images:
                    lg.warning("Not enough images, the video was probably cut "
                               "after LiftingFromTheDeep was run.")
                    continue
                im = copy.deepcopy(images[frame_id])
                im = cv2.cvtColor(im, cv2.COLOR_RGB2BGR)
            else:
                im = np.zeros(
                    (shape_orig[0].astype(int), shape_orig[1].astype(int), 3),
                    dtype='i1')
            if lin_frame_id is not None:
                for jid in range(np_pos_2d_out.shape[2]):
                    if skel_ours_2d.is_visible(frame_id2, jid):
                        p2d = tuple(np_pos_2d_out[lin_frame_id, :,
                                                  jid].astype(int).tolist())
                        p2d_det = tuple(np_poses_2d[lin_frame_id, :,
                                                    jid].astype(int).tolist())
                        cv2.line(im,
                                 p2d,
                                 p2d_det,
                                 color=(100, 100, 100),
                                 thickness=3)
                        cv2.circle(im,
                                   p2d,
                                   radius=3,
                                   color=(0, 0, 200),
                                   thickness=-1)
                        cv2.circle(im,
                                   p2d_det,
                                   radius=3,
                                   color=(0, 200, 0),
                                   thickness=-1)
            out_images[frame_id] = im
            # cv2.imshow("Out", im)
            # cv2.waitKey(50)

        if False:
            # visualize
            fig = plt.figure()
            ax = fig.gca(projection='3d')
            for frame_id in range(0, np_pos_3d_out.shape[0], 1):
                j = Joint.PELV
                ax.scatter(np_pos_3d_out[frame_id, 0, j],
                           np_pos_3d_out[frame_id, 2, j],
                           -np_pos_3d_out[frame_id, 1, j],
                           marker='o')
            # smallest = np_pos_3d_out.min()
            # largest = np_pos_3d_out.max()
            ax.set_xlim3d(-5., 5.)
            ax.set_xlabel('x')
            ax.set_ylim3d(-5., 5.)
            ax.set_ylabel('y')
            ax.set_zlim3d(-5., 5.)
            ax.set_zlabel('z')

    if False:
        # visualize
        fig = plt.figure()
        ax = fig.gca(projection='3d')
        for frame_id in range(0, np_pos_3d_out.shape[0], 1):
            for j in range(np_pos_3d_out.shape[2]):
                ax.scatter(np_pos_3d_out[frame_id, 0, j],
                           np_pos_3d_out[frame_id, 2, j],
                           -np_pos_3d_out[frame_id, 1, j],
                           marker='o')
        # smallest = np_pos_3d_out.min()
        # largest = np_pos_3d_out.max()
        ax.set_xlim3d(-5., 5.)
        ax.set_xlabel('x')
        ax.set_ylim3d(-5., 5.)
        ax.set_ylabel('y')
        ax.set_zlim3d(-5., 5.)
        ax.set_zlabel('z')
    plt.show()

    assert all(a == b
               for a, b in zip(skel_ours.poses.shape, np_pos_3d_out.shape)), \
        "no"
    skel_ours.poses = np_pos_3d_out
    return skel_ours, out_images, intrinsics
Esempio n. 9
0
def main(argv):
    parser = argparse.ArgumentParser(
        "Filter initial path based on distance to full fit")
    parser.add_argument('skel', help="Skeleton file to filter", type=str)
    parser.add_argument('--threshold',
                        help='Distance threshold. Default: 0.4',
                        type=float,
                        default=0.4)
    args = parser.parse_args(argv)
    lower_body = [
        Joint.LKNE, Joint.RKNE, Joint.LANK, Joint.RANK, Joint.LHIP, Joint.RHIP
    ]

    print(args.skel)
    p_root = os.path.dirname(args.skel)
    p_fit = os.path.join(p_root, 'opt1')
    assert os.path.isdir(p_fit), p_fit
    query = Scenelet.load(args.skel)
    out = Skeleton()

    data = []

    x = []
    y = []
    y2 = []
    for d_ in sorted(os.listdir(p_fit)):
        d = os.path.join(p_fit, d_)
        pattern = os.path.join(d, 'skel_*.json')
        for f in sorted(glob.iglob(pattern)):
            print(f)
            assert '00' in f, f
            sclt = Scenelet.load(f)
            frames = sclt.skeleton.get_frames()
            mid_frame = frames[len(frames) // 2]
            time = sclt.skeleton.get_time(mid_frame)
            q_frame_id = query.skeleton.find_time(time)
            q_time = query.skeleton.get_time(q_frame_id)
            print(time, q_time, f)
            q_pose = query.skeleton.get_pose(q_frame_id)
            pose = sclt.skeleton.get_pose(mid_frame)
            pose[[0, 2]] -= (pose[:, Joint.PELV:Joint.PELV + 1] -
                             q_pose[:, Joint.PELV:Joint.PELV + 1])[[0, 2]]
            diff = np.mean(
                np.linalg.norm(q_pose[:, lower_body] - pose[:, lower_body],
                               axis=0))
            print(q_frame_id, time, diff)
            y.append(diff)
            x.append(q_frame_id)
            data.append((q_frame_id, diff, time))

            if query.skeleton.has_pose(q_frame_id - 1):
                tmp_pose = copy.deepcopy(q_pose)
                tmp_pose -= tmp_pose[:, Joint.PELV:Joint.PELV +
                                     1] - query.skeleton.get_pose(
                                         q_frame_id -
                                         1)[:, Joint.PELV:Joint.PELV + 1]
                y2.append(
                    np.mean(
                        np.linalg.norm(pose[:, lower_body] -
                                       tmp_pose[:, lower_body],
                                       axis=0)))
            else:
                y2.append(0.)

            out.set_pose(frame_id=q_frame_id, time=q_time, pose=pose)
            break

    data = smooth(data)
    plt.plot(x, y, 'x--', label='Distance to best Kinect fit\'s center frame')
    plt.plot(x, y2, 'o--', label='Distance to prev pose')
    plt.plot([d[0] for d in data], [d[1] for d in data],
             'o--',
             label='Smoothed')
    plt.xlabel('Time (s)')
    plt.ylabel('Sum local squared distance')
    plt.legend()
    plt.savefig(os.path.join(p_root, 'tmp.pdf'))
    Scenelet(skeleton=out).save(os.path.join(p_root, 'skel_tmp.json'))

    above = []
    prev_frame_id = None
    for frame_id, dist, time in data:
        # assert prev_frame_id is None or frame_id != prev_frame_id, \
        #     'No: {}'.format(frame_id)
        if dist > args.threshold:
            above.append(
                Span2(start=frame_id, end=frame_id, value=dist, time=time))
        prev_frame_id = frame_id

    spans = [copy.deepcopy(above[0])]
    it = iter(above)
    next(it)
    prev_frame_id = above[0].start
    for span2 in it:
        frame_id = span2.start
        if prev_frame_id + 1 < frame_id:
            # span = spans[-1]
            # spans[-1] = span[0], prev_frame_id, span[2]
            spans[-1].end = prev_frame_id
            spans.append(
                Span2(start=frame_id,
                      end=frame_id,
                      time=None,
                      value=span2.value))
        else:
            print(prev_frame_id, frame_id)
        prev_frame_id = frame_id
    spans[-1].end = prev_frame_id
    print("Need replacement: {}".format(above))
    print("Need replacement2: {}".format(spans))
Esempio n. 10
0
def main(argv):
    np.set_printoptions(suppress=True, linewidth=200)
    pjoin = os.path.join

    parser = argparse.ArgumentParser("matcher")
    parser.add_argument("d_scenelets",
                        type=argparse_check_exists,
                        help="Folder containing scenelets")
    parser.add_argument("video", type=argparse_check_exists, help="Input path")
    parser.add_argument("--gap-size-limit",
                        type=int,
                        help="Smallest gap size to still explain")
    args = parser.parse_args(argv)
    d_query = os.path.dirname(args.video)

    # 2d keypoint rescale
    p_im = pjoin(d_query, 'origjpg', 'color_00100.jpg')
    im_ = cv2.imread(p_im)
    shape_orig = im_.shape
    scale_2d = shape_orig[0] / float(INPUT_SIZE)

    query = Scenelet.load(args.video, no_obj=True)
    tr_ground = np.array(query.aux_info['ground'], dtype=np.float32)
    print("tr: %s" % tr_ground)

    name_query = os.path.basename(args.video).split('_')[1]
    query_2d = Scenelet.load(pjoin(d_query,
                                   "skel_%s_2d_00.json" % name_query)).skeleton
    p_intr = pjoin(d_query, 'intrinsics.json')
    intr = np.array(json.load(open(p_intr, 'r')), dtype=np.float32)
    lg.debug("intr: %s" % intr)

    gaps = find_gaps(query.skeleton, min_pad=1)

    p_scenelets_pickle = pjoin(args.d_scenelets, 'match_gap_scenelets.pickle')
    if os.path.exists(p_scenelets_pickle):
        scenelets = pickle_load(open(p_scenelets_pickle, 'rb'))
    else:
        scenelets = read_scenelets(args.d_scenelets, limit=0)
        pickle.dump(scenelets, open(p_scenelets_pickle, 'wb'))

    p_out_sclts = pjoin(d_query, 'fill')
    if os.path.exists(p_out_sclts):
        shutil.rmtree(p_out_sclts)
    os.makedirs(p_out_sclts)
    times = []
    for gap_id, gap in enumerate(gaps):
        lg.debug("gap is %s" % repr(gap))
        if gap[1] - gap[0] < args.gap_size_limit:
            continue
        with Timer("gap %d" % gap_id) as timer:
            chosen = []
            for sc_id, sclt in enumerate(scenelets):
                lg.info("scenelet %d / %d" % (sc_id, len(scenelets)))
                sclt = scenelets[sc_id]
                ground_obj = next(ob for ob in sclt.objects.values()
                                  if ob.label == 'floor')
                ground_part = ground_obj.get_part_by_name('floor')
                lg.debug("floor: %s" % ground_part)
                ground_transform = ground_part.obb.as_transform()
                lg.debug("floor: %s" % ground_transform)
                # sys.exit(0)
                # chosen.extend(
                out_sclts = match(query,
                                  d_query,
                                  query_2d,
                                  sclt,
                                  intr,
                                  gap,
                                  tr_ground,
                                  scale=scale_2d)
                if not len(out_sclts):
                    continue
                # pick best from scene
                chosen.append(
                    [out_sclts[0][i]
                     for i in range(len(out_sclts[0]))] + [sc_id])
                # break

            # os.system("rm %s/skel_%s_fill_%03d_%03d__*.json"
            #           % (p_out_sclts, name_query, gap[0], gap[1]))
            chosen = sorted(chosen, key=lambda score_sclt: score_sclt[0])
            for sid, (score, out_sclt, sc_id) in enumerate(chosen):
                p_out = pjoin(
                    p_out_sclts, "skel_%s_fill_%03d_%03d__%02d.json" %
                    (name_query, gap[0], gap[1], sid))
                out_sclt.save(p_out)
                if sid > 5:
                    break
        times.append(timer.get_elapsed_ms())
    lg.info("mean time per gap: %s" % np.mean(times))
Esempio n. 11
0
"""
Setup:
    conda create --name iMapper python=3 numpy -y \
    conda activate iMapper

Usage:
    export PYTHONPATH=$(pwd); python3 example.py
"""


from imapper.logic.scenelet import Scenelet

if __name__ == '__main__':
    scenelet = Scenelet.load('i3DB/Scene04/gt/skel_lobby19-3_GT.json')
    skeleton = scenelet.skeleton
    print('Have {} poses and {} objects'
          .format(len(skeleton.get_frames()), len(scenelet.objects)))
Esempio n. 12
0
def main(argv=None):
    np.set_printoptions(suppress=True)
    parser = argparse.ArgumentParser()
    parser.add_argument('d', help="Folder of scene")
    parser.add_argument('-resolution',
                        help='Target resolution for occupancy map',
                        default=0.1)
    parser.add_argument(
        '-thresh-area',
        help='Ratio of occupancy map cell area that has to be occupied '
        'for it to count as occupied',
        default=0.1)
    parser.add_argument('-postfix',
                        type=str,
                        help="Scene postfix for augmentation",
                        default="")
    args = parser.parse_args(argv if argv is not None else sys.argv)
    res_target = args.resolution
    if args.postfix and len(args.postfix) and not args.postfix.startswith('_'):
        args.postfix = "_%s" % args.postfix

    path_parent, name_input = os.path.split(os.path.abspath(args.d))
    lg.warning("name input: %s" % name_input)
    path_for_tf = os.path.abspath(
        os.path.join(path_parent, os.pardir, 'dataset'))
    # if 'video' not in path_parent else os.path.join(path_parent, 'dataset')
    if not os.path.exists(path_for_tf):
        os.makedirs(path_for_tf, mode=0o0775)

    lg.debug("Loading scenelet...")
    path_scenelet = os.path.join(args.d, "skel_%s.json" % name_input)
    scenelet = Scenelet.load(path_scenelet)
    lg.debug("Scenelet: %s" % scenelet)

    path_state_pickle = os.path.join(args.d, "state%s.pickle" % args.postfix)
    if not os.path.exists(path_state_pickle):
        lg.error("Does not exist: %s" % path_state_pickle)
        return False

    # assert os.path.exists(path_state_pickle), \
    #     "Does not exist: %s" % path_state_pickle
    lg.debug("Loading volume...")
    state = pickle_load(open(path_state_pickle, 'rb'))
    lg.debug("Loaded volume...")

    lg.debug("Creating scene from scenelet")
    if not no_vis:
        vis = Visualizer(win_size=(1024, 1024))
        vis.add_coords()
    else:
        vis = None
    # scene = Scene(scenelet.name_scenelet)
    # colors = {0: (200., 0., 0.), 1: (0., 200., 0.), 2: (0., 0., 200.)}
    # unit_x = np.array((1., 0., 0.))

    occup = State(room=state.room,
                  tr_ground_inv=None,
                  res_theta=state.resolution[3],
                  resolution=[res_target, res_target, res_target])
    occup.get_volume(labels_to_lin_ids_arg=state.get_labels_to_lin_ids())
    occup_angle = np.ones(shape=(len(
        occup.volume), occup.volume[0].shape[0], occup.volume[0].shape[1], 1),
                          dtype=np.float32) * -1.
    assert np.min(occup_angle) < 0. and np.max(occup_angle) < 0., "Not empty"

    grid_polys = get_grid_shapely(occup=occup, res_orig=state.resolution)
    occup.volume.flags.writeable = True
    volume_occp = occup.volume
    angles = sorted(state.get_angles())
    labels_to_lin_ids = occup.get_labels_to_lin_ids()
    had_vtk_problem = no_vis

    plt.figure()

    rects = []
    for oid, ob in scenelet.objects.items():
        assert oid >= 0, "Need positive here"
        label = ob.label
        if label in TRANSLATIONS_CATEGORIES:
            label = TRANSLATIONS_CATEGORIES[label]

        if label not in labels_to_lin_ids:
            continue

        try:
            poly = get_poly([part.obb for part in ob.parts.values()])
        except ValueError as e:
            print("\n===========\n\nShapely error: %s for %s\n\n" %
                  (e, (label, oid, ob)))
            with open('error.log', 'a') as f:
                f.write("[%s] %d, %s, %s\n" % (args.d, oid, label, ob))
            continue

        ob_angle = ob.get_angle(positive_only=True)
        assert 0. <= ob_angle <= 2 * np.pi, "No: %g" % ob_angle

        rect = get_rectangle(poly, ob_angle)
        rect.extend([oid, CATEGORIES[label]])
        rects.append(rect)

        cat_id = labels_to_lin_ids[label]  # cat_id in volume, not categories
        for gp in grid_polys:
            # skip, if not occupied enough
            if gp.poly.intersection(poly).area / gp.area < args.thresh_area:
                continue
            # save occupancy
            gp.occupancy = 1.
            id_angle_lower = None
            id_angle_upper = None
            if ob_angle > angles[-1]:
                id_angle_lower = len(angles) - 1
                id_angle_upper = 0
            else:
                for id_angle, angle in enumerate(angles):
                    if ob_angle < angle:
                        id_angle_upper = id_angle
                        id_angle_lower = id_angle - 1
                        break
            assert id_angle_lower is not None \
                   and id_angle_upper is not None, \
                "Wrong?"
            assert id_angle_upper != id_angle_lower, \
                "? %s %s" % (id_angle_lower, id_angle_upper)

            # cache
            xy = gp.xy

            # zero means empty in occupancy,
            # so object ids are shifted with 1
            # we need object ids to filter "untouched" objects
            # in tfrecords_create
            if volume_occp[cat_id, xy[0], xy[1], id_angle_lower] == 0 \
               or label in CATEGORIES_DOMINANT:
                volume_occp[cat_id, xy[0], xy[1], id_angle_lower] = oid + 1
            if volume_occp[cat_id, xy[0], xy[1], id_angle_upper] == 0 \
               or label in CATEGORIES_DOMINANT:
                volume_occp[cat_id, xy[0], xy[1], id_angle_upper] = oid + 1

            # angles are right now not per-category, but per-scene
            # hence, an object can only overwrite, if it's usually "above"
            # other objects, e.g. a table
            # this is a hack for a z-test
            if occup_angle[cat_id, xy[0], xy[1], 0] < 0. \
               or label in CATEGORIES_DOMINANT:
                occup_angle[cat_id, xy[0], xy[1], 0] = ob_angle

        if not had_vtk_problem:
            color = COLORS_CATEGORIES[label] if label in COLORS_CATEGORIES \
                else (200., 200., 200.)
            try:
                for id_part, part in ob.parts.items():
                    vis.add_mesh(MeshOBJ.from_obb(part.obb),
                                 name="ob_%02d_part_%02d" % (oid, id_part),
                                 color=color)
            except AttributeError:
                print("VTK problem...")
                had_vtk_problem = True
    #plt.savefig()
    plt.close()
    if not had_vtk_problem:
        vis.set_camera_pos(pos=(0., -1., 0.))
        vis.camera().SetFocalPoint(0., 0., 0.)
        vis.camera().SetViewUp(-1., 0., 0.)
        vis.set_camera_type(is_ortho=True)
        vis.camera().SetParallelScale(3.)
    # vis.show()

    name_recording = "%s_%s" % (os.path.basename(args.d), args.postfix) \
        if args.postfix else os.path.basename(args.d)
    lg.info("name_recording: %s" % name_recording)

    path_out_occp = os.path.join(os.path.dirname(args.d), os.pardir,
                                 'occupancy', name_recording)
    if not os.path.exists(path_out_occp):
        os.makedirs(path_out_occp)

    # prepare www storage
    www_grid = {'evidence': {}, 'occ': {}}

    # normalize evidence maps
    vmax = 0.
    ims = {}
    for cat, cat_id in labels_to_lin_ids.items():
        ims[cat] = np.squeeze(
            np.sum(state.volume[cat_id, :, :, :], axis=2, keepdims=True))
        vmax = max(vmax, np.max(ims[cat]))

    # gather joined occupancy map
    im_sum = None

    # for each evidence category
    for cat, cat_id in labels_to_lin_ids.items():
        im = ims[cat] / vmax * 255.
        path_out_im = os.path.join(path_out_occp, "e_%s.jpg" % cat)
        cv2.imwrite(path_out_im, im)
        # lg.debug("wrote to %s" % path_out_im)
        www_grid['evidence'][cat] = path_out_im

        im = np.squeeze(volume_occp[cat_id, :, :, 0])
        path_out_im = os.path.join(path_out_occp, "o_%s.jpg" % cat)
        cv2.imwrite(path_out_im, im * 255.)
        # lg.debug("wrote to %s" % path_out_im)
        www_grid['occ'][cat] = path_out_im

        if im_sum is None:
            im_sum = im.copy()
        else:
            im_sum = np.maximum(im, im_sum)

    #
    # save dataset
    #
    name_input_old = name_input
    if args.postfix is not None and len(args.postfix):
        name_input = "%s_%s" % (name_input, args.postfix)

    # state
    path_state_dest = os.path.join(path_for_tf, "state_%s.pickle" % name_input)
    shutil.copyfile(path_state_pickle, path_state_dest)
    lg.info("Copied\n\t%s to\n\t%s" % (path_state_pickle, path_state_dest))

    # occupancy
    path_occup_dest = os.path.join(path_for_tf, "occup_%s.pickle" % name_input)
    pickle.dump(occup, open(path_occup_dest, 'wb'), -1)
    lg.info("Wrote to %s" % path_occup_dest)

    # occupancy_angle
    path_occup_angle_dest = os.path.join(path_for_tf,
                                         "angle_%s.npy" % name_input)
    min_angle = np.min(occup_angle)
    assert min_angle < 0., "No empty cells??"
    lg.debug("min angle is %s" % min_angle)
    np.save(open(path_occup_angle_dest, 'wb'), occup_angle)
    lg.info("Wrote to %s" % path_occup_angle_dest)

    # skeleton
    path_copied = shutil.copy2(path_scenelet, path_for_tf)
    lg.info("Copied\n\t%s to \n\t%s" % (path_scenelet, path_copied))

    # charness skeleton
    name_skeleton_charness = "skel_%s-charness.json" % name_input_old
    path_scenelet_charness = os.path.join(args.d, name_skeleton_charness)
    assert os.path.exists(path_scenelet_charness), \
        "Does not exist: %s" % path_scenelet_charness
    shutil.copy2(path_scenelet_charness, path_for_tf)
    assert os.path.exists(os.path.join(path_for_tf, name_skeleton_charness)), \
        "Does not exist: %s" % os.path.join(path_for_tf,
                                            name_skeleton_charness)

    # rectangles
    name_rectangles = "rectangles_%s.npy" % name_input_old
    path_rectangles = os.path.join(path_for_tf, name_rectangles)
    np.save(open(path_rectangles, 'wb'), rects)

    #
    # visualize
    #

    path_out_im = os.path.join(path_out_occp, '3d.png')
    if not had_vtk_problem:
        vis.save_png(path_out_im)
    www_grid['3d'] = path_out_im

    path_out_im = os.path.join(path_out_occp, 'o_sum.png')
    max_im_sum = np.max(im_sum)
    if max_im_sum > 0.:
        cv2.imwrite(path_out_im, im_sum / max_im_sum * 255.)
    else:
        cv2.imwrite(path_out_im, im_sum * 255.)
    www_grid['o_sum'] = path_out_im

    path_www = os.path.join(path_out_occp, os.pardir)
    with open(os.path.join(path_www, 'index.html'), 'a') as f:
        f.write("<style> img {image-rendering: pixelated; } </style>\n")
        f.write("<script>\n")
        f.write("</script>\n")
        f.write("<h3>%s</h3>" % os.path.basename(args.d))
        f.write('<table>\n')

        f.write("<tr>\n")
        f.write("<th>3d</th>")
        f.write("<th>Occupancy sum</th>")
        for cat in www_grid['evidence']:
            f.write("\t<th>%s</th>\n" % cat)
        f.write("<th></th>\n")  # titles
        f.write("</tr>\n")

        f.write("<tr>\n")
        # 3D
        f.write("\t<td rowspan=\"2\">\n")
        path_im = os.path.relpath(www_grid['3d'], path_www)
        f.write("\t<a href=\"%s\">\n"
                "\t\t<img src=\"%s\" height=\"400\" />\n"
                "\t</a>\n" % (path_im, path_im))

        # Evidence sum
        f.write("\t<td rowspan=\"2\">\n")
        path_im = os.path.relpath(www_grid['o_sum'], path_www)
        f.write("\t<a href=\"%s\">\n"
                "\t\t<img src=\"%s\" height=\"400\" />\n"
                "\t</a>\n" % (path_im, path_im))
        # Evidence
        for cat in www_grid['evidence']:
            f.write("<td style=\"padding-bottom: 2px\">\n")
            path_im = os.path.relpath(www_grid['evidence'][cat], path_www)
            f.write("\t<a href=\"%s\">\n"
                    "\t\t<img src=\"%s\" height=\"200\" />\n"
                    "\t</a>\n" % (path_im, path_im))
            f.write("</td>\n")
        f.write("<td>Evidence</td>\n")

        f.write("\t</td>\n")
        f.write("</tr>\n")

        f.write("<tr>\n")
        for cat in www_grid['occ']:
            f.write("<td>\n")
            path_im = os.path.relpath(www_grid['occ'][cat], path_www)
            f.write("\t<a href=\"%s\">\n"
                    "\t\t<img src=\"%s\" height=\"200\" />\n"
                    "</a>\n" % (path_im, path_im))
            f.write("</td>\n")
        f.write("<td>Occupancy map</td>\n")
        f.write("</tr>")

        f.write('</table>')

    return True
Esempio n. 13
0
def main(argv):
    from imapper.pose.opt_consistent import main as opt_consistent
    pjoin = os.path.join
    parser = argparse.ArgumentParser("Fit full video")
    parser.add_argument("video", type=argparse_check_exists, help="Input path")
    parser.add_argument("step_size", type=int, help="Stepsize in frames.")
    parser.add_argument("window_size", type=int, help="Window size in frames.")
    parser.add_argument('--wp',
                        type=float,
                        help="Projection weight.",
                        default=1.)
    parser.add_argument('--ws',
                        type=float,
                        help="Smoothness weight.",
                        default=.1)
    parser.add_argument('--wo',
                        type=float,
                        help="Occlusion weight.",
                        default=0.1)
    parser.add_argument('--wi',
                        type=float,
                        help="Intersection weight.",
                        default=1.
                        # used to be 10.
                        )
    parser.add_argument('--gtol',
                        type=float,
                        help="Optimizer gradient tolerance (termination "
                        "criterion).",
                        default=1e-6)
    parser.add_argument('--maxiter',
                        type=int,
                        help="Optimizer max number of iterations.",
                        default=0)
    parser.add_argument('-w-occlusion',
                        action='store_true',
                        help="Estimate occlusion score.")
    parser.add_argument('-no-isec',
                        action='store_true',
                        help='Don\'t use intersection terms')
    parser.add_argument('--dest-dir',
                        type=str,
                        help="Name of subdirectory to save output to.",
                        default='opt1')
    parser.add_argument("-s",
                        "--d-scenelets",
                        dest='s',
                        type=argparse_check_exists,
                        help="Folder containing original PiGraphs scenelets")
    parser.add_argument('--batch-size',
                        type=int,
                        help="How many scenelets to optimize at once.",
                        default=1500)
    parser.add_argument('--output-n',
                        type=int,
                        help="How many candidates to output per batch and "
                        "overall.",
                        default=200)
    parser.add_argument('--filter-same-scene',
                        action='store_true',
                        help="Hold out same scene scenelets.")
    args = parser.parse_args(argv)

    # get video parent directory
    d_query = args.video if os.path.isdir(args.video) \
        else os.path.dirname(args.video)

    # save call log to video directory
    with open(pjoin(d_query, 'args_opt_consistent.txt'), 'a') as f_args:
        f_args.write('(python3 ')
        f_args.write(" ".join(sys.argv))
        f_args.write(")\n")

    # parse video path
    name_query = os.path.split(d_query)[-1]
    p_query = pjoin(d_query, "skel_%s_unannot.json" % name_query) \
        if os.path.isdir(args.video) else args.video
    assert p_query.endswith('.json'), "Need a skeleton file"
    print("name_query: %s" % name_query)

    cache_scenes = None

    skipped = []
    # load initial video path (local poses)
    query = Scenelet.load(p_query, no_obj=True)
    frame_ids = query.skeleton.get_frames()
    half_window_size = args.window_size // 2
    for mid_frame_id in range(frame_ids[0] + half_window_size,
                              frame_ids[-1] - half_window_size + 1,
                              args.step_size):
        gap = (mid_frame_id - half_window_size,
               mid_frame_id + half_window_size)
        assert gap[0] >= frame_ids[0]
        assert gap[1] <= frame_ids[-1]
        pose_count = sum(1 for _frame_id in range(gap[0], gap[1] + 1)
                         if query.skeleton.has_pose(_frame_id))
        if pose_count < 9:
            print("Skipping span because not enough poses: %s" % pose_count)
            skipped.append((gap, pose_count))
        same_actor = query.skeleton.n_actors == 1  # type: bool
        if not same_actor:
            same_actor = query.skeleton.get_actor_id(frame_id=gap[0]) \
                         == query.skeleton.get_actor_id(frame_id=gap[1])
        if not same_actor:
            print('skipping gap {:d}...{:d}, not same actor'.format(
                gap[0], gap[1]))
            continue

        lg.info("gap: %s" % repr(gap))
        argv = [
            '-silent',
            '--wp',
            "%g" % args.wp,
            '--ws',
            "%g" % args.ws,
            '--wo',
            "%g" % args.wo,
            '--wi',
            "%g" % args.wi,
            '--nomocap',  # added 16/4/2018
            '-v',
            args.video,
            '--output-n',
            "%d" % args.output_n
        ]
        if args.w_occlusion:
            argv.extend(['-w-occlusion'])
        if args.no_isec:
            argv.extend(['-no-isec'])

        if args.filter_same_scene:
            argv.extend(['--filter-scenes', name_query.partition('_')[0]])
        # else:
        #     assert False, "crossvalidation assumed"

        if args.maxiter:
            argv.extend(['--maxiter', "%d" % args.maxiter])

        argv.extend([
            'independent', '-s', args.s, '--gap',
            "%d" % gap[0],
            "%d" % gap[1], '--dest-dir', args.dest_dir, '-tc', '-0.1',
            '--batch-size',
            "%d" % args.batch_size
        ])
        lg.info("argv: %s" % argv)

        # if 'once' not in locals():
        try:
            _cache_scenes = opt_consistent(argv, cache_scenes)
            if isinstance(_cache_scenes, list) and len(_cache_scenes) \
                and (cache_scenes is None
                     or len(_cache_scenes) != len(cache_scenes)):
                cache_scenes = _cache_scenes
        except FileNotFoundError as e:
            lg.error("e: %s" % e)
            if e.__str__().endswith('_2d_00.json\''):
                from imapper.pose.main_denis import main as opt0
                argv_opt0 = [
                    's8', '-d',
                    "%s/denis" % d_query, '-smooth', '0.005'
                ]
                opt0(argv_opt0)
            else:
                print(e.__str__())

            opt_consistent(argv)

        # once = True
    show_folder([args.video])

    extract_gaps([args.video, args.s])

    print("skipped: %s" % skipped)
Esempio n. 14
0
def show_folder(argv):
    # python3 stealth/pose/fit_full_video.py --show /home/amonszpa/workspace/stealth/data/video_recordings/scenelets/lobby15 opt1
    # python3 stealth/pose/visualization/show_charness_scores.py --show /media/data/amonszpa/stealth/shared/video_recordings/library1 -o opt1
    pjoin = os.path.join

    parser = argparse.ArgumentParser("Fit full video")
    parser.add_argument('--show', action='store_true')
    parser.add_argument("video", type=argparse_check_exists, help="Input path")
    parser.add_argument(
        '-o',
        '--opt-folder',
        help="Which optimization output to process. Default: opt1",
        default='opt1')
    parser.add_argument("--window-size",
                        type=int,
                        help="Window size in frames.",
                        default=20)

    args = parser.parse_args(argv)
    d = os.path.join(args.video, args.opt_folder)
    assert os.path.exists(d), "does not exist: %s" % d

    # parse video path
    if args.video.endswith(os.sep):
        args.video = args.video[:-1]
    name_query = os.path.split(args.video)[-1]
    print("split: %s" % repr(os.path.split(args.video)))
    p_query = pjoin(args.video, "skel_%s_unannot.json" % name_query) \
        if os.path.isdir(args.video) else args.video
    assert p_query.endswith('.json'), "Need a skeleton file"

    # load initial video path (local poses)
    query = Scenelet.load(p_query, no_obj=True)

    frame_ids = query.skeleton.get_frames()
    centroids = Skeleton.get_resampled_centroids(start=frame_ids[0],
                                                 end=frame_ids[-1],
                                                 old_frame_ids=frame_ids,
                                                 poses=query.skeleton.poses)

    depths_times_charnesses = []
    skeleton = Skeleton()
    depths = []
    skeleton.charness_poses = {}  # this is in Scenelet incorrectly...
    skeleton.score_fit = {}  # inventing this now
    skeleton.score_reproj = {}  # inventing this now
    for p in sorted(os.listdir(d)):
        d_time = pjoin(d, p)
        if not os.path.isdir(d_time):
            continue
        p_skel = next(
            f for f in os.listdir(d_time) if os.path.isfile(pjoin(d_time, f))
            and f.startswith('skel') and f.endswith('json') and '_00' in f)
        sclt = Scenelet.load(pjoin(d_time, p_skel))
        mn, mx = sclt.skeleton.get_frames_min_max()
        frame_id = mn + (mx - mn) // 2
        if query.skeleton.has_pose(frame_id):
            pos_3d = query.skeleton.get_centroid_3d(frame_id)
        else:
            lin_id = frame_id - frame_ids[0]
            pos_3d = centroids[lin_id, :]

        # put centroid for each joint
        skeleton.set_pose(frame_id=frame_id,
                          pose=np.tile(pos_3d[:, None], (1, 16)))
        with open(pjoin(d_time, 'avg_charness.json')) as fch:
            data = json.load(fch)
            set_or_max(skeleton.charness_poses, frame_id, data['avg_charness'])
            # if frame_id in skeleton.charness_poses:
            #     lg.warning("Maxing charness at frame %d" % frame_id)
            #     skeleton.charness_poses[frame_id] = max(
            #       skeleton.charness_poses[frame_id], data['avg_charness'])
            # else:
            #     skeleton.charness_poses[frame_id] = data['avg_charness']

        # fit scores
        if 'score_fit' in sclt.aux_info:
            set_or_max(skeleton.score_fit, frame_id,
                       sclt.aux_info['score_fit'])
        else:
            set_or_max(skeleton.score_fit, frame_id, 0.)

        if 'score_reproj' in sclt.aux_info:
            set_or_max(skeleton.score_reproj, frame_id,
                       sclt.aux_info['score_reproj'])
        else:
            set_or_max(skeleton.score_reproj, frame_id, 0.)

    fig = plt.figure(figsize=(16, 12), dpi=100)
    ax = fig.add_subplot(121, aspect='equal')
    X = []  # skeleton x
    Z = []  # skeleton z (depth)
    C = []  # charness
    F = []  # score_fit
    R = []  # score_reproj
    T = []  # times
    for frame_id in skeleton.get_frames():
        c = skeleton.get_joint_3d(6, frame_id=frame_id)
        X.append(c[0])
        Z.append(c[2])
        C.append(skeleton.charness_poses[frame_id])
        F.append(skeleton.score_fit[frame_id])
        R.append(skeleton.score_reproj[frame_id])
        T.append(frame_id)
    ax.plot(X, Z, 'k--')
    for frame_id in skeleton.get_frames():
        if frame_id % 5:
            continue
        c = skeleton.get_joint_3d(6, frame_id=frame_id)
        ax.annotate("%d" % frame_id, xy=(c[0], c[2]), zorder=5)
    cax = ax.scatter(X, Z, c=C, cmap='jet', zorder=5)
    fig.colorbar(cax)
    z_lim = (min(Z), max(Z))
    z_span = (z_lim[1] - z_lim[0]) // 2
    x_lim = min(X), max(X)
    x_span = (x_lim[1] - x_lim[0]) // 2
    pad = .5
    dspan = z_span - x_span
    if dspan > 0:
        ax.set_xlim(x_lim[0] - dspan - pad, x_lim[1] + dspan + pad)
        ax.set_ylim(z_lim[0] - pad, z_lim[1] + pad)
    else:
        ax.set_xlim(x_lim[0] - pad, x_lim[1] + pad)
        ax.set_ylim(z_lim[0] + dspan - pad, z_lim[1] - dspan + pad)
    ax.set_title('Fit score weighted characteristicness\ndisplayed at '
                 'interpolated initial path position')

    ax = fig.add_subplot(122)

    ax.plot(T, C, 'x--', label='max charness')
    charness_threshes = [0.4, 0.35, 0.3]
    mn_thr_charness = min(charness_threshes)
    mx_thr_charness = max(charness_threshes)
    for ct in charness_threshes:
        ax.plot([T[0], T[-1]], [ct, ct], 'r')
        ax.annotate("charness %g" % ct, xy=(T[0], ct + 0.005))

    charness_sorted = sorted([(fid, c)
                              for fid, c in skeleton.charness_poses.items()],
                             key=lambda e: e[1])

    to_show = []
    # Fitness
    divisor = 5.
    F_ = -np.log10(F) / divisor
    print(F_)
    ax.plot(T, F_, 'x--', label="-log_10(score) / %.0f" % divisor)
    mx_F_ = np.percentile(F_, 90)  # np.max(F_)
    for i, (t, f) in enumerate(zip(T, F_)):
        if f > mx_F_ or any(C[i] > ct for ct in charness_threshes):
            to_show.append(i)
            # ax.annotate("%.4f" % (F[i]), xy=(t, f), xytext=(t+4, f-0.02),
            #             arrowprops=dict(facecolor='none', shrink=0.03))
            # charness
            # ax.annotate("%.3f\n#%d" % (C[i], t), xy=(t, C[i]),
            #             xytext=(t-10, C[i]-0.02),
            #             arrowprops=dict(facecolor='none', shrink=0.03))

    windows = []  # [(t_start, t_max, t_end), ...]
    crossings = {}

    # Reproj
    R_ = -np.log10(R) / divisor
    # ax.plot(T, R_, 'x--', label="-log_10(score reproj) / %.0f" % divisor)
    mx_R_ = np.max(R_)
    is_above = [False for _ in charness_threshes]
    mx_above = []
    for i, (t, r) in enumerate(zip(T, R_)):
        # if i in to_show:
        # ax.annotate("%.4f" % (R[i]), xy=(t, r), xytext=(t-10, r+0.02),
        #             arrowprops=dict(facecolor='none', shrink=0.03))
        # ax.annotate("%d" % t, xy=(t, r - 0.01))
        if (i + 1 < len(C)) and (C[i] > C[i + 1]) and (C[i] > mn_thr_charness):
            mx_above.append((C[i], t))
        for thr_i, thr in enumerate(charness_threshes):
            if (C[i] > thr) != is_above[thr_i] \
              or (C[i] > mx_thr_charness and not is_above[thr_i]):
                step = 15 * (len(charness_threshes) - thr_i) \
                    if is_above[thr_i] \
                    else -15 * thr_i

                if is_above[thr_i]:
                    if 'down' not in crossings:
                        crossings['down'] = (C[i], t)
                    # else:
                    #     assert crossings['down'][0] > C[i], (crossings['down'][0], C[i])
                else:
                    if 'up' not in crossings:
                        crossings['up'] = (C[i - 1], t)
                    elif crossings['up'][0] < C[i - 1]:
                        crossings['up'] = (C[i - 1], t)

                # ax.annotate("%.3f\n#%d" % (C[i], t), xy=(t, C[i]),
                #             xytext=(t + step, C[i]-0.1),
                #             arrowprops=dict(facecolor='none', shrink=0.03))
                if C[i] < mn_thr_charness and is_above[thr_i]:
                    try:
                        c, t = max((e for e in mx_above), key=lambda e: e[0])
                        ax.annotate("%.3f\n#%d" % (c, t),
                                    xy=(t, c),
                                    xytext=(t + step, c + 0.1),
                                    arrowprops=dict(facecolor='none',
                                                    shrink=0.03))
                        mx_above = []
                        windows.append(
                            (crossings['up'][1], t, crossings['down'][1]))
                    except (KeyError, ValueError):
                        lg.warning("Can't find gap: %s, %s" %
                                   (crossings, mx_above))
                    crossings = {}

                is_above[thr_i] = C[i] > thr
                break

    for crossing in windows:
        for i, t in enumerate(crossing):
            c = skeleton.charness_poses[t]
            step = -15 + i * 10
            ax.annotate("%.3f\n#%d" % (c, t),
                        xy=(t, c),
                        xytext=(t + step, c - 0.1),
                        arrowprops=dict(facecolor='none', shrink=0.03))

    # extract_gaps([args.video])

    # labels
    ax.set_title("Scores and charness w.r.t time: max charness: #%d %g" %
                 (charness_sorted[-1][0], charness_sorted[-1][1]))
    ax.set_xlabel('integer time')
    ax.legend(loc='lower right')
    ax.grid(True)
    ax.yaxis.grid(which='both')
    ax.xaxis.set_ticks(np.arange(T[0] - 1, T[-1] + 1, 5))
    ax.set_yticks([])
    ax.set_ylim(0., 1.)
    ax.set_ylabel('higher is better')
    plt.suptitle("%s" % name_query)
    with open(os.path.join(d, 'charness_rank.csv'), 'w') as fout:
        fout.write("frame_id,charness\n")
        for fid_charness in reversed(charness_sorted):
            fout.write("{:d},{:g}\n".format(*fid_charness))
            print(fid_charness)
    # plt.show()
    p_out = os.path.join(d, 'charnesses.svg')
    plt.savefig(p_out)
    lg.debug("saved to %s" % p_out)
Esempio n. 15
0
def prepare(camera_name, winsorize_limit, shape_orig, path_scene, skel_ours_2d,
            skel_ours, resample, path_skel):
    """

    Args:
        camera_name (str):
            Name of camera for intrinsics calculation.
        winsorize_limit (float):
            Outlier detection threshold.
        shape_orig (Tuple[int, int]):
            Original video resolution.
        path_scene (str): Root path to scene.
        skel_ours_2d (np.ndarray): (N, 2, 16)
            2D skeletons from LFD in our format.
        skel_ours (np.ndarray): (N, 3, 16)
            Local space 3D skeletons in iMapper coordinate frame
            (y-down, z-front).
        resample (bool):
            If needs densification using Blender's IK engine.
    Returns:
        skel_ours (Skeleton):
        skel_ours_2d (Skeleton):
        intrinsics (np.ndarray):
    """
    assert camera_name is not None and isinstance(camera_name, str), \
        "Need a camera name"

    if shape_orig is None:
        shape_orig = (np.float32(1080.), np.float32(1920.))
    np.set_printoptions(linewidth=200, suppress=True)

    if False:
        plt.figure()
        for i, frame_id in enumerate(skel_ours.get_frames()):
            plot_2d(skel_ours_2d.get_pose(frame_id), images[frame_id])
            plt.show()

    path_intrinsics = os.path.join(path_scene, "intrinsics.json")
    if os.path.exists(path_intrinsics):
        lg.warning("Loading existing intrinsics matrix!")
        K = np.array(json.load(open(path_intrinsics, 'r')), dtype=np.float32)
        scale = (shape_orig[1] /
                 int(round(shape_orig[1] * float(INPUT_SIZE) / shape_orig[0])),
                 shape_orig[0] / float(INPUT_SIZE))
        K[0, 0] /= scale[0]
        K[0, 2] /= scale[0]
        K[1, 1] /= scale[1]
        K[1, 2] /= scale[1]
    else:
        K = intrinsics_matrix(INPUT_SIZE, shape_orig, camera_name)
        focal_correction = Conf.get().optimize_path.focal_correction
        if abs(focal_correction - 1.) > 1.e-3:
            lg.warning("Warning, scaling intrinsics matrix by %f" %
                       focal_correction)
            K[0, 0] *= focal_correction
            K[1, 1] *= focal_correction
    #print("K:\n%s,\nintr:\n%s" % (K, intr))
    # sys.exit(0)

    #
    # Prune poses
    #

    skel_ours_2d, frame_ids_removed = filter_outliers(
        skel_ours_2d, winsorize_limit=winsorize_limit, show=False)
    frames_to_remove_3d = filter_wrong_poses(skel_ours_2d, skel_ours)
    frames_to_ignore_list = set()
    # if frames_ignore is not None:
    #     for start_end in frames_ignore:
    #         if isinstance(start_end, tuple):
    #             l_ = list(range(
    #               start_end[0],
    #               min(start_end[1], skel_ours_2d.get_frames()[-1])))
    #             frames_to_remove_3d.extend(l_)
    #             frames_to_ignore_list.update(l_)
    #         else:
    #             assert isinstance(start_end, int), \
    #                 "Not int? %s" % repr(start_end)
    #             frames_to_remove_3d.append(start_end)
    #             frames_to_ignore_list.add(start_end)
    for frame_id in skel_ours.get_frames():
        if frame_id in frames_to_remove_3d:
            skel_ours.remove_pose(frame_id)

    # resample skeleton to fill in missing frames
    skel_ours_old = skel_ours
    frame_ids_filled_in = set(skel_ours_2d.get_frames()).difference(
        set(skel_ours_old.get_frames()))
    if resample:
        lg.warning("Resampling BEFORE optimization")
        # frames_to_resample = sorted(set(skel_ours_2d.get_frames()).difference(
        #   frames_to_ignore_list))
        # skel_ours = Skeleton.resample(skel_ours_old,
        #                               frame_ids=frames_to_resample)
        # Aron on 6/4/2018
        sclt_ours = Scenelet(skeleton=skel_ours)
        stem = os.path.splitext(path_skel)[0]
        path_filtered = "%s_filtered.json" % stem
        path_ipoled = "%s_ikipol.json" % os.path.splitext(path_filtered)[0]
        if not os.path.exists(path_ipoled):
            sclt_ours.save(path_filtered)
            script_filepath = \
                os.path.normpath(os.path.join(
                  os.path.dirname(os.path.abspath(__file__)),
                  os.pardir, 'blender', 'ipol_ik.py'))
            assert os.path.exists(script_filepath), "No: %s" % script_filepath
            blender_path = os.environ.get('BLENDER')
            if not os.path.isfile(blender_path):
                raise RuntimeError(
                    "Need \"BLENDER\" environment variable to be set "
                    "to the blender executable")
            cmd_params = [
                blender_path, '-noaudio', '-b', '-P', script_filepath, '--',
                path_filtered
            ]
            print("calling %s" % " ".join(cmd_params))
            ret = check_call(cmd_params)
            print("ret: %s" % ret)
        else:
            lg.warning("\n\n\tNOT recomputing IK interpolation, "
                       "file found at %s!\n" % path_ipoled)
        skel_ours = Scenelet.load(path_ipoled, no_obj=True).skeleton

        # remove extra frames at ends and beginnings of actors
        spans = skel_ours_old.get_actor_empty_frames()
        old_frames = skel_ours_old.get_frames()
        frames_to_remove = []
        for frame_id in skel_ours.get_frames():
            if frame_id not in old_frames:
                in_spans = next(
                    (True for span in spans if span[0] < frame_id < span[1]),
                    None)
                if in_spans:
                    frames_to_remove.append(frame_id)
                    # lg.debug("diff: %s  (a%s, f%s)"
                    #          % (
                    #              frame_id,
                    #              skel_ours_old.get_actor_id(frame_id),
                    #              skel_ours_old.mod_frame_id(frame_id)
                    #          ))
        for frame_id in frames_to_remove:
            skel_ours.remove_pose(frame_id)

    for frame_id in skel_ours_2d.get_frames():
        if not skel_ours.has_pose(frame_id):
            skel_ours_2d.remove_pose(frame_id)
    for frame_id in skel_ours.get_frames():
        if not skel_ours_2d.has_pose(frame_id):
            skel_ours.remove_pose(frame_id)
    frames_set_ours = set(skel_ours.get_frames())
    frames_set_2d = set(skel_ours_2d.get_frames())
    if frames_set_ours != frames_set_2d:
        print("Frame mismatch: %s" % frames_set_ours.difference(frames_set_2d))

    lg.warning("Removing pelvis and neck from 2D input")
    for frame_id in skel_ours_2d.get_frames():
        skel_ours_2d.set_visible(frame_id, Joint.PELV, 0)
        skel_ours_2d.set_visible(frame_id, Joint.NECK, 0)

    return skel_ours, skel_ours_2d, K, frame_ids_filled_in
Esempio n. 16
0
def evaluate(named_solution,
             sclt_gt,
             sclt_gt_2d,
             frame_ids,
             path_scene,
             stats,
             actions=None,
             scale=100.):
    """
    
    :param named_solution:
    :param sclt_gt:
    :param sclt_gt_2d:
    :param frame_ids:
    :param path_scene:
    :param stats:
    :param actions:
    :param scale: scale from meter to cm
    :return:
    """
    p_intrinsics = os.path.join(path_scene, 'intrinsics.json')
    intrinsics = np.array(json.load(open(p_intrinsics, 'r')), dtype=np.float32)
    print('Loading {}'.format(named_solution.path))
    sclt_sol = Scenelet.load(named_solution.path)
    sclt_sol.skeleton._visibility.clear()
    sclt_sol.skeleton._confidence.clear()
    sclt_sol.skeleton._forwards.clear()
    sclt_sol.skeleton = Skeleton.resample(sclt_sol.skeleton)
    err_3d = Comparison(title='World',
                        path_scene=path_scene,
                        name_method=named_solution.name_method,
                        stats=stats)
    err_3d_local = Comparison(title='Local',
                              path_scene=path_scene,
                              name_method=named_solution.name_method,
                              stats=stats)
    err_2d = Comparison(title='2D',
                        path_scene=path_scene,
                        name_method=named_solution.name_method,
                        stats=stats)

    occlusion = sclt_gt.aux_info['occluded']
    missing = {'method': [], 'gt': []}
    for frame_id in frame_ids:
        try:
            entry = sclt_sol.skeleton.get_pose(frame_id=frame_id)
        except KeyError:
            missing['method'].append(frame_id)
            continue
        if actions is not None and frame_id in actions \
          and actions[frame_id] == 'walking':
            print('Skipping non-interactive frame {} {}'.format(
                frame_id, actions[frame_id]))
            continue

        # 3D
        gt = sclt_gt.skeleton.get_pose(frame_id=frame_id)
        occluded = occlusion['{:d}'.format(frame_id)]
        err_3d.add(entry=entry,
                   gt=gt,
                   frame_id=frame_id,
                   scale=scale,
                   occluded=occluded)

        # Local 3D
        local_entry = entry - entry[:, Joint.PELV:Joint.PELV + 1]
        local_gt = gt - gt[:, Joint.PELV:Joint.PELV + 1]
        err_3d_local.add(entry=local_entry,
                         gt=local_gt,
                         frame_id=frame_id,
                         scale=scale,
                         occluded=occluded)

        #
        # GT 2D
        #

        gt_2d = sclt_gt_2d.skeleton.get_pose(frame_id=frame_id)
        entry_2d = entry[:2, :] / entry[2, :]
        entry_2d[0, :] *= intrinsics[0, 0]
        entry_2d[1, :] *= intrinsics[1, 1]
        entry_2d[0, :] += intrinsics[0, 2]
        entry_2d[1, :] += intrinsics[1, 2]

        err_2d.add(entry=entry_2d,
                   gt=gt_2d[:2, :],
                   frame_id=frame_id,
                   occluded=occluded)

    # stats.paint(path_dest=os.path.join(path_scene, 'debug_eval'))
    mn, mx = np.min(sclt_gt.skeleton.poses, axis=(0, 2)), \
             np.max(sclt_gt.skeleton.poses, axis=(0, 2))
    err_3d.dimensions = (mx - mn) * scale

    assert len(missing['method']) < len(frame_ids) / 2, (missing, frame_ids)

    return OrderedDict({
        err_3d.title: err_3d,
        err_3d_local.title: err_3d_local,
        err_2d.title: err_2d,
        '_missing': missing
    })
Esempio n. 17
0
def work_scene(p_root, plot_fun_name, name_scene, fname):
    pjoin = os.path.join

    name_scene = os.path.split(p_root)[-1]
    p_actions = os.path.join(p_root, 'gt', 'actions.txt')
    actions = None
    # if os.path.isfile(p_actions):
    #     with open(p_actions, 'r') as f:
    #         actions = [line.strip().split('\t') for line in f.readlines()]
    #         actions = {int(line[0]): line[1] for line in actions}

    p_quant2 = pjoin(p_root, _QUANT_FOLDER)
    if not os.path.isdir(p_quant2):
        os.makedirs(p_quant2)

    p_methods = []

    #
    # Tome3D
    #

    pfixes = [('Tome3D-nosmooth', '0')]  # ('Tome3D-smooth', '10')
    for postfix, smooth in pfixes:
        p_tome3d = pjoin(p_quant2,
                         'skel_{}_{}.json'.format(name_scene, postfix))
        p_tome_skels = pjoin(p_root, 'denis')
        if os.path.isfile(p_tome3d):
            p_methods.append(NamedSolution('\\tomethreed', p_tome3d))
        else:
            print('Can\'t find Tome3D at {}'.format(p_tome3d))

    #
    # LCR-Net 3D
    #

    postfix = 'LCRNet3D-nosmooth'
    p_lcrnet3d = pjoin(p_quant2, 'skel_{}_{}.json'.format(name_scene, postfix))
    if os.path.isfile(p_lcrnet3d):
        p_methods.append(
            NamedSolution('\\lcrnetthreed$_{no smooth}$', p_lcrnet3d))
    else:
        print('Can\'t find Tome3D at {}'.format(p_tome3d))

    #
    # GT
    #

    p_gt = pjoin(p_root, 'gt', 'skel_{}_GT.json'.format(name_scene))
    assert os.path.isfile(p_gt), 'Need gt file: {}'.format(p_gt)
    sclt_gt = Scenelet.load(p_gt)

    p_gt_2d = pjoin(p_root, 'gt', 'skel_GT_2d.json')
    sclt_gt_2d = Scenelet.load(p_gt_2d)

    #
    # Evaluate
    #

    p_methods.append(NamedSolution('\\name', pjoin(p_root, 'output', fname)))

    # Append your solution here

    p_methods.append(
        NamedSolution('NewMethod', pjoin(p_root, 'NewMethod', fname)))

    stats = StatsOverTime(plot_fun_name=plot_fun_name, name_scene=name_scene)
    errors = OrderedDict()
    for named_solution in p_methods:
        frame_ids = [
            fid for fid in sclt_gt.skeleton.get_frames() if not fid % 2
        ]
        # print(frame_ids)
        errors_ = evaluate(named_solution=named_solution,
                           sclt_gt=sclt_gt,
                           sclt_gt_2d=sclt_gt_2d,
                           frame_ids=frame_ids,
                           path_scene=p_root,
                           stats=stats,
                           actions=actions)
        errors[named_solution.name_method] = errors_
    series = stats.paint(path_dest=os.path.join(p_root, 'debug_eval'))
    return errors, series