ONNX 模型仓库 Faster R-CNN R-50-FPN 实战指南:预处理、推理、后处理与 INT8 量化
【免费下载链接】modelsA collection of pre-trained, state-of-the-art models in the ONNX format项目地址: https://gitcode.com/gh_mirrors/model/models
Faster R-CNN R-50-FPN 是 ONNX 模型仓库中经过精度验证的目标检测模型,可实时检测 80 个常见物体类别(完整类别清单见 coco_classes.txt)。本指南以 validated/vision/object_detection_segmentation/faster-rcnn/README.md 为核心,结合仓库内实际的 ONNX 模型文件与 ONNX_HUB_MANIFEST.json 中的元数据,完整讲解从输入预处理、ONNX Runtime 推理、输出后处理到 INT8 量化的端到端实战流程。读完本文,你将掌握如何基于仓库提供的四种版本模型(fp32 / int8 / QDQ)完成一次可复现的目标检测推理,并理解其精度与性能权衡。
模型概览与仓库定位
Faster R-CNN 于 2015 年提出(论文题目:Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks,发表于 NIPS 2015),通过引入区域建议网络(Region Proposal Network, RPN)将候选区域生成与检测网络统一在同一框架内,实现了近实时的目标检测。本仓库提供的版本以 ResNet-50 为骨干网络、FPN(Feature Pyramid Network)为特征金字塔结构,由 facebookresearch/maskrcnn-benchmark 转换而来,输入为任意尺寸图像,输出 80 个 COCO 类别(外加 1 个背景类,类别文件共 81 行,首行为__background)的检测框、类别与置信度。
仓库在validated/vision/object_detection_segmentation/faster-rcnn/model/目录下提供了四种模型文件,每个模型均同时提供纯模型(.onnx)和附带示例测试数据的压缩包(.tar.gz),下载对照表如下(数据来自原文档):
| 模型 | 下载 | 下载(含示例测试数据) | ONNX 版本 | Opset 版本 | 精度 |
|---|---|---|---|---|---|
| Faster R-CNN R-50-FPN | 167.3 MB | 158.0 MB | 1.5 | 10 | mAP 0.35 |
| Faster R-CNN R-50-FPN-fp32 | 168.5 MB | 156.2 MB | 1.9 | 12 | mAP 0.3437 |
| Faster R-CNN R-50-FPN-int8 | 42.6 MB | 36.2 MB | 1.9 | 12 | mAP 0.3409 |
| Faster R-CNN R-50-FPN-qdq | 43 MB | 29 MB | 1.9 | 12 | mAP 0.3390 |
与 fp32 版 FasterRCNN-12 相比,int8 版 FasterRCNN-12 的 mAP 下降幅度为 0.81%,性能提升为 1.43 倍。
注意:性能数据依赖于测试硬件。
此处的性能数据采集环境为 Intel® Xeon® Platinum 8280 处理器,每实例 1 个插槽 4 核,CentOS Linux 8.3,数据批次大小为 1。
上述模型的输入输出端口、文件校验信息(model_sha)与字节大小可在 ONNX_HUB_MANIFEST.json 中逐一核对,例如 Faster R-CNN R-50-FPN 的model_bytes为 167330019(约 167.3 MB),与文档表格一致;四个模型的io_ports均声明了相同的输入输出结构,可据此在接入推理引擎前预先校验图结构。
推理流程总览
一个完整的推理链路包含四个环节:预处理(Preprocessing)→ 模型推理(Inference)→ 输出解析(Outputs)→ 后处理可视化(Postprocessing)。仓库文档分别给出了预处理与后处理的完整参考代码,下文逐一展开。
输入到模型
模型的唯一输入名为image(见 Manifest 中的io_ports声明),形状为:
(3 x 'height' x 'width')即通道优先(CHW)布局的浮点张量,三个通道依次为 B、G、R(见下方预处理步骤)。height与width为动态维度,模型可以接受不同尺寸的图像输入。
预处理步骤
原始图像需要经过以下转换才能送入模型:
- 加载到 [0, 255] 数值范围(即不进行 0-1 归一化缩放);
- 按比例缩放(Resize):以短边为基准缩放到 800,保持长宽比;
- 转换到 BGR 通道顺序;
- 减去均值归一化,均值向量为
[102.9801, 115.9465, 122.7717]; - 零填充(Pad),使高度和宽度都能被 32 整除。
文档特别指出:模型可以接受不同尺寸的图像,但为了获得最佳性能,建议将图像缩放到高度与宽度都处于[800, 1333]范围内,再用零填充使两个维度都能被 32 整除。
以下代码展示了如何对 demo.jpg 进行预处理(来自原文档,可直接运行):
import numpy as np from PIL import Image def preprocess(image): # Resize ratio = 800.0 / min(image.size[0], image.size[1]) image = image.resize((int(ratio * image.size[0]), int(ratio * image.size[1])), Image.BILINEAR) # Convert to BGR image = np.array(image)[:, :, [2, 1, 0]].astype('float32') # HWC -> CHW image = np.transpose(image, [2, 0, 1]) # Normalize mean_vec = np.array([102.9801, 115.9465, 122.7717]) for i in range(image.shape[0]): image[i, :, :] = image[i, :, :] - mean_vec[i] # Pad to be divisible of 32 import math padded_h = int(math.ceil(image.shape[1] / 32) * 32) padded_w = int(math.ceil(image.shape[2] / 32) * 32) padded_image = np.zeros((3, padded_h, padded_w), dtype=np.float32) padded_image[:, :image.shape[1], :image.shape[2]] = image image = padded_image return image img = Image.open('dependencies/demo.jpg') img_data = preprocess(img)要点解读:
ratio = 800.0 / min(...)实现“短边对齐 800”的缩放策略;由于演示图为 640×480(短边 480),缩放后尺寸约为 1067×800。- 均值减法是逐通道进行的,且不做除以标准差(std)的操作,这与 ImageNet 分类模型中常用的
(x / 255 - mean) / std预处理不同,务必按此实现,否则检测精度会受影响。 - 填充值固定为 0,填充发生在均值减法之后(即填充区域不参与减去均值),代码中的实现顺序已保证这一点。
- 文档建议将预处理放在推理前的数据管线上完成("The transformation should preferably happen at preprocessing"),不要在模型图内部进行,以保证模型输入与文档约定一致。
输出到模型
模型共有3 个输出(对应 Manifest 中名为6379、6381、6383的三个输出端口):
| 输出 | 形状 | 含义 |
|---|---|---|
| boxes | (nbox x 4) | 检测框坐标,格式为(xmin, ymin, xmax, ymax),float 类型 |
| labels | (nbox) | 每个检测框的类别索引,int64 类型(索引从 0 开始,对应类别文件中的__background之后的行,即 1 对应person) |
| scores | (nbox) | 每个检测框的置信度分数,float 类型 |
nbox为本次推理实际输出的检测框数量,是动态的,取决于输入图像内容与模型内部的非极大值抑制(NMS)结果。
后处理步骤
模型输出的坐标是基于预处理后的填充图像坐标系的,因此展示前需要按缩放比例ratio还原回原始图像尺寸。文档给出的后处理与可视化代码如下:
import matplotlib.pyplot as plt import matplotlib.patches as patches classes = [line.rstrip('\n') for line in open('coco_classes.txt')] def display_objdetect_image(image, boxes, labels, scores, score_threshold=0.7): # Resize boxes ratio = 800.0 / min(image.size[0], image.size[1]) boxes /= ratio _, ax = plt.subplots(1, figsize=(12,9)) image = np.array(image) ax.imshow(image) # Showing boxes with score > 0.7 for box, label, score in zip(boxes, labels, scores): if score > score_threshold: rect = patches.Rectangle((box[0], box[1]), box[2] - box[0], box[3] - box[1], linewidth=1, edgecolor='b', facecolor='none') ax.annotate(classes[label] + ':' + str(np.round(score, 2)), (box[0], box[1]), color='w', fontsize=12) ax.add_patch(rect) plt.show() display_objdetect_image(img, boxes, labels, scores)其中类别标签文件从 coco_classes.txt 读取,共 81 行:首行为__background,其余 80 行依次为person、bicycle、car、motorcycle等 COCO 常见类别(至toothbrush结束)。由于labels输出是类别索引,直接以classes[label]索引即可得到可读的类别名。
在实际工程中,还可以在score > score_threshold的基础上叠加类别过滤、IoU 去重等策略;score_threshold=0.7是文档演示使用的默认阈值,可根据场景在 0.3~0.9 之间调整。
推理调用骨架
完成预处理后,即可借助 ONNX Runtime 等推理引擎加载模型(仓库中的.onnx文件可直接作为InferenceSession的输入)。以下是与本模型 I/O 结构对应的最小推理代码示意:
import onnxruntime as ort sess = ort.InferenceSession('model/FasterRCNN-12.onnx') # 输入名 'image'、输出名 '6379'/'6381'/'6383' 均可由 sess.get_inputs()/get_outputs() 获取 boxes, labels, scores = sess.run(None, {'image': img_data})注意:原文档的预处理代码将img_data直接作为模型输入,若在脚本中运行,需要额外将其转换为(1, 3, H, W)的批维度并传入 ONNX Runtime。仓库 README 首页还提示,INT8 系列模型由 Intel® Neural Compressor 生成,可在 CPU 推理场景下显著降低模型体积并提升吞吐。
数据集与精度验证
- 来源:原始预训练 Faster R-CNN 模型来自 facebookresearch/maskrcnn-benchmark(Massa, Francisco 与 Girshick, Ross 维护的 PyTorch 实例分割与目标检测参考实现)。
- 评测数据集:与 Detectron 一致,在 COCO 的
coco_2014_minival上计算 mAP,该子集与coco_2017_val完全等价。 - 验证精度:评测指标为 COCO box mAP(对 IoU 0.5:0.95 取平均),在 2017 COCO val 数据上计算,mAP 为 0.353。
该精度与模型表中的 mAP 数值(0.35 / 0.3437 / 0.3409 / 0.3390)相互印证,说明各版本在精度上保持了较好的一致性。
INT8 / QDQ 量化:从 fp32 到更小更快
量化背景
Faster R-CNN R-50-FPN-int8与Faster R-CNN R-50-FPN-qdq均由 fp32 版FasterRCNN-12.onnx量化得到,量化工具为 Intel® Neural Compressor(onnxruntime 后端)。从模型文件体积可见量化收益显著:fp32 版约 168.5 MB,int8 版约 42.6 MB(缩小约 4 倍),且精度损失控制在极小范围(mAP 由 0.3437 降至 0.3409)。
其中-int8与-qdq的区别在于 ONNX 中量化表示的两种方式:int8 为算子级量化表示,QDQ(Quantize-Dequantize)为张量级量化表示,即在模型中显式插入 QuantizeLinear/DequantizeLinear 节点,兼容更多运行时(如 ONNX Runtime 的 CPU/GPU EP)的量化执行路径。
量化环境
原文档给出的复现环境如下:
- onnx: 1.9.0
- onnxruntime: 1.8.0
准备模型
wget https://github.com/onnx/models/raw/main/vision/object_detection_segmentation/faster-rcnn/model/FasterRCNN-12.onnx(也可直接使用仓库内已提供的 FasterRCNN-12.onnx 文件,无需重复下载。)
执行量化
量化通过 Intel® Neural Compressor 提供的调优脚本完成,命令格式如下:
bash run_tuning.sh --input_model=path/to/model \ # model path as *.onnx --config=faster_rcnn.yaml \ --data_path=path/to/COCO2017 \ --output_model=path/to/save参数说明:
| 参数 | 含义 |
|---|---|
--input_model | 待量化的 fp32 模型路径,格式为*.onnx |
--config | 量化配置文件,示例为faster_rcnn.yaml(定义量化方式、校准策略、精度目标等) |
--data_path | 校准用数据集路径,示例为COCO2017(用于后训练量化 PTQ 的校准数据) |
--output_model | 量化后模型的保存路径 |
Intel® Neural Compressor 支持自动的精度驱动调优策略,可帮助用户快速找到精度与性能均衡的最佳量化模型;量化属于后训练量化(PTQ)流程,用户也可以在其示例目录中找到针对 ONNX 模型仓库该模型的完整量化示例说明。
出处、贡献与许可
- 论文出处:Shaoqing Ren, Kaiming He, Ross Girshick, and Jian Sun.Faster R-CNN: Towards Real-Time Object Detection with Region Proposal Networks. Conference on Neural Information Processing Systems (NIPS), 2015.
- 参考实现:本模型由 maskrcnn-benchmark(含 onnx 导出分支)转换而来,转换过程中做了一定的修改。
- 贡献者:mengniwang95、yuwenzho、airMeng、ftian1、hshen14(均来自 Intel)。
- 许可证:MIT License(模型目录文档声明)。
实战要点小结
- 预处理顺序不可调换:缩放 → BGR → CHW → 减均值 → 补零,均值
[102.9801, 115.9465, 122.7717]是模型训练时的统计量,务必按文档原样实现; - 输入尺寸策略:短边对齐 800、长边不超过 1333,并补零到 32 的倍数,是精度与性能的推荐折中点;
- 输出坐标还原:boxes 坐标基于填充后的图像坐标系,展示前必须除以
ratio还原到原图; - 量化选型:对 CPU 部署有体积与吞吐要求的场景,优先选择
FasterRCNN-12-int8.onnx(约 42.6 MB,mAP 仅降 0.81%);对跨运行时兼容性要求高的场景,可选用 QDQ 版本; - 验证依据:所有模型文件、SHA、I/O 端口均可对照 ONNX_HUB_MANIFEST.json 与 model 目录 进行复核,确保接入生产环境前图结构与文档声明一致。
【免费下载链接】modelsA collection of pre-trained, state-of-the-art models in the ONNX format项目地址: https://gitcode.com/gh_mirrors/model/models
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考