| 12015 | } |
| 12016 | |
| 12017 | int sam3_tracker_add_instance(sam3_tracker& tracker, sam3_state& state, |
| 12018 | const sam3_model& model, |
| 12019 | const sam3_pvs_params& pvs_params) { |
| 12020 | const int D = model.hparams.neck_dim; |
| 12021 | const int mask_hw = sam3_eff_feat_size(state, model.hparams) * 4; |
| 12022 | |
| 12023 | // Run PVS to get the segmentation mask |
| 12024 | auto r = sam3_segment_pvs(state, model, pvs_params); |
| 12025 | if (r.detections.empty()) { |
| 12026 | fprintf(stderr, "%s: PVS returned no masks\n", __func__); |
| 12027 | return -1; |
| 12028 | } |
| 12029 | |
| 12030 | const auto& det = r.detections[0]; |
| 12031 | if (det.mask.data.empty()) { |
| 12032 | fprintf(stderr, "%s: PVS mask is empty\n", __func__); |
| 12033 | return -1; |
| 12034 | } |
| 12035 | |
| 12036 | int inst_id = tracker.next_inst_id++; |
| 12037 | // tracker.frame_index points to the *next* frame to process; |
| 12038 | // the instance is being added on the frame that was just tracked. |
| 12039 | int fi = tracker.frame_index - 1; |
| 12040 | if (fi < 0) fi = 0; |
| 12041 | |
| 12042 | // Create synthetic 288x288 logits from the binary mask. |
| 12043 | // sam3_encode_memory applies sigmoid then scale/bias, so +6/-6 gives |
| 12044 | // sigmoid values ~0.9975/~0.0025 — practically identical to real logits. |
| 12045 | std::vector<float> synth_logits(mask_hw * mask_hw); |
| 12046 | { |
| 12047 | int mw = det.mask.width, mh = det.mask.height; |
| 12048 | for (int y = 0; y < mask_hw; ++y) { |
| 12049 | int sy = y * mh / mask_hw; |
| 12050 | for (int x = 0; x < mask_hw; ++x) { |
| 12051 | int sx = x * mw / mask_hw; |
| 12052 | synth_logits[y * mask_hw + x] = |
| 12053 | (det.mask.data[sy * mw + sx] > 127) ? 6.0f : -6.0f; |
| 12054 | } |
| 12055 | } |
| 12056 | } |
| 12057 | |
| 12058 | // Encode into memory bank |
| 12059 | float obj_score = det.mask.obj_score; |
| 12060 | if (!sam3_encode_memory(tracker, state, model, inst_id, |
| 12061 | synth_logits.data(), mask_hw, mask_hw, |
| 12062 | fi, true, obj_score)) { |
| 12063 | fprintf(stderr, "%s: failed to encode memory for instance %d\n", __func__, inst_id); |
| 12064 | return -1; |
| 12065 | } |
| 12066 | |
| 12067 | // Extract object pointer from the SAM decoder token |
| 12068 | std::vector<float> op(D); |
| 12069 | if (!det.sam_token.empty()) { |
| 12070 | sam3_extract_obj_ptr_cpu(model, det.sam_token.data(), obj_score, op.data()); |
| 12071 | } else { |
| 12072 | std::fill(op.begin(), op.end(), 0.0f); |
| 12073 | } |
| 12074 | sam3_store_obj_ptr(tracker, model, inst_id, op.data(), fi); |