开发者实战 | 自训练 YOLOv5 模型使用 OpenVINO™ 优化并部署在英特尔开发套件

点击蓝字

关注我们,让开发变得更有趣

作者:深圳技术大学 黎逸鹏(电子科学与技术2021级)

指导老师:张阳(英特尔边缘计算创新大使,深圳技术大学, 副教授)

86c4280487c5008a9e0e59ea9b90cdcb.png

1.1

简介

本文章将在《自训练Pytorch模型使用 OpenVINO™ 优化并部署在英特尔开发套件》文章的基础上进行扩展,将介绍如何使用 OpenVINO Python API 对 YOLOv5 模型进行优化以及部署,完成 YOLOv5 目标检测任务。

本文 Python 程序的开发环境是 Ubuntu20.04 LTS + PyCharm,硬件平台是英特尔开发套件爱克斯开发板 AIxBoard。

本文项目背景:针对 2023 第十一届全国大学生光电设计竞赛赛题 2 “迷宫寻宝”光电智能小车题目。基于该赛项宝藏样式,我通过深度学习训练出能分类四种不同颜色不同标记形状骨牌的模型,骨牌样式详见图 1.1。

bfd94534ee7edf3dd8533431b7db1c85.png

图1.1  四种骨牌类型

1.2

YOLOv5 以及目标检测

YOLO (You Only Look Once) 是目标检测模型,目标检测是计算机视觉中一种重要的任务,目的是在一张图片中找出特定的物体,同时要求识别物体的种类和位置。在此之前的文章中 Pytorch 模型是用于图像分类,只要求识别画面中物体的种类。具体的区别通过图 1.2.1 直观可知。

8858c8505cb45c1e381bff321db53d95.png

图 1.2.1  图像分类、目标定位、目标检测

01

通过 labelImg 对图像进行数据集构建

Labelimg 是一款数据标注软件,支持输出包括 yolo, PascalVOC 等格式标注数据,这里我们选择 yolo 格式即可。

在环境中执行:

pip install labelimg -i https://mirror.baidu.com/pypi/simple

向右滑动查看完整代码

而后打开 labelimg 软件,如图 1.2.2

519e2ced922ed10871e24c0064302fe3.png

图 1.2.2  labelImg 软件界面

如图所示,选择好图片数据目录 (Open Dir) 和数据标注保存目录 (Choose Save Dir),就可以对想要的物体进行人工的数据标注。

02

标注好后检查保存目录中的 label 文件,查看是否无误,如图 1.2.3

ba038bc9202a503cfcbb45408eaef370.png

图 1.2.3  标注好的文件

03

本次实验共标注 2000 张图片(单分类 500 张共 4 分类)具体训练流程在 YOLOv5 Github 有较为详细的教程,在此不作为重点讲解。得到 YOLOv5 模型后通过 OpenVINO™ Model Optimization 转化成 IR 模型,这样无论从处理速度还是精度都能获得一定程度的优化。

1.3

使用 OpenVINO™ Runtime 对 YOLOv5 模型进行推理

在这一章节里我们将在 Pycharm 中使用 OpenVINO™ Runtime 对我们训练的 YOLOv5 模型进行优化推理。

整个推理流程大致可以分为:

推理核心初始化 → 对输入图进行预处理 → 输入到推理引擎获得结果 → 通过置信度/NMS(非极大值抑制)过滤得到结果 → 将结果通过 OpenCV API 进行可视化

1.3.1

导入功能包

import openvino.runtime as ov
import cv2
import numpy as np
import openvino.preprocess as op

本次我们导入四个功能包,分别是 OpenVINO™ Runtime & PreProcess 、Numpy 、OpenCV。与之前不同在于我们需要使用 OpenVINO™ 自带的预处理 API 对我们的模型进行一个预先处理,使得模型能够正常工作在 OpenVINO™ 的推理引擎下。

PreProcess API 介绍:

