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

Function sam3_roi_align_single

sam3.cpp:7607–7666  ·  view source on GitHub ↗

CPU-side ROI Align matching torchvision.ops.roi_align behavior. Features in ggml [C, W, H] layout. Box in XYXY format scaled to feature grid coords. Uses sub-sampling matching torchvision's sampling_ratio=0 (auto). Output: [C * roi_size * roi_size] in ggml layout.

Source from the content-addressed store, hash-verified

7605// Uses sub-sampling matching torchvision's sampling_ratio=0 (auto).
7606// Output: [C * roi_size * roi_size] in ggml layout.
7607static void sam3_roi_align_single(
7608 const float* feats, // [C, W, H] ggml layout (C innermost, then W, then H)
7609 int C, int W_feat, int H_feat,
7610 float x0, float y0, float x1, float y1,
7611 int roi_size,
7612 float* out) // [C, roi_size, roi_size]
7613{
7614 float roi_w = std::max(x1 - x0, 1e-6f);
7615 float roi_h = std::max(y1 - y0, 1e-6f);
7616 float bin_w = roi_w / (float)roi_size;
7617 float bin_h = roi_h / (float)roi_size;
7618
7619 // Match torchvision sampling_ratio=0: use ceil(bin_size) sub-samples
7620 int sample_y_count = std::max(1, (int)ceilf(bin_h));
7621 int sample_x_count = std::max(1, (int)ceilf(bin_w));
7622 float inv_count = 1.0f / (float)(sample_y_count * sample_x_count);
7623
7624 auto bilinear_sample = [&](float sx, float sy, int c) -> float {
7625 // Clamp to [-0.5, W-0.5] then adjust — matching torchvision
7626 if (sx < -1.0f || sx > (float)W_feat || sy < -1.0f || sy > (float)H_feat)
7627 return 0.0f;
7628
7629 sy = std::max(0.0f, sy);
7630 sx = std::max(0.0f, sx);
7631
7632 int y_lo = (int)sy;
7633 int x_lo = (int)sx;
7634 int y_hi = std::min(y_lo + 1, H_feat - 1);
7635 int x_hi = std::min(x_lo + 1, W_feat - 1);
7636 y_lo = std::min(y_lo, H_feat - 1);
7637 x_lo = std::min(x_lo, W_feat - 1);
7638
7639 float ly = sy - (float)y_lo;
7640 float lx = sx - (float)x_lo;
7641
7642 // ggml layout: feats[c + x * C + y * C * W_feat]
7643 float v00 = feats[c + x_lo * C + y_lo * C * W_feat];
7644 float v10 = feats[c + x_hi * C + y_lo * C * W_feat];
7645 float v01 = feats[c + x_lo * C + y_hi * C * W_feat];
7646 float v11 = feats[c + x_hi * C + y_hi * C * W_feat];
7647
7648 return v00 * (1 - ly) * (1 - lx) + v10 * (1 - ly) * lx + v01 * ly * (1 - lx) + v11 * ly * lx;
7649 };
7650
7651 for (int ph = 0; ph < roi_size; ++ph) {
7652 for (int pw = 0; pw < roi_size; ++pw) {
7653 for (int c = 0; c < C; ++c) {
7654 float sum = 0.0f;
7655 for (int iy = 0; iy < sample_y_count; ++iy) {
7656 float sy = y0 + bin_h * ((float)ph + ((float)iy + 0.5f) / (float)sample_y_count);
7657 for (int ix = 0; ix < sample_x_count; ++ix) {
7658 float sx = x0 + bin_w * ((float)pw + ((float)ix + 0.5f) / (float)sample_x_count);
7659 sum += bilinear_sample(sx, sy, c);
7660 }
7661 }
7662 out[c + pw * C + ph * C * roi_size] = sum * inv_count;
7663 }
7664 }

Callers 1

Calls

no outgoing calls

Tested by

no test coverage detected