| 6 | namespace imgproc { |
| 7 | |
| 8 | std::vector<float> resize_bicubic_plane( |
| 9 | const std::vector<float>& src, |
| 10 | int src_w, int src_h, |
| 11 | int dst_w, int dst_h, |
| 12 | bool antialias) |
| 13 | { |
| 14 | std::vector<float> dst(static_cast<size_t>(dst_w) * dst_h); |
| 15 | |
| 16 | // PyTorch's exact scale calculation (align_corners=False for resize) |
| 17 | const float scale_w = area_pixel_compute_scale(src_w, dst_w, false); |
| 18 | const float scale_h = area_pixel_compute_scale(src_h, dst_h, false); |
| 19 | |
| 20 | // PyTorch antialias logic |
| 21 | const bool do_antialias_w = antialias && (scale_w > 1.0f); |
| 22 | const bool do_antialias_h = antialias && (scale_h > 1.0f); |
| 23 | |
| 24 | // PyTorch kernel support and sigma calculation |
| 25 | const float support = 2.0f; // bicubic kernel support |
| 26 | const float clamped_scale_w = do_antialias_w ? scale_w : 1.0f; |
| 27 | const float clamped_scale_h = do_antialias_h ? scale_h : 1.0f; |
| 28 | |
| 29 | // PyTorch's exact sigma calculation |
| 30 | const float sigma_w = do_antialias_w ? (clamped_scale_w * support) / 2.0f : 0.0f; |
| 31 | const float sigma_h = do_antialias_h ? (clamped_scale_h * support) / 2.0f : 0.0f; |
| 32 | |
| 33 | for (int dst_y = 0; dst_y < dst_h; ++dst_y) { |
| 34 | // PyTorch's exact coordinate calculation |
| 35 | float real_y = area_pixel_compute_source_index(scale_h, dst_y, false, true); |
| 36 | int input_y = static_cast<int>(std::floor(real_y)); |
| 37 | float t_y = real_y - input_y; |
| 38 | |
| 39 | for (int dst_x = 0; dst_x < dst_w; ++dst_x) { |
| 40 | float real_x = area_pixel_compute_source_index(scale_w, dst_x, false, true); |
| 41 | int input_x = static_cast<int>(std::floor(real_x)); |
| 42 | float t_x = real_x - input_x; |
| 43 | |
| 44 | float sum = 0.0f, wsum = 0.0f; |
| 45 | |
| 46 | // PyTorch uses exact 4x4 neighborhood for bicubic |
| 47 | for (int yy = -1; yy <= 2; ++yy) { |
| 48 | int src_y = clamp(input_y + yy, 0, src_h - 1); |
| 49 | float dy = real_y - (input_y + yy); |
| 50 | float wy = bicubic_kernel(dy / clamped_scale_h); |
| 51 | if (do_antialias_h) { |
| 52 | wy *= gaussian(dy, sigma_h); |
| 53 | } |
| 54 | |
| 55 | for (int xx = -1; xx <= 2; ++xx) { |
| 56 | int src_x = clamp(input_x + xx, 0, src_w - 1); |
| 57 | float dx = real_x - (input_x + xx); |
| 58 | float wx = bicubic_kernel(dx / clamped_scale_w); |
| 59 | if (do_antialias_w) { |
| 60 | wx *= gaussian(dx, sigma_w); |
| 61 | } |
| 62 | |
| 63 | float weight = wx * wy; |
| 64 | sum += src[src_y * src_w + src_x] * weight; |
| 65 | wsum += weight; |
no test coverage detected