OpenVINO™ PreProcess 是 OpenVINO™ Python API 大家庭的一员,主要是提供了一个 OpenVINO™ Runtime 原生用于数据预处理的 API 函数库,在不用 PreProcess 时,开发者需要用第三方库例如 OpenCV 来对其进行预处理,但是 OpenCV 作为一个开源的、广泛的功能库,数据预处理只能加载到 CPU 去进行实现,这无疑是增加对 CPU 资源的开销,并且之后需要将处理后数据再次返还到 iGPU 等计算设备进行推理。而 PreProcess 提供了一种方式,使得预处理也能直接集成到模型执行图中去,整个模型工作流程都在 iGPU 上流转,这样无需依赖 CPU,能提高执行效率。

由于输入数据的不同,我们需要预处理来将数据能够正确的进行处理。例如改变精度、改变输入颜色通道、输入数据的 Layout 等等。

整体 PreProcess 的流程大概是:

创建 PPP(PrePostProcess) 对象 → 声明输入数据信息 → 指定 Layout →设置输出张量信息 → 从 PPP 对象中构建 Model 并进行推理

可以明显得知,PreProcess 的存在使得预处理变得非常简单易懂,只需要在在转换前查看模型的输入输出信息,再比对自己环境下的输入数据,进行预处理改变即可。而且整个环境都可以在 iGPU 等计算设备上运行,减轻了 CPU 负担,可以把更多宝贵的资源留在处理其他重要事情上。

1.3.2

模型载入

将模型进行载入:

def Init():
    global core
    global model
    global compiled_model
global infer_request
#核心创建
core = ov.Core() 
#读取用YOLOv5模型转换而来的IR模型
model = core.read_model("best2.xml", "best2.bin") 
#运用PPP(PrePostProcessor)对模型进行预处理
Premodel = op.PrePostProcessor(model)
Premodel.input().tensor().set_element_type(ov.Type.u8).set_layout(ov.Layout("NHWC")).set_color_format(op.ColorFormat.BGR)
Premodel.input().preprocess().convert_element_type(ov.Type.f32).convert_color(op.ColorFormat.RGB).scale(
        [255., 255., 255.])
    Premodel.input().model().set_layout(ov.Layout("NCHW"))
    Premodel.output(0).tensor().set_element_type(ov.Type.f32)
    model = Premodel.build()
    compiled_model = core.compile_model(model, "CPU") #加载模型,可用CPU or GPU
    infer_request = compiled_model.create_infer_request() #生成推理

向右滑动查看完整代码

1.3.3

图像尺寸调整

由于输入图的尺寸不确定性,在此我们特意加入一个 Resize 环节,用来适应不同分辨率的图像,但是若输入图像尺寸较为稳定,只需要求出其变换图的长宽比例即可。

def resizeimg(image, new_shape):
old_size = image.shape[:2]
#记录新形状和原生图像矩形形状的比率
    ratio = float(new_shape[-1] / max(old_size)) 
    new_size = tuple([int(x * ratio) for x in old_size])
    image = cv2.resize(image, (new_size[1], new_size[0]))
    delta_w = new_shape[1] - new_size[1]
    delta_h = new_shape[0] - new_size[0]
color = [100, 100, 100]
new_im = cv2.copyMakeBorder(image, 0, delta_h, 0, delta_w, cv2.BORDER_CONSTANT, value=color)    #增广操作
    return new_im, delta_w, delta_h

向右滑动查看完整代码

1.3.4

推理过程以及结果展示

在上一节中我们把输入图像所要进行的预处理图像进行了一个定义,在这一小节则是 OpenVINO™ Runtime 推理程序的核心。

