【华为云-上云之路】【昇腾】【每天进步一点点】在Atlas 200 DK创建模型推理引擎,实现基于自己模型的部署

举报
Tianyi_Li 发表于 2020/05/30 09:48:51 2020/05/30
【摘要】 在Atlas 200 DK上开发,关键部分是模型的转换和对推理结果的后处理,做好了这两步,开发就成功了一大半,剩下的基本就是优化设计了。而模型转换后在Atlas 200 DK上需要自己创建模型推理引擎,完成数据的输入和推理结果的输出及解析。在这里,以行人检测的Demo为例,说一下自己对推理引擎创建的了解。如有不对的地方,还请在下面留言,批评指正。

前言

在Atlas 200 DK上开发部署自己的模型,我觉得最为关键部分是模型的转换和对推理结果的后处理,做好了这两步,开发就成功了一大半,剩下的基本就是优化设计了。而模型转换后在Atlas 200 DK上需要自己创建模型推理引擎,完成数据的输入和推理结果的输出及解析。在这里,以行人检测的Demo为例,说一下自己对推理引擎创建的了解

这里省略了如果模型转换失败,要进行修改的步骤,如果不幸遇到了这个问题,就要根据转换模型的报错,具体问题具体分析了,这里推荐一位大神发的关于模型转换遇到问题时解决办法的总结,该总结也被转发在了昇腾论坛里,推荐大家看看,绝对干货满满,特地奉上链接:https://bbs.huaweicloud.com/forum/thread-57916-1-1.html


行人检测Demo链接https://bbs.huaweicloud.com/blogs/170452


代码介绍

推理引擎的创建,模型是关键。首先,需要得到转换好的.om模型,这一步十分重要,因为模型的创建中可能需要根据模型做一些设置。来看代码来理解吧。这里使用的是行人检测Demo里行人检测推理部分的代码,代码比单纯的讲解更能帮助人理解实现过程,我在代码中加了注释,可以根据注释理解。

# -*- coding: utf-8 -*-
# !/usr/bin/python3
# 行人检测,基于开源数据集和ModelArts中YOLOv3_Resnet18算法
# 行人检测推理部分

# 引入ConstManager, 这是一个自行创建的.py文件,用来存放模型的路径
from ConstManager import *

# 引入ModelManager,这也是一个.py文件,用来做模型推理创建的模板,按照这个模板,可以轻松创建推理引擎
import ModelManager

# 引入hiai库,这是华为的一个库,用来将输入图片做向量化和推理,直接用就好
import hiai
from hiai.nn_tensor_lib import DataType

# numpy和cv2就不用说了吧,很著名的两个Python库
import numpy as np
import cv2

# 引入utils,这是自行创建的一个.py文件,这里用来对推理结果解析,输入模型推理结果,返回我们想要的类别,框
# 的坐标等,这样做个封装,方便使用和移植,会使整体代码较为简洁
import utils

# 引入Python库datetime,用来计算程序执行时间,这里没用的,是在测试的时候用的。
import datetime


'''
Yolo3_Resnet18模型, 输入H = 352, W = 640,图像输入必须处理成numpy格式
bj_threshold 置信度阈值,取值范围为0~1。推理的时候,如果预测框的置信度小于该值,那么就会过滤掉, 默认为0.3
nms_threshold NMS阈值,取值范围为0~1。默认为0.4
'''


# 创建Yolo3_Resnet18Inference类
class Yolo3_Resnet18Inference(object):
    def __init__(self):
        # 由用户指定推理引擎的所在Graph的id号
        self.graph_id = 1000
        self.model_engine_id = 100
        # 基于输入图片框坐标
        self.boxList = []
        # 置信度
        self.confList = []
        # 概率
        self.scoresList = []
        # 输入图片中行人部分
        self.personList = []
        # 实例化模型管理类
        self.model = ModelManager.ModelManager()
        self.width = 640
        self.height = 352
        # 描述推理模型以及初始化Graph
        self.graph = None
        self._getgraph()

    def __del__(self):
        self.graph.destroy()

    def _getgraph(self):
        # 描述推理模型
        inferenceModel = hiai.AIModelDescription('Yolo3_Resnet18', yolo3_resnet18_model_path)
        # 初始化Graph
        self.graph = self.model.CreateGraph(inferenceModel, self.graph_id, self.model_engine_id)
        if self.graph is None:
            print("Init Graph failed")

    '''
    1.定义输入Tensor的格式
    2.调用推理接口
    3.对一帧推理的正确结果保存到self.resultList中
    4.根据返回值True和False判断是否推理成功
    '''

    def Inference(self, input_image):
        if isinstance(input_image, np.ndarray) is None:
            return False

        # Image PreProcess
        resized_image_opencv = cv2.resize(input_image, (self.width, self.height))
        resized_image = resized_image_opencv
        inputImageTensor = hiai.NNTensor(resized_image)
        nntensorList = hiai.NNTensorList(inputImageTensor)

        # 调用推理接口
        resultList = self.model.Inference(self.graph, nntensorList)

        if resultList is not None:
            bboxes = utils.get_result(resultList, self.width, self.height)  # 获取检测结果
            # print("bboxes:", bboxes)

            # Yolov_resnet18 Inference
            output_image = utils.draw_boxes(resized_image, bboxes)       # 在图像上画框
            output_image = cv2.resize(output_image, (input_image.shape[1], input_image.shape[0]))
            img_name = datetime.datetime.now().strftime("%Y-%m-%d%H-%M-%S-%f")
            cv2.imwrite('output_image/' + str(img_name) + '.jpg', output_image)

        else:
            print('no person in this frame.')
            return False

        return True


# 程序执行的主要部分,调用前面定义的推理函数Inference完成推理和后处理
def dowork(src_img, yolo3_resnet18_app):

    res = yolo3_resnet18_app.Inference(src_img)
    if res is None:
        print("[ERROR] Please Check yolo3_resnet18_app.Inference!")
        return False
    else:
        print("[ERROR] Run Failed, dowork function failed.")
    return True


得益于ModelManager.py推理引擎创建模板的使用,我们可以很轻松创建一个推理引擎,而这个ModelManager.py这里并没有放出代码,可在本文开头的行人检测Demo的百度网盘链接中下载压缩包,解压后就能看到这个.py文件了。需要注意的是,如果要使用的话,需要在主函数先完成初始化工作,详情可参见Demo中的main.py,很简单的,就几行代码。


此外,模型创建需要指定Graph和engine的ID号,即告诉处理器,你具体想用的Engine,这里使用的graph_id = 1000, model_engine_id =100: 



注意这里的graph_id应该是从1000开始,可以到1003吧,即可选为1000,1001,1002,1003,我试过到1003应该是没问题的,1004可能也可以。model_engine_id是从100开始,可以向后延伸,应该到104都可以吧,不过不建议使用这么多,ID号到103就可以了。


还有一点,不同ID的Graph中的Engine的ID互不干扰,可以相同。简单来说,Graph像是一个国家,而Engine是国家的国民,不同ID的Graph是不同的国家,那么他们国民的名字,也就是ID号即使重复也没什么关系。


那么问题来了,如果我想使用多个模型推理怎么办呢?很简单,有两种方法:

  1. 创建一个Graph,在里面创建多个Engine,用于模型推理。

  2. 创建多个Graph,在每个Graph里面创建一个Engine,用于模型推理。

   个人建议,一个Graph里面不要创建太多用于推理的Engine,两个就差不多了,如果要用的模型较多,可以在创建一个Graph。


最后,说说Graph和Engine的关系吧。对于一个简单的单模型项目,一个Graph和一个模型推理Engine就足够了,比如这个Demo就是一个Graph和一个模型推理的Engine,也即是说一个Graph对应一个项目,但如果项目使用多个模型,比如4个模型,那我觉得创建两个Graph比较好,每个Graph里创建两个Engine,那么上面的代码就变成了四份,每份对应一个Engine。这里要注意下数据的传递,好像不同Graph之间数据传递比较慢,可根据具体的代码去调整Engine。


以上是我个人在使用Python实现Demo时,自己的一点感悟,可能有不对的地方,还请批评指正,博客中写的不完善或看不懂的地方,可以在下面评论或私信我哈,我看到会回复的。有时间,欢迎大家到昇腾论坛发帖提问或交流,一起打造昇腾良好的社区生态。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。