OpenVINO是Open Visual Inference & Neural Network Optimization工具包的缩写,是一个用于优化和部署AI推理模型的综合工具包。OpenVINO支持CPU、GPU和NPU设备。
OpenVINO的优势:
(1).性能:OpenVINO利用英特尔CPU、集成和独立GPU以及FPGA的强大功能提供高性能推理。
(2).支持异构执行:OpenVINO提供一次编写(write once)并部署在任何受支持的英特尔硬件(CPU、GPU、FPGA、VPU等)上的API。
(3).模型优化器:OpenVINO提供模型优化器(Model Optimizer),可以导入、转换和优化(imports, converts, and optimizes)来自流行的深度学习框架(如PyTorch、TensorFlow、TensorFlow Lite、Keras、ONNX、PaddlePaddle和Caffe)的模型。
(4).易于使用:该工具包附带80多个教程(包括YOLOv8优化)讲授该工具包的不同方面。
OpenVINO导出结构:将模型导出为OpenVINO格式即IR(Intermediate Representation)格式时,会产生一个包含以下内容的目录(如目录名为best_openvino_model),你可以使用这些文件通过OpenVINO推理引擎进行推理
(1).XML文件:描述网络拓扑,如best.xml。
(2).BIN文件:包含权重和偏差(weights and biases)二进制数据,如best.bin。
(3).映射文件:保存原始模型输出张量到OpenVINO张量名称的映射,如metadata.yaml。
在部署中使用OpenVINO Export:
获得OpenVINO文件后,你可以使用OpenVINO Runtime运行模型。Runtime提供统一的API来在所有受支持的Intel硬件上进行推理。它还提供高级功能,例如跨 Intel硬件进行负载平衡和异步执行。
注:你需要XML和BIN文件以及任何特定于应用程序的设置(如输入大小、归一化的缩放因子等),才能正确设置和使用运行时模型。
在部署应用程序中,你通常会执行以下步骤:
(1).通过创建core = ov::Core()来初始化OpenVINO。
(2).使用core.read_model()方法加载模型。
(3).使用core.compile_model()函数编译模型。
(4).准备输入(图像、文本、音频等)。
(5).使用compiled_model(input_data)运行推理。
将英特尔的OpenVINO工具包与YOLOv8模型结合的好处:
性能:CPU推理速度提升高达3倍,并利用英特尔GPU和NPU实现加速。
模型优化器:转换、优化和执行来自PyTorch、TensorFlow和ONNX等流行框架的模型。
易于使用:有超过80个教程可供用户入门,包括YOLOv8。
异构执行:使用统一的API在各种英特尔硬件上部署模型。
注:以上文字描述主要来自:https://docs.ultralytics.com/integrations/openvino/
Windows10 Anaconda上配置OpenVINO环境:
(1).配置Ultralytics CUDA开发环境,执行以下命令:
# install cuda 11.8
# install cudnn v8.7.0: copy the contents of bin,include,lib/x64 cudnn directories to the corresponding CUDA directories
conda create --name ultralytics-env-cuda python=3.8 -y
conda activate ultralytics-env-cuda
conda install -c pytorch -c nvidia -c conda-forge pytorch==2.2.2 torchvision==0.17.2 torchaudio==2.2.2 pytorch-cuda=11.8 ultralytics # pytorch 2.2.2
git clone https://github.com/fengbingchun/NN_Test
cd NN_Test/demo/Python
(2).安装OpenVINO,执行以下命令:
conda install -c conda-forge openvino=2024.0.0
pip install nncf==2.8.0 # openvino INT8 need
注:具体版本要与已安装的libopenvino版本保持一致
生成OpenVINO模型的训练代码如下所示:
import argparse
import colorama
from ultralytics import YOLO
import torch
def parse_args():
parser = argparse.ArgumentParser(description="YOLOv8 train")
parser.add_argument("--yaml", required=True, type=str, help="yaml file")
parser.add_argument("--epochs", required=True, type=int, help="number of training")
parser.add_argument("--task", required=True, type=str, choices=["detect", "segment"], help="specify what kind of task")
args = parser.parse_args()
return args
def train(task, yaml, epochs):
if task == "detect":
model = YOLO("yolov8n.pt") # load a pretrained model
elif task == "segment":
model = YOLO("yolov8n-seg.pt") # load a pretrained model
else:
print(colorama.Fore.RED + "Error: unsupported task:", task)
raise
results = model.train(data=yaml, epochs=epochs, imgsz=640) # train the model
metrics = model.val() # It'll automatically evaluate the data you trained, no arguments needed, dataset and settings remembered
model.export(format="onnx", opset=12, simplify=True, dynamic=False, imgsz=640) # onnx, export the model, cannot specify dynamic=True, opencv does not support
model.export(format="torchscript", imgsz=640) # libtorch
model.export(format="engine", imgsz=640, dynamic=False, verbose=False, batch=1, workspace=2) # tensorrt fp32
# model.export(format="engine", imgsz=640, dynamic=True, verbose=True, batch=4, workspace=2, half=True) # tensorrt fp16
# model.export(format="engine", imgsz=640, dynamic=True, verbose=True, batch=4, workspace=2, int8=True, data=yaml) # tensorrt int8
# model.export(format="openvino", imgsz=640) # openvino fp32
# model.export(format="openvino", imgsz=640, half=True) # openvino fp16
model.export(format="openvino", imgsz=640, int8=True, data=yaml) # openvino int8, INT8 export requires 'data' arg for calibration
if __name__ == "__main__":
# python test_yolov8_train.py --yaml datasets/melon_new_detect/melon_new_detect.yaml --epochs 1000 --task detect
colorama.init()
args = parse_args()
if torch.cuda.is_available():
print("Runging on GPU")
else:
print("Runting on CPU")
train(args.task, args.yaml, args.epochs)
print(colorama.Fore.GREEN + "====== execution completed ======")
注:
(1).无论指定是FP32、还是PF16训练完生成的最终目录名都为best_openvino_model,这里手动调整文件名
(2).指定INT8,训练完生成的最终目录名为best_int8_openvino_model
在网上下载了200多幅包含西瓜和冬瓜的图像组成melon数据集,使用生成的best_int8_openvino_model进行预测,代码如下所示:
import colorama
import argparse
from ultralytics import YOLO
import os
import torch
import numpy as np
np.bool = np.bool_ # Fix Error: AttributeError: module 'numpy' has no attribute 'bool'. OR: downgrade numpy: pip unistall numpy; pip install numpy==1.23.1
def parse_args():
parser = argparse.ArgumentParser(description="YOLOv8 predict")
parser.add_argument("--model", required=True, type=str, help="model file")
parser.add_argument("--dir_images", required=True, type=str, help="directory of test images")
parser.add_argument("--dir_result", required=True, type=str, help="directory where the image results are saved")
args = parser.parse_args()
return args
def get_images(dir):
# supported image formats
img_formats = (".bmp", ".jpeg", ".jpg", ".png", ".webp")
images = []
for file in os.listdir(dir):
if os.path.isfile(os.path.join(dir, file)):
# print(file)
_, extension = os.path.splitext(file)
for format in img_formats:
if format == extension.lower():
images.append(file)
break
return images
def predict(model, dir_images, dir_result):
model = YOLO(model) # load an model
# model.info() # display model information # only *.pt format support
images = get_images(dir_images)
# print("images:", images)
os.makedirs(dir_result) #, exist_ok=True)
for image in images:
if torch.cuda.is_available():
results = model.predict(dir_images+"/"+image, verbose=True, device="cuda")
else:
results = model.predict(dir_images+"/"+image, verbose=True)
for result in results:
# print(result)
result.save(dir_result+"/"+image)
if __name__ == "__main__":
# python test_yolov8_predict.py --model runs/detect/train10/weights/best_int8.engine --dir_images datasets/melon_new_detect/images/test --dir_result result_detect_engine_int8
colorama.init()
args = parse_args()
if torch.cuda.is_available():
print("Runging on GPU")
else:
print("Runting on CPU")
predict(args.model, args.dir_images, args.dir_result)
print(colorama.Fore.GREEN + "====== execution completed ======")
执行结果如下图所示:
预测结果图像如下所示:
GitHub:https://github.com/fengbingchun/NN_Test