#************************************#
#               推理主程序             #
def main(img,infer_request):
    push =[]
    img_re,dw,dh = resizeimg(img,(640,640)) #尺寸处理
    input_tensor = np.expand_dims(img_re, 0) #获得输入张量
    infer_request.infer({0: input_tensor}) #输入到推理引擎
    output = infer_request.get_output_tensor(0) #获得推理结果
    detections = output.data[0] #获得检测数据
    boxes = []
    class_ids = []
    confidences = []
    for prediction in detections:
        confidence = prediction[4].item() #获取置信度
        if confidence >= 0.6: #初步过滤,过滤掉绝大多数的无效数据
            classes_scores = prediction[5:]
            _, _, _, max_indx = cv2.minMaxLoc(classes_scores)
            class_id = max_indx[1]
            if (classes_scores[class_id] > .25):
                confidences.append(confidence)
                class_ids.append(class_id)
                x, y, w, h = prediction[0].item(), prediction[1].item(), prediction[2].item(), prediction[3].item() #获取有效信息
                xmin = x - (w / 2) #由于NMSBoxes缘故,需要从中心点得到左上角点
                ymin = y - (h / 2)
                box = np.array([xmin, ymin, w, h]) #记录数据
                boxes.append(box)
    indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.5) #NMS筛选
    detections = []
    for i in indexes:
        j = i.item()
        detections.append({"class_index": class_ids[j], "confidence": confidences[j], "box": boxes[j]}) #储存获取的目标名称和框选位
    for detection in detections:
        box = detection["box"]
        classId = detection["class_index"]
        confidence = detection["confidence"]
if(confidence<0.88): #再次过滤
            continue
        else :
            push.append(classId)
        rx = img.shape[1] / (img_re.shape[1] - dw)
        ry = img.shape[0] / (img_re.shape[0] - dh)
        img_re = cv2.rectangle(img_re, (int(box[0]), int(box[1])), (int(box[0] + box[2]), int(box[1] + box[3])), (0, 255, 0), 3)
        box[0] = rx * box[0] #恢复原尺寸box,如果尺寸不变可以忽略
        box[1] = box[1] *ry
        box[2] = rx * box[2]
        box[3] = box[3] *ry
        xmax = box[0] + box[2]
        ymax = box[1] + box[3]
        img = cv2.rectangle(img, (int(box[0]), int(box[1])), (int(xmax), int(ymax)), (0, 255, 0), 3) #绘制物体框
        img = cv2.rectangle(img, (int(box[0]), int(box[1]) - 20), (int(xmax), int(box[1])), (0, 255, 0), cv2.FILLED) #绘制目标名称底色填充矩形
        img = cv2.putText(img, str(label[classId])+'  '+str(int(confidence*100))+'%', (int(box[0]), int(box[1]) - 5), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0))  #绘制目标名称
    cv2.imshow("d", img_re)
    cv2.imshow('w',img)
    cv2.waitKey(0)

向右滑动查看完整代码

以上推理函数编写已经完成。以下是运行主程序:

#********************主程序***********************#
def MainToSolve(infer):
    img = cv2.imread("boundtest.jpg")  #如果需要实时,只需要将输入img变成从摄像机抓取的帧画面
main(img,infer)


#从这里开始,初始化以及推理
Init()
MainToSolve(infer_request)

向右滑动查看完整代码

当我们运行该程序时,会得到如图 1.3.1。

e2ab2ae1f70f9aa3c0317115b1ebfb80.png

图 1.3.1  图像结果

如图所示,YOLOv5 模型通过转换成IR模型,再经过 PPP 预处理以及 Runtime 引擎,成功运行在 AlxBoard。整体上性能非常不错。

1.4

模型应用场景简述:

原先的 Pytorch 模型只完成了图像分类的任务,本文通过 YOLOv5 训练并运用 OpenVINO™ 技术来完成了目标检测这一更高难度的任务,通过得到物块的位置我们就能更好的给予小车底盘信息,用来精确对物块进行任务(抓取或是推到)

搭载 AlxBoard 的四轮小车如图 1.4.1。

c703e25f55b1342ae923641f98f3fc2d.png

图 1.4.1  AlxBoard 智能小车

通过此小车,我们还能发挥想象去做更多的应用场景,通过 OpenVINO™ 赋能小车系统,我们还能实现例如空对地无图导航等等更具有特色的应用场景。

1.5

结论

自训练 YOLOv5 模型在通过 OpenVINO™ Model Optimizer  模型优化后用 OpenVINO™ PreProcess 先进行预处理,处理后用 OpenVINO™ Runtime 进行推理,推理过程简单清晰。推理整个过程由于加入了 PPP(PrePostProcess) 的预处理技术,整个处理可以放在 iGPU 上运行,有效减少 CPU 的开销。通过 OpenVINO™ 技术优化后的模型优势明显,加上 AlxBoard 开发者板,能让我们迅速构建起智能小车来验证系统。

