在《基于OpenVINOTM 2022.1实现YOLOv5推理程序》中详述了:
本文将介绍如何使用OpenVINOTM 2022.1的预处理API,进一步提升YOLOv5模型的推理计算性能
OpenVINO™ 2022.1之前版本不提供OpenVINOTM Runtime原生的用于数据预处理的API函数[1],如图1-1所示,开发者必须通过第三方库(例如:OpenCV)来实现数据预处理。
图1-1 OpenVINOTM Runtime预处理API
假设没有预处理API,那么输入数据的预处理操作只能放在CPU上实现,CPU完成数据预处理后,再将预处理后的数据传给iGPU、VPU等AI 加速计算设备进行推理计算。
有了预处理API后,就能将预处理操作集成到在模型执行图中,这样iGPU、VPU 或即将发布的Intel独立显卡都能进行数据预处理,无需依赖CPU,提高了执行效率,如图1-2所示。
图1-2 预处理OpenCV vs OpenVINO
由于输入数据的Shape、Precision等特征,与模型输入张量的要求不一致,所以需要通过预处理,将输入数据按照模型输入张量的要求进行转换,如图1-3所示。
图1-3 输入数据 vs模型输入张量
从图1-3中可见,数据预处理的典型操作有:
对应数据预处理的典型操作,OpenVINOTM预处理API提供了相应的类,方便开发者快速使用,其主要流程有6步[2],如图1-4所示,依次是:
图1-4 使用预处理API的流程
本文将按照上述顺序依次介绍。
实例化PrePostProcessor对象的Python代码,如代码清单1-1所示。
代码清单1-1 实例化PrePostProcessor对象
from openvino.runtime import Core, Type, Layout
from openvino.preprocess import PrePostProcessor, ColorFormat
# Please modify the model path
model_path = "yolov5s.onnx"
model = core.read_model(model_path)
# Step1: Instance PrePostProcessor object
ppp = PrePostProcessor(model)
申明输入数据的信息的Python代码,如代码清单1-2所示。
代码清单1-2 申明输入数据的信息
# Step2: Declare input data information:
ppp.input().tensor() \
.set_color_format(ColorFormat.BGR) \
.set_element_type(Type.u8) \
.set_layout(Layout('NHWC'))
指定模型的数据布局(layout) 的Python代码,如代码清单1-3所示。
代码清单1-3 指定模型的数据布局(layout)
# Step3: Specify actual model layout
ppp.input().model().set_layout(Layout('NCHW'))
设置模型输出张量的信息的Python代码,如代码清单1-4所示。
代码清单1-4 设置模型输出张量的信息
# Step4: Set output tensor information:
# - precision of tensor is supposed to be 'f32'
ppp.output().tensor().set_element_type(Type.f32)
定义预处理的具体步骤的Python代码,如代码清单1-5所示。
代码清单1-5 定义预处理的具体步骤
# Step5: Apply preprocessing modifing the original 'model'
# - Precision from u8 to f32
# - color plane from BGR to RGB
# - subtract mean
# - divide by scale factor
# - Layout conversion will be done automatically as last step
ppp.input().preprocess() \
.convert_element_type(Type.f32) \
.convert_color(ColorFormat.RGB) \
.mean([0.0, 0.0, 0.0]) \
.scale([255.0, 255.0, 255.0])
将预处理步骤集成到模型的Python代码,如代码清单1-6所示。
预处理方式 |
CPU/iGPU型号 |
推理设备 |
迭代次数 |
运行时间 |
OpenVINOTM预处理API |
i7-1165G7 Intel®Iris®Xe |
device=”GPU” |
500 |
12.68s |
OpenCV |
i7-1165G7 Intel®Iris®Xe |
device=”GPU” |
500 |
13.43s |
代码清单1-6 将预处理步骤集成到模型
# Step6: Integrate preprocessing steps into model
print(f'Build preprocessor: {ppp}')
model = ppp.build()
使用serialize()函数,可以将集成了预处理步骤的模型导出,方便后续调用,如代码清单1-7所示。
代码清单1-7 导出包含预处理步骤的模型
# Save the Model with preprocess
from openvino.offline_transformations import serialize
serialize(model, 'yolov5s.xml', 'yolov5s.bin')
使用Netron打开导出模型,可以看到预处理步骤已经集成到执行图中,如图1-5所示。
图1-5 预处理集成到执行图中
导出集成预处理模型的完整源代码:https://gitee.com/ppov-nuc/yolov5_infer/blob/main/preprocessing_with_saving_to_IR.py
本文随附使用OpenVINOTM 2022.1预处理API实现YOLOv5s推理程序的完整源代码,参见:infer_with_openvino_preprocess.py · PPOV_NUC/yolov5_infer - Gitee.com。
表1-1使用OpenVINOTM 2022.1预处理API和使用OpenCV实现预处理的性能对比
操作系统:Windows10;Python版本:3.8;OpenVINO版本:2022.1
模型:yolov5s.onnx
预处理方式 |
CPU/iGPU型号 |
推理设备 |
迭代次数 |
运行时间 |
OpenVINOTM预处理API |
i7-1165G7 Intel®Iris®Xe |
device=”GPU” |
500 |
12.68s |
OpenCV |
i7-1165G7 Intel®Iris®Xe |
device=”GPU” |
500 |
13.43s |
执行命令, 将yolov5s.onnx转换为FP16精度的yolov5s.xml后
mo --input_model yolov5s.onnx --data_type FP16
操作系统:Windows10;Python版本:3.8;OpenVINO版本:2022.1
模型:yolov5s.xml @ FP16
预处理方式 |
CPU/iGPU型号 |
推理设备 |
迭代次数 |
运行时间 |
OpenVINOTM预处理API |
i7-1165G7 Intel®Iris®Xe |
device=”GPU” |
500 |
7.41s |
OpenCV |
i7-1165G7 Intel®Iris®Xe |
device=”GPU” |
500 |
8.24s |
总结
本文完整介绍了什么是OpenVINO™ 预处理API和为什么推荐使用预处理API将预处理操作集成到模型执行图中,然后详细介绍了使用步骤并提供了完整范例源代码。
通过运行源代码,可以看到,使用了OpenVINO™预处理API,使输入数据预处理操作不再依赖CPU,可以由推理设备(如GPU/VPU)完成,提高了推理计算效率,减少了运行时间。
参考文献:
[1] openvino.preprocess — OpenVINO™ documentation
[2] Preprocessing API - details — OpenVINO™ documentation
[3] openvino_notebooks/002-openvino-api.ipynb at main · openvinotoolkit/openvino_notebooks · GitHub