File size: 3,703 Bytes
3f1985b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | #!/usr/bin/env python3
"""
det02 β ONNX graph surgery to patch det_500m.onnx for dynamic batch.
Patches 3 things in the graph metadata:
1. Input dim[0]: 1 β symbolic 'batch'
2. Reshape shape constants starting with 1: that 1 β 0 (copy batch dim from input)
3. Output dim[0]: 1 β symbolic 'batch'
Saves the result, then prints declared output shapes and actual runtime shapes for N=1 and N=2.
"""
import argparse
import numpy as np
import onnx
from onnx import numpy_helper
import onnxruntime as ort
parser = argparse.ArgumentParser()
parser.add_argument('--model', required=True, help='Path to det_500m.onnx')
parser.add_argument('--out', required=True, help='Output path for patched model')
args = parser.parse_args()
model = onnx.load(args.model)
# ββ 1. Patch input batch dim ββββββββββββββββββββββββββββββββββββββββββββββββββ
for inp in model.graph.input:
d0 = inp.type.tensor_type.shape.dim[0]
d0.ClearField('dim_value')
d0.dim_param = 'batch'
print(f" Input '{inp.name}': batch dim β dynamic")
# ββ 2. Patch Reshape shape initializers that start with 1 ββββββββββββββββββββ
reshape_shape_names = set()
for node in model.graph.node:
if node.op_type == 'Reshape':
reshape_shape_names.add(node.input[1])
patched = 0
for init in list(model.graph.initializer):
if init.name not in reshape_shape_names:
continue
arr = numpy_helper.to_array(init).copy()
if arr.ndim == 1 and arr[0] == 1:
print(f" Reshape initializer '{init.name}': {arr} β ", end='')
arr[0] = 0
print(arr)
new_t = numpy_helper.from_array(arr, init.name)
model.graph.initializer.remove(init)
model.graph.initializer.append(new_t)
patched += 1
print(f' Patched {patched} Reshape shape constant(s)')
# ββ 3. Patch output batch dims ββββββββββββββββββββββββββββββββββββββββββββββββ
for out in model.graph.output:
d0 = out.type.tensor_type.shape.dim[0]
d0.ClearField('dim_value')
d0.dim_param = 'batch'
print(f" Output '{out.name}': batch dim β dynamic")
# ββ Save ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
onnx.checker.check_model(model)
onnx.save(model, args.out)
print(f'\nSaved: {args.out}')
# ββ Declared output shapes (from patched graph) βββββββββββββββββββββββββββββββ
print('\nDeclared output shapes after surgery:')
for out in model.graph.output:
shape = [d.dim_param if d.HasField('dim_param') else d.dim_value
for d in out.type.tensor_type.shape.dim]
print(f' {out.name}: {shape}')
# ββ Actual output shapes (from runtime with N=1 and N=2) βββββββββββββββββββββ
print('\nActual output shapes at runtime:')
session = ort.InferenceSession(args.out, providers=['CPUExecutionProvider'])
inp0 = session.get_inputs()[0]
out_names = [o.name for o in session.get_outputs()]
for N in (1, 2):
dummy = np.random.randint(0, 255, (N, 3, 640, 640)).astype(np.float32)
try:
outs = session.run(out_names, {inp0.name: dummy})
print(f' N={N}:')
for name, o in zip(out_names, outs):
print(f' {name}: {list(o.shape)}')
except Exception as e:
print(f' N={N}: FAILED β {e}')
|