MCPcopy Create free account
hub / github.com/PABannier/sam3.cpp / sam2_compute_pos_embed

Function sam2_compute_pos_embed

sam3.cpp:4118–4175  ·  view source on GitHub ↗

Compute Hiera positional embedding on CPU. Returns [E, H, W] in ggml column-major layout: element (e, x, y) at flat index e + x*E + y*E*W. PE = bicubic_interp(pos_embed_bkg, (H, W)) + tile(pos_embed_window, (H/W0, W/W0))

Source from the content-addressed store, hash-verified

4116// Returns [E, H, W] in ggml column-major layout: element (e, x, y) at flat index e + x*E + y*E*W.
4117// PE = bicubic_interp(pos_embed_bkg, (H, W)) + tile(pos_embed_window, (H/W0, W/W0))
4118static std::vector<float> sam2_compute_pos_embed(const sam3_model& model, int H, int W) {
4119 const auto& hp = model.hparams;
4120 const int E = hp.hiera_embed_dim;
4121 const int bkg_h = hp.hiera_pos_embed_bkg_h;
4122 const int bkg_w = hp.hiera_pos_embed_bkg_w;
4123 const int ws = hp.hiera_window_spec[0];
4124
4125 // Read background PE from GPU.
4126 // Registered as [bkg_w, bkg_h, E, 1] in ggml; raw bytes match PyTorch NCHW [1,E,H,W].
4127 // ggml flat index for ne=[W,H,E,1]: w + h*W + e*W*H = same as CHW[e,h,w] = e*H*W + h*W + w.
4128 // So we can use the raw data directly as CHW layout for bicubic interpolation.
4129 std::vector<float> bkg_chw(E * bkg_h * bkg_w);
4130 ggml_backend_tensor_get(model.hiera.pos_embed, bkg_chw.data(), 0,
4131 bkg_chw.size() * sizeof(float));
4132
4133 // Bicubic interpolate to [E, H, W]
4134 std::vector<float> bkg_interp(E * H * W);
4135 sam2_bicubic_interpolate_cpu(bkg_chw.data(), E, bkg_h, bkg_w,
4136 bkg_interp.data(), H, W);
4137
4138 // Read window PE from GPU: registered [ws, ws, E, 1], raw bytes = CHW [E, ws, ws]
4139 std::vector<float> win_chw(E * ws * ws);
4140 ggml_backend_tensor_get(model.hiera.pos_embed_window, win_chw.data(), 0,
4141 win_chw.size() * sizeof(float));
4142
4143 // Tile window PE to [E, H, W]
4144 std::vector<float> win_tiled(E * H * W);
4145 for (int e = 0; e < E; ++e)
4146 for (int y = 0; y < H; ++y)
4147 for (int x = 0; x < W; ++x)
4148 win_tiled[e * H * W + y * W + x] = win_chw[e * ws * ws + (y % ws) * ws + (x % ws)];
4149
4150 // Dump intermediates if requested
4151 const char* dump_dir = getenv("SAM2_DUMP_DIR");
4152 if (dump_dir) {
4153 char path[512];
4154 // Dump bkg_interp as CHW
4155 snprintf(path, sizeof(path), "%s/cpp_pe_bkg_interp.bin", dump_dir);
4156 FILE* f = fopen(path, "wb");
4157 if (f) { fwrite(bkg_interp.data(), sizeof(float), bkg_interp.size(), f); fclose(f); }
4158 snprintf(path, sizeof(path), "%s/cpp_pe_bkg_interp.shape", dump_dir);
4159 f = fopen(path, "w"); if (f) { fprintf(f, "%d,%d,%d", E, H, W); fclose(f); }
4160 // Dump win_tiled as CHW
4161 snprintf(path, sizeof(path), "%s/cpp_pe_win_tiled.bin", dump_dir);
4162 f = fopen(path, "wb");
4163 if (f) { fwrite(win_tiled.data(), sizeof(float), win_tiled.size(), f); fclose(f); }
4164 }
4165
4166 // Sum and convert to ggml layout [E, W, H, 1]
4167 std::vector<float> pe(E * H * W);
4168 for (int e = 0; e < E; ++e)
4169 for (int y = 0; y < H; ++y)
4170 for (int x = 0; x < W; ++x)
4171 pe[e + x * E + y * E * W] = bkg_interp[e * H * W + y * W + x]
4172 + win_tiled[e * H * W + y * W + x];
4173
4174 return pe;
4175}

Callers 2

sam2_encode_image_hieraFunction · 0.85

Calls 1

Tested by

no test coverage detected