Files
wehub-resource-sync 5cbd3f29e3
Fuzz / Run fuzz harnesses (${{ github.event_name == 'schedule' && 'nightly' || 'smoke' }}) (push) Has been cancelled
Create Releases / call-mac (push) Has been cancelled
Create Releases / call-linux (push) Has been cancelled
Create Releases / call-sdist (push) Has been cancelled
Create Releases / call-win (push) Has been cancelled
Create Releases / call-pyodide (push) Has been cancelled
Windows_No_Exception_CI / build (x64, 3.10) (push) Has been cancelled
Check URLs / build (push) Has been cancelled
Create Releases / Attest CI build artifacts (push) Has been cancelled
Create Releases / Check for Publish release build to pypi (push) Has been cancelled
Create Releases / Check for Publish preview build to test.pypi-weekly (push) Has been cancelled
Create Releases / Publish preview build to test.pypi-weekly (push) Has been cancelled
Create Releases / Check for Publish release build to test.pypi (rc-candidates) (push) Has been cancelled
Create Releases / Publish release build to test.pypi (push) Has been cancelled
Create Releases / Check for Publish preview build to pypi-weekly (push) Has been cancelled
Create Releases / Publish preview build to pypi-weekly (push) Has been cancelled
Create Releases / Publish release build to pypi (push) Has been cancelled
Create Releases / test source distribution (push) Has been cancelled
clang-tidy / clang-tidy (push) Has been cancelled
Lint / Validate SBOM (push) Has been cancelled
Lint / Enforce style (push) Has been cancelled
CI / Test windows-2022, 3.14, External, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
CI / Test windows-latest, 3.10, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
CI / Test windows-latest, 3.14, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
CI / Test windows-latest, 3.14t, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
CI / Test ubuntu-24.04, 3.14, Internal, debug=1, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
CI / Test ubuntu-24.04, 3.14, External, debug=0, unity_build=1, onnx_ml=1, autogen=1 (push) Has been cancelled
CI / Test ubuntu-24.04, 3.14, External, debug=0, unity_build=0, onnx_ml=0, autogen=0 (push) Has been cancelled
CI / Test macos-latest, 3.10, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
CI / Test macos-latest, 3.14, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
CI / Test macos-latest, 3.14t, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
CI / Test ubuntu-24.04, 3.14, External, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
CI / Test ubuntu-24.04, 3.10, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
CI / Test ubuntu-24.04, 3.14, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
CI / Test ubuntu-24.04, 3.14t, Internal, debug=0, unity_build=0, onnx_ml=1, autogen=0 (push) Has been cancelled
Pixi CI / Install and lint (ubuntu-24.04-arm) (push) Has been cancelled
Pixi CI / Install and lint (windows-2022) (push) Has been cancelled
Pixi CI / Xcode generator build (push) Has been cancelled
Pixi CI / Install and test (macos-latest, default) (push) Has been cancelled
Pixi CI / Install and test (ubuntu-24.04-arm, default) (push) Has been cancelled
Pixi CI / Install and test (ubuntu-latest, default) (push) Has been cancelled
Pixi CI / Install and test (windows-2022, default) (push) Has been cancelled
Pixi CI / Install and test (macos-latest, oldies) (push) Has been cancelled
Pixi CI / Install and test (ubuntu-24.04-arm, oldies) (push) Has been cancelled
Pixi CI / Install and test (ubuntu-latest, oldies) (push) Has been cancelled
Pixi CI / Install and test (windows-2022, oldies) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (cpp) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Copilot Setup Steps / copilot-setup-steps (push) Has been cancelled
Generate and publish ONNX docs / build (push) Has been cancelled
Generate and publish ONNX docs / deploy (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:41:19 +08:00

297 lines
11 KiB
Python

# Copyright (c) ONNX Project Contributors
# SPDX-License-Identifier: Apache-2.0
from __future__ import annotations
import numpy as np
from onnx.reference.op_run import OpRun
class PreCalc:
def __init__(self, pos1=0, pos2=0, pos3=0, pos4=0, w1=0, w2=0, w3=0, w4=0):
self.pos1 = pos1
self.pos2 = pos2
self.pos3 = pos3
self.pos4 = pos4
self.w1 = w1
self.w2 = w2
self.w3 = w3
self.w4 = w4
def __repr__(self) -> str:
return f"PreCalc({self.pos1},{self.pos2},{self.pos3},{self.pos4},{self.w1},{self.w2},{self.w3},{self.w4})"
class RoiAlign(OpRun):
@staticmethod
def pre_calc_for_bilinear_interpolate(
height: int,
width: int,
pooled_height: int,
pooled_width: int,
iy_upper: int,
ix_upper: int,
roi_start_h,
roi_start_w,
bin_size_h,
bin_size_w,
roi_bin_grid_h: int,
roi_bin_grid_w: int,
pre_calc,
):
pre_calc_index = 0
for ph in range(pooled_height):
for pw in range(pooled_width):
for iy in range(iy_upper):
yy = (
roi_start_h
+ ph * bin_size_h
+ (iy + 0.5) * bin_size_h / roi_bin_grid_h
)
for ix in range(ix_upper):
xx = (
roi_start_w
+ pw * bin_size_w
+ (ix + 0.5) * bin_size_w / roi_bin_grid_w
)
x = xx
y = yy
# deal with: inverse elements are out of feature map boundary
if y < -1.0 or y > height or x < -1.0 or x > width:
pc = pre_calc[pre_calc_index]
pc.pos1 = 0
pc.pos2 = 0
pc.pos3 = 0
pc.pos4 = 0
pc.w1 = 0
pc.w2 = 0
pc.w3 = 0
pc.w4 = 0
pre_calc_index += 1
continue
y = max(y, 0)
x = max(x, 0)
y_low = int(y)
x_low = int(x)
if y_low >= height - 1:
y_high = y_low = height - 1
y = y_low
else:
y_high = y_low + 1
if x_low >= width - 1:
x_high = x_low = width - 1
x = x_low
else:
x_high = x_low + 1
ly = y - y_low
lx = x - x_low
hy = 1.0 - ly
hx = 1.0 - lx
w1 = hy * hx
w2 = hy * lx
w3 = ly * hx
w4 = ly * lx
# save weights and indices
pc = PreCalc()
pc.pos1 = y_low * width + x_low
pc.pos2 = y_low * width + x_high
pc.pos3 = y_high * width + x_low
pc.pos4 = y_high * width + x_high
pc.w1 = w1
pc.w2 = w2
pc.w3 = w3
pc.w4 = w4
pre_calc[pre_calc_index] = pc
pre_calc_index += 1
@staticmethod
def roi_align_forward(
output_shape: tuple[int, int, int, int],
bottom_data,
spatial_scale,
height: int,
width: int,
sampling_ratio,
bottom_rois,
num_roi_cols: int,
top_data,
mode,
half_pixel: bool,
batch_indices_ptr,
):
n_rois = output_shape[0]
channels = output_shape[1]
pooled_height = output_shape[2]
pooled_width = output_shape[3]
# 100 is a random chosen value, need be tuned
for n in range(n_rois):
index_n = n * channels * pooled_width * pooled_height
# bottom_rois
offset_bottom_rois = n * num_roi_cols
roi_batch_ind = batch_indices_ptr[n]
# Do not using rounding; this implementation detail is critical.
offset = 0.5 if half_pixel else 0.0
roi_start_w = bottom_rois[offset_bottom_rois + 0] * spatial_scale - offset
roi_start_h = bottom_rois[offset_bottom_rois + 1] * spatial_scale - offset
roi_end_w = bottom_rois[offset_bottom_rois + 2] * spatial_scale - offset
roi_end_h = bottom_rois[offset_bottom_rois + 3] * spatial_scale - offset
roi_width = roi_end_w - roi_start_w
roi_height = roi_end_h - roi_start_h
if not half_pixel:
# Force malformed ROIs to be 1x1
roi_width = max(roi_width, 1.0)
roi_height = max(roi_height, 1.0)
bin_size_h = roi_height / pooled_height
bin_size_w = roi_width / pooled_width
# We use roi_bin_grid to sample the grid and mimic integral
roi_bin_grid_h = (
int(sampling_ratio)
if sampling_ratio > 0
else int(np.ceil(roi_height / pooled_height))
)
roi_bin_grid_w = (
int(sampling_ratio)
if sampling_ratio > 0
else int(np.ceil(roi_width / pooled_width))
)
# We do average (integral) pooling inside a bin
count = int(max(roi_bin_grid_h * roi_bin_grid_w, 1))
# we want to precalculate indices and weights shared by all channels,
# this is the key point of optimization
pre_calc = [
PreCalc()
for i in range(
roi_bin_grid_h * roi_bin_grid_w * pooled_width * pooled_height
)
]
RoiAlign.pre_calc_for_bilinear_interpolate(
height,
width,
pooled_height,
pooled_width,
roi_bin_grid_h,
roi_bin_grid_w,
roi_start_h,
roi_start_w,
bin_size_h,
bin_size_w,
roi_bin_grid_h,
roi_bin_grid_w,
pre_calc,
)
for c in range(channels):
index_n_c = index_n + c * pooled_width * pooled_height
# bottom_data
offset_bottom_data = int(
(roi_batch_ind * channels + c) * height * width
)
pre_calc_index = 0
for ph in range(pooled_height):
for pw in range(pooled_width):
index = index_n_c + ph * pooled_width + pw
output_val = 0.0
if mode == "avg": # avg pooling
for _iy in range(roi_bin_grid_h):
for _ix in range(roi_bin_grid_w):
pc = pre_calc[pre_calc_index]
output_val += (
pc.w1
* bottom_data[offset_bottom_data + pc.pos1]
+ pc.w2
* bottom_data[offset_bottom_data + pc.pos2]
+ pc.w3
* bottom_data[offset_bottom_data + pc.pos3]
+ pc.w4
* bottom_data[offset_bottom_data + pc.pos4]
)
pre_calc_index += 1
output_val /= count
else: # max pooling
max_flag = False
for _iy in range(roi_bin_grid_h):
for _ix in range(roi_bin_grid_w):
pc = pre_calc[pre_calc_index]
val = max(
pc.w1
* bottom_data[offset_bottom_data + pc.pos1],
pc.w2
* bottom_data[offset_bottom_data + pc.pos2],
pc.w3
* bottom_data[offset_bottom_data + pc.pos3],
pc.w4
* bottom_data[offset_bottom_data + pc.pos4],
)
if not max_flag:
output_val = val
max_flag = True
else:
output_val = max(output_val, val)
pre_calc_index += 1
top_data[index] = output_val
def _run(
self,
X,
rois,
batch_indices,
coordinate_transformation_mode=None,
mode=None,
output_height=None,
output_width=None,
sampling_ratio=None,
spatial_scale=None,
):
coordinate_transformation_mode = (
coordinate_transformation_mode or self.coordinate_transformation_mode
)
mode = mode or self.mode
output_height = output_height or self.output_height
output_width = output_width or self.output_width
sampling_ratio = sampling_ratio or self.sampling_ratio
spatial_scale = spatial_scale or self.spatial_scale
num_channels = X.shape[1]
num_rois = batch_indices.shape[0]
num_roi_cols = rois.shape[1]
y_dims = (num_rois, num_channels, output_height, output_width)
Y = np.empty(y_dims, dtype=X.dtype).flatten()
self.roi_align_forward(
y_dims,
X.flatten(),
spatial_scale,
X.shape[2], # height, 3
X.shape[3], # width, 4
sampling_ratio,
rois.flatten(),
num_roi_cols,
Y,
mode.lower(),
coordinate_transformation_mode.lower() == "half_pixel",
batch_indices.flatten(),
)
return (Y.reshape(y_dims).astype(X.dtype),)