sam3.1-coreml / tracker /scripts /coreml_traj_test.py
sdkv2's picture
Merge tracker + backbone, drop kino references
47d8ad6 verified
Raw
History Blame Contribute Delete
1.99 kB
"""Trajectory parity: torch wrapper vs converted CoreML model, both from zero
state, 18 sequential frames with real per-frame inputs. Early frames sit on the
object-score decision boundary (degenerate zero memory); the test is whether
late frames track once banks hold real memories.
"""
import numpy as np
import torch
import common
import dense_wrapper as dw
def main():
import coremltools as ct
cache = torch.load("eager_cache.pt", weights_only=False)
wrapper, model = dw.build_wrapper()
wrapper.mem_bank.zero_(); wrapper.img_bank.zero_(); wrapper.ptr_bank.zero_()
mlmodel = ct.models.MLModel("dense_sam3_trackstep.mlpackage",
compute_units=ct.ComputeUnit.CPU_ONLY)
in_names = [i.name for i in mlmodel.input_description._fd_spec]
state = mlmodel.make_state()
frames = list(range(16, 34))
print(f"{'frame':>5} {'osl_rel':>9} {'iou_rel':>9} {'mask_sign_agree':>15} "
f"{'lowmask_rel':>11}")
for f in frames:
inputs = dw.frame_inputs(model, cache, f)
with torch.no_grad():
t_low, t_high, t_osl, t_ious = [x.clone() for x in wrapper(*inputs)]
feed = {n: v.numpy().astype(np.float32)
for n, v in zip(in_names, inputs)}
got = mlmodel.predict(feed, state=state)
# map outputs by shape (names are auto-generated)
by_shape = {tuple(np.asarray(v).shape): torch.from_numpy(
np.asarray(v)).float() for v in got.values()}
c_low = by_shape[tuple(t_low.shape)]
c_osl = by_shape[tuple(t_osl.shape)]
c_ious = by_shape[tuple(t_ious.shape)]
def rel(a, b):
return ((a - b).abs().max() / b.abs().max().clamp_min(1e-9)).item()
sign_agree = ((c_low > 0) == (t_low > 0)).float().mean().item()
print(f"{f:>5} {rel(c_osl, t_osl):>9.2e} {rel(c_ious, t_ious):>9.2e} "
f"{sign_agree:>15.4f} {rel(c_low, t_low):>11.2e}")
if __name__ == "__main__":
main()