OpenVINO™ 简单易上手,提供了健全的文档和 OpenVINO™ Notebooks 范例,帮助开发者专注在自身应用的实现和算法搭建。

OpenVINO™

--END--

你也许想了解(点击蓝字查看)⬇️➡️ 基于 ChatGLM2 和 OpenVINO™ 打造中文聊天助手➡️ 基于 Llama2 和 OpenVINO™ 打造聊天机器人➡️ OpenVINO™ DevCon 2023重磅回归!英特尔以创新产品激发开发者无限潜能➡️ 5周年更新 | OpenVINO™  2023.0,让AI部署和加速更容易➡️ OpenVINO™5周年重头戏!2023.0版本持续升级AI部署和加速性能➡️ OpenVINO™2023.0实战 | 在 LabVIEW 中部署 YOLOv8 目标检测模型➡️ 开发者实战系列资源包来啦!➡️ 以AI作画,祝她节日快乐;简单三步,OpenVINO™ 助你轻松体验AIGC
➡️ 还不知道如何用OpenVINO™作画?点击了解教程。➡️ 几行代码轻松实现对于PaddleOCR的实时推理,快来get!➡️ 使用OpenVINO 在“端—边—云”快速实现高性能人工智能推理
扫描下方二维码立即体验 
OpenVINO™ 工具套件 2023.0

点击 阅读原文 立即体验OpenVINO 2023.0

2c5fb763bf13c41b26688ee58505cc78.png

文章这么精彩,你有没有“在看”?

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
YOLOv5是一种流行的目标检测算法,而OpenVINO 2022是一款用于深度学习模型部署和加速推理的工具包。结合使用YOLOv5OpenVINO 2022可以实现高效的目标检测应用部署使用OpenVINO 2022部署YOLOv5的推理有以下步骤: 1. 安装OpenVINO 2022:首先需要下载和安装OpenVINO 2022工具包。安装完成后,配置OpenVINO的环境变量等设置。 2. 模型转换:YOLOv5的原始模型使用PyTorch训练的,为了能够在OpenVINO中进行推理,需要将模型转换为OpenVINO支持的IR(Intermediate Representation)格式。可以使用OpenVINO提供的Model Optimizer工具来完成模型转换,具体命令如下: ```bash mo.py --input_model <path_to_yolov5_model> --model_name yolov5 -o <output_dir> --data_type FP16 ``` 这里的`<path_to_yolov5_model>`是原始YOLOv5模型的路径,`<output_dir>`是转换后的IR模型的输出目录,`--data_type`指定了推理过程中使用的数据精度,可以根据需求选择FP16或FP32。 3. 推理应用开发:根据使用场景和需求,使用OpenVINO提供的API开发推理应用程序。可以使用C++、Python等主流编程语言进行开发OpenVINO提供了相应的API接口供开发者使用开发过程中需要加载转换后的模型文件,并进行图像的预处理、推理计算等操作。 4. 编译和优化使用OpenVINO提供的Model Optimizer工具,可以对推理应用进行编译和优化,以提高推理性能。具体命令如下: ```bash mo.py --input_model <model_xml> --model_name yolov5 --output_dir <output_dir> --data_type FP16 --batch 1 ``` 这里的`<model_xml>`是前面转换得到的IR模型的路径,`<output_dir>`是优化后的模型文件的输出目录,`--batch`指定了模型的批处理大小,可以根据需求进行调整。 5. 部署和推理:在部署和推理阶段,可以将优化后的模型开发的应用程序部署到目标设备上,并进行推理计算。OpenVINO提供了适用于多种硬件平台的推理引擎,可以选择合适的推理引擎来进行部署。 综上所述,使用OpenVINO 2022部署YOLOv5的推理需要进行模型转换、推理应用开发、编译和优化等步骤。通过结合YOLOv5OpenVINO 2022,可以实现高效的目标检测应用部署和推理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值