| """Eager SAM3 track_step baseline: frame 0 mask-init + frames 1..TARGET propagation. |
| Caches per-frame outputs needed by the dense wrapper + TARGET/warmup eager |
| outputs for parity checking. One-time cost; results go to eager_cache.pt. |
| """ |
|
|
| import time |
| import torch |
| import common |
|
|
| TARGET = 16 |
| WARMUP = 3 |
|
|
|
|
| def bf_prop(model, frame_idx): |
| feats, sizes = common.synth_frame_features(model, frame_idx) |
| pos72 = common.POS72 |
| return { |
| "vision_feats": feats, |
| "vision_masks": [None, None, None], |
| "vision_pos_embeds": [None, None, pos72], |
| "feat_sizes": sizes, |
| } |
|
|
|
|
| def bf_inter(model, frame_idx): |
| feats, sizes = common.synth_frame_features(model, frame_idx) |
| return {"vision_feats": feats, "feat_sizes": sizes} |
|
|
|
|
| def main(): |
| model = common.build_model() |
| common.POS72 = common.pos_embed_72(model) |
| ms = common.make_multiplex_state(model) |
| output_dict = {"cond_frame_outputs": {}, "non_cond_frame_outputs": {}} |
|
|
| with torch.no_grad(): |
| |
| t0 = time.time() |
| out0 = model.track_step( |
| frame_idx=0, |
| is_init_cond_frame=True, |
| backbone_features_interactive=bf_inter(model, 0), |
| backbone_features_propagation=bf_prop(model, 0), |
| image=None, |
| point_inputs=None, |
| mask_inputs=common.init_masks(), |
| gt_masks=None, |
| frames_to_add_correction_pt=[], |
| output_dict=output_dict, |
| num_frames=64, |
| multiplex_state=ms, |
| ) |
| output_dict["cond_frame_outputs"][0] = out0 |
| print(f"frame 0 (init): {time.time()-t0:.1f}s") |
| for k, v in out0.items(): |
| if torch.is_tensor(v): |
| print(f" {k}: {tuple(v.shape)} {v.dtype}") |
| elif isinstance(v, list) and v and torch.is_tensor(v[0]): |
| print(f" {k}: list[{tuple(v[0].shape)}]") |
| else: |
| print(f" {k}: {type(v).__name__} {v if isinstance(v, set) else ''}") |
|
|
| |
| for f in range(1, TARGET + 1): |
| t0 = time.time() |
| out = model.track_step( |
| frame_idx=f, |
| is_init_cond_frame=False, |
| backbone_features_interactive=None, |
| backbone_features_propagation=bf_prop(model, f), |
| image=None, |
| point_inputs=None, |
| mask_inputs=None, |
| gt_masks=None, |
| frames_to_add_correction_pt=[], |
| output_dict=output_dict, |
| num_frames=64, |
| multiplex_state=ms, |
| ) |
| output_dict["non_cond_frame_outputs"][f] = out |
| print(f"frame {f}: {time.time()-t0:.1f}s " |
| f"maskmem {tuple(out['maskmem_features'].shape)} " |
| f"obj_ptr {tuple(out['obj_ptr'].shape)}") |
|
|
| |
| keep = ["maskmem_features", "maskmem_pos_enc", "obj_ptr", |
| "image_features", "image_pos_enc", "object_score_logits"] |
| cache = {"cond": {}, "frames": {}, "target": {}, "warmup": {}} |
| for k in keep: |
| cache["cond"][k] = out0.get(k) |
| for f in range(1, TARGET): |
| cache["frames"][f] = {k: output_dict["non_cond_frame_outputs"][f].get(k) |
| for k in keep} |
|
|
| def pack_target(frame_idx, bucket): |
| tgt = output_dict["non_cond_frame_outputs"][frame_idx] |
| for k in ["pred_masks", "pred_masks_high_res", "object_score_logits", |
| "maskmem_features", "obj_ptr"]: |
| bucket[k] = tgt[k] |
| bucket["ious"] = tgt["multistep_pred_ious"][-1] |
|
|
| pack_target(TARGET, cache["target"]) |
| cache["target_frame"] = TARGET |
| pack_target(WARMUP, cache["warmup"]) |
| cache["warmup_frame"] = WARMUP |
|
|
| torch.save(cache, "eager_cache.pt") |
| print("saved eager_cache.pt") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|