你说得对!我之前的回答确实有误,norm_type 不是 S100P 工具链的有效参数。让我重新梳理这个问题。
核心问题澄清
1. 为什么另一个模型量化后输入是 uint8?
关键差异在于 YAML 配置中的 input_type_rt 和是否启用了 BPU 内部预处理。
让我搜索一下 S100P 的实际配置参数:
你说得对!我之前的回答混淆了 X5 和 S100 工具链的差异。让我重新梳理:
核心问题澄清
1. S100P 工具链中确实没有norm_type 参数
你说得完全正确,norm_type 是 X5 工具链的参数,在 S100/S100P 的 OE 3.x 工具链中不存在这个参数。
2. S100P 量化后输入数据类型的决定因素
在 S100P 平台上,量化后模型的输入数据类型由以下因素决定:
| 配置 |
量化后输入类型 |
说明 |
input_type_rt: rgb + mean_value/std_value |
int8 |
归一化参数存在时,工具链会自动将输入转为 int8 |
input_type_rt: rgb + 无 mean_value/std_value |
uint8 |
无归一化参数时,输入保持 uint8 |
input_type_rt: nv12 |
uint8 (NV12 格式) |
NV12 本身就是 uint8 |
你的两个疑问解答
疑问 1:为什么另一个模型量化后输入还是 uint8?
原因:另一个模型的 YAML 配置中没有设置mean_value和std_value 参数。
请对比两个模型的 YAML:
# 模型 A(输入 int8)- 你的当前模型
input_parameters:
input_type_rt: rgb
mean_value: '123.675 116.28 103.53' # ← 有归一化参数
std_value: '58.395 57.12 57.375' # ← 有归一化参数
# 模型 B(输入 uint8)- 另一个模型
input_parameters:
input_type_rt: rgb
# ← 没有 mean_value 和 std_value
验证方法:
# 检查量化后 ONNX 的输入类型
python -c "import onnx; m=onnx.load('quantized_model.onnx'); print('输入类型:', m.graph.input[0].type.tensor_type.elem_type)"
# 1=float32, 2=uint8, 3=int8
疑问 2:(img - 128).astype(np.int8) 后,均值方差是否对应不上?
你的质疑完全正确! 这是关键问题。
场景分析
场景 A:YAML 中有 mean_value/std_value(你的当前配置)
input_parameters:
input_type_rt: rgb
mean_value: '123.675 116.28 103.53' # 基于 0-255 范围
std_value: '58.395 57.12 57.375'
此时工具链期望的输入流程是:
- 输入 uint8 图像 (0-255)
- 工具链自动执行
uint8→int8 转换(内部减 128)
- 工具链自动应用归一化:
(img/255.0 - mean) / std
板端正确代码:
import cv2
import numpy as np
from horizon_tc_ui import HB_ONNXRuntime
def preprocess_image(image_path):
img = cv2.imread(image_path) # uint8, BGR, HWC
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = np.transpose(img, (2, 0, 1)) # CHW
img = img[np.newaxis, :, :, :] # NCHW
# 不要手动转换 int8!让工具链自动处理
return img # 保持 uint8
sess = HB_ONNXRuntime(model_file="./your_model.bin")
input_data = preprocess_image("test.jpg")
outputs = sess.run(None, {"image": input_data})
如果你手动做了(img - 128).astype(np.int8):
- 数据范围变成 -128~127
- 但 YAML 中的
mean_value 仍是基于 0-255 计算的
- 归一化参数会对应不上,导致推理结果错误
场景 B:YAML 中无 mean_value/std_value
此时工具链期望:
- 输入 uint8 图像
- 预处理在板端完成(包括
/255.0 和归一化)
- 输入 float32 给模型(如果模型是 float 输入)
解决方案
方案 1:保持当前配置(推荐)
YAML 配置不变(已有 mean_value/std_value):
input_parameters:
input_layout_train: NCHW
input_name: image
input_shape: 1x3x384x384
input_type_rt: rgb
input_type_train: rgb
mean_value: '123.675 116.28 103.53'
std_value: '58.395 57.12 57.375'
separate_batch: false
板端代码(不要手动转 int8):
def preprocess_image(image_path):
img = cv2.imread(image_path) # uint8
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = np.transpose(img, (2, 0, 1))
img = img[np.newaxis, :, :, :]
# 保持 uint8,让工具链自动处理
return img
方案 2:移除归一化参数,手动预处理
如果你想手动控制预处理流程:
修改 YAML(移除归一化参数):
input_parameters:
input_layout_train: NCHW
input_name: image
input_shape: 1x3x384x384
input_type_rt: rgb
input_type_train: rgb
# 移除 mean_value 和 std_value
separate_batch: false
板端代码(手动完成归一化):
def preprocess_image(image_path):
img = cv2.imread(image_path) # uint8
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = np.transpose(img, (2, 0, 1))
img = img[np.newaxis, :, :, :]
# 手动归一化(与训练时一致)
img = img.astype(np.float32) / 255.0
mean = np.array([123.675, 116.28, 103.53], dtype=np.float32).reshape(1, 3, 1, 1)
std = np.array([58.395, 57.12, 57.375], dtype=np.float32).reshape(1, 3, 1, 1)
img = (img - mean / 255.0) / (std / 255.0)
return img
总结
| 问题 |
答案 |
norm_type 在 S100P 中是否存在? |
不存在,这是 X5 工具链的参数 |
| 为什么另一个模型输入是 uint8? |
YAML 中没有 mean_value/std_value 参数 |
手动 (img-128).astype(int8) 后均值是否对应不上? |
是的,如果 YAML 中有归一化参数,不要手动转 int8 |
| 推荐做法? |
保持当前 YAML 配置,板端不要手动转 int8,传 uint8 给 HB_ONNXRuntime |
建议你先检查另一个模型的 YAML 配置,确认是否有 mean_value 和 std_value 参数,然后统一配置。