Extract object pointer from SAM output token via 3-layer MLP (CPU-side).
| 9346 | |
| 9347 | // Extract object pointer from SAM output token via 3-layer MLP (CPU-side). |
| 9348 | static void sam3_extract_obj_ptr_cpu( |
| 9349 | const sam3_model& model, |
| 9350 | const float* sam_token_data, // [D] |
| 9351 | float obj_score, |
| 9352 | float* out_ptr) // [D] |
| 9353 | { |
| 9354 | const auto& hp = model.hparams; |
| 9355 | const int D = hp.neck_dim; |
| 9356 | |
| 9357 | // SAM2/EdgeTAM with fixed_no_obj_ptr: blend projected ptr with no_obj_ptr |
| 9358 | // based on presence score λ. |
| 9359 | // SAM3 / SAM2 without fixed_no_obj_ptr: binary threshold. |
| 9360 | if ((hp.is_sam2() || hp.is_edgetam()) && hp.fixed_no_obj_ptr) { |
| 9361 | // λ = (obj_score > 0) ? 1.0 : 0.0 (hard threshold, not sigmoid) |
| 9362 | float lambda = (obj_score > 0.0f) ? 1.0f : 0.0f; |
| 9363 | |
| 9364 | // Project token through MLP |
| 9365 | std::vector<float> h(D), tmp(D); |
| 9366 | std::copy(sam_token_data, sam_token_data + D, h.data()); |
| 9367 | for (int j = 0; j < 3; ++j) { |
| 9368 | auto* w = model.obj_ptr_proj_w[j]; |
| 9369 | auto* b = model.obj_ptr_proj_b[j]; |
| 9370 | int nel_w = (int)(w->ne[0] * w->ne[1]); |
| 9371 | std::vector<float> w_data(nel_w), b_data(D); |
| 9372 | sam3_read_f32(w, w_data.data(), nel_w); |
| 9373 | sam3_read_f32(b, b_data.data(), D); |
| 9374 | for (int o = 0; o < D; ++o) { |
| 9375 | float sum = b_data[o]; |
| 9376 | for (int i = 0; i < D; ++i) sum += w_data[o * D + i] * h[i]; |
| 9377 | tmp[o] = (j < 2) ? std::max(0.0f, sum) : sum; |
| 9378 | } |
| 9379 | std::swap(h, tmp); |
| 9380 | } |
| 9381 | |
| 9382 | // Blend: obj_ptr = λ * projected + (1-λ) * no_obj_ptr |
| 9383 | std::vector<float> no_ptr(D); |
| 9384 | ggml_backend_tensor_get(model.no_obj_ptr, no_ptr.data(), 0, D * sizeof(float)); |
| 9385 | for (int i = 0; i < D; ++i) |
| 9386 | out_ptr[i] = lambda * h[i] + (1.0f - lambda) * no_ptr[i]; |
| 9387 | return; |
| 9388 | } |
| 9389 | |
| 9390 | // SAM3 / default path: binary threshold |
| 9391 | if (obj_score <= 0.0f) { |
| 9392 | ggml_backend_tensor_get(model.no_obj_ptr, out_ptr, 0, D * sizeof(float)); |
| 9393 | return; |
| 9394 | } |
| 9395 | |
| 9396 | std::vector<float> h(D), tmp(D); |
| 9397 | std::copy(sam_token_data, sam_token_data + D, h.data()); |
| 9398 | |
| 9399 | for (int j = 0; j < 3; ++j) { |
| 9400 | auto* w = model.obj_ptr_proj_w[j]; |
| 9401 | auto* b = model.obj_ptr_proj_b[j]; |
| 9402 | |
| 9403 | int nel_w = (int)(w->ne[0] * w->ne[1]); |
| 9404 | std::vector<float> w_data(nel_w); |
| 9405 | sam3_read_f32(w, w_data.data(), nel_w); |
no test coverage detected