保姆级教程 - atlas500部署yolov3-tiny检测实时视频流 [2] - yolov3-tiny模型转换到om模型

保姆级教程 - atlas500部署yolov3-tiny检测实时视频流 [2] - yolov3-tiny模型转换到om模型

接上文 ->

内网环境下docker部署atlas500 开发环境 [踩坑记录]

文章目录

      • 保姆级教程 - atlas500部署yolov3-tiny检测实时视频流 [2] - yolov3-tiny模型转换到om模型
        • 2、yolov3-tiny转换到om模型
          • (1)weight -> ckpt
          • (2)模型固化ckpt -> pb
            • - 确定yolov3和yolov3-tiny的输出节点
            • - 确定yolov3和yolov3-tiny的输入节点
          • (3)ATC 模型转换
          • (4)AIPP、DVPP预处理算子介绍

后续开发需要很多华为atlas官方的知识,版本迭代较快,我们应该以官方文档为主:https://support.huaweicloud.com/adevg-atlas500app/atlas500development_01_0001.html

还有对应cann版本的推理、训练文档:昇腾CANN社区版(5.0.4.alpha002)(训练)、昇腾CANN社区版(5.0.4.alpha002)(推理)
保姆级教程 - atlas500部署yolov3-tiny检测实时视频流 [2] - yolov3-tiny模型转换到om模型_第1张图片

2、yolov3-tiny转换到om模型

本文采用darknet原生的yolov3-tiny进行训练:https://pjreddie.com/darknet/ ,训练过程在此不再介绍

由于训练出的模型是weights,而atlas CANN目前对tensorflow、yolov3支持最好。(yolov5目前暂不支持使用) 详看模型支持列表:https://support.huaweicloud.com/ug-mfac-mindxsdk201/atlasmx_02_0129.html

而CANN的atc模型转换,也主要支持tf和caffe。本文采用weight -> ckpt ->pb -> atc转换为om模型的方案

(1)weight -> ckpt

从weight模型提取出ckpt权重。

借助项目: https://github.com/mystic123/tensorflow-yolo-v3

通过convert_weights.py提取ckpt权重,其中可指定yolov3 或 yolov3-tiny:

其中,本文使用tf1.15,通过浏览一些样例发现tf1.15应该是目前支持最好的

# -*- coding: utf-8 -*-
import tensorflow as tf
import yolo_v3
import yolo_v3_tiny
from utils import load_coco_names, load_weights

FLAGS = tf.app.flags.FLAGS

tf.app.flags.DEFINE_string(
    'class_names', './model/voc.names', 'File with class names')
tf.app.flags.DEFINE_string(
    'weights_file', './model/yolov3-tiny.weights', 'Binary file with detector weights')
tf.app.flags.DEFINE_string(
    'data_format', 'NHWC', 'Data format: NCHW (gpu only) / NHWC')
tf.app.flags.DEFINE_bool(
    'tiny', True, 'Use tiny version of YOLOv3')
tf.app.flags.DEFINE_bool(
    'spp', False, 'Use SPP version of YOLOv3')
tf.app.flags.DEFINE_string(
    'ckpt_file', './saved_model/yolov3-tiny.ckpt', 'Chceckpoint file')


def main(argv=None):
    if FLAGS.tiny:
        model = yolo_v3_tiny.yolo_v3_tiny
    elif FLAGS.spp:
        model = yolo_v3.yolo_v3_spp
    else:
        model = yolo_v3.yolo_v3

    classes = load_coco_names(FLAGS.class_names)

    # placeholder for detector inputs
    # any size > 320 will work here
    inputs = tf.placeholder(tf.float32, [1, 416, 416, 3])

    with tf.variable_scope('detector'):
        detections = model(inputs, len(classes),
                           data_format=FLAGS.data_format)
        load_ops = load_weights(tf.global_variables(
            scope='detector'), FLAGS.weights_file)

    saver = tf.train.Saver(tf.global_variables(scope='detector'))

    with tf.Session() as sess:
        sess.run(load_ops)

        save_path = saver.save(sess, save_path=FLAGS.ckpt_file)
        print('Model saved in path: {}'.format(save_path))


if __name__ == '__main__':
    tf.app.run()

提取出的ckpt文件如下:

checkpoint			# 文本文件,记录了保存的最新的checkpoint文件以及其它checkpoint文件列表
yolov3-tiny.ckpt.data-00000-of-00001	# 保存当前参数值
yolov3-tiny.ckpt.index		# 保存当前参数名
yolov3-tiny.ckpt.meta		# 保存当前图结构
(2)模型固化ckpt -> pb

模型固化和om模型转换最重要的是,确定模型的输入输出节点

模型固化流程可以参考对应版本的cann训练文档进行实现:https://support.huaweicloud.com/tfmigr-cann504alpha2training/atlasmprtg_13_9023.html

本文在仓库https://github.com/wizyoung/YOLOv3_TensorFlow的基础上,进行模型固化,代码参考如下:

import tensorflow as tf
from tensorflow.python.framework import graph_util
from tensorflow.python.platform import gfile

"""
    将ckpt权重解释:
    checkpoint:文本文件,记录了保存的最新的checkpoint文件以及其它checkpoint文件列表。
    model.ckpt.data-00000-of-00001:保存当前参数值
    model.ckpt.index:保存当前参数名
    model.ckpt.meta:保存当前图结构
"""
def freeze_graph(input_path, output_path):
    # 指定输出节点名称
    # output_node_names = "yolov3/yolov3_head/feature_map_1,yolov3/yolov3_head/feature_map_2,yolov3/yolov3_head/feature_map_3"
    output_node_names = 'yolov3-tiny/convolutional10/BiasAdd,yolov3-tiny/convolutional13/BiasAdd'
    saver = tf.train.import_meta_graph(input_path+".meta", clear_devices=True)  # 保存tf模型的计算图结构
    graph = tf.get_default_graph()
    input_graph_def = graph.as_graph_def()

    with tf.Session() as sess:
        saver.restore(sess, input_path)
        output_graph_def = graph_util.convert_variables_to_constants(
                           sess=sess,
                           input_graph_def=input_graph_def,   # = sess.graph_def,
                           output_node_names=output_node_names.split(","))

        with tf.gfile.GFile(output_path, 'wb') as fgraph:
            fgraph.write(output_graph_def.SerializeToString())

if __name__=="__main__":
    input_path = "./ckpt_convert_pro/yolov3-tiny.ckpt"
    output_path = "./pb_model/yolov3-tiny.pb"
    freeze_graph(input_path, output_path)

其中,重要的是指定ckpt权重的输出节点名称。可以通过tensorboard可视化ckpt权重,找到没有继续输出节点的终结点。

  • tensorboard可视化ckpt权重

    import tensorflow as tf
    from tensorflow.summary import FileWriter
     
    sess = tf.Session()
    ckpt_path= "./ckpt_convert_pro/yolov3-voc_50000.ckpt.meta"
    tf.train.import_meta_graph(ckpt_path)
    FileWriter("__tb_yolov3", sess.graph)     
    

    终端执行# tensorboard --logdir=./ --host=127.0.0.15

    显示,TensorBoard 1.15.0 at http://127.0.0.15:6006/ (Press CTRL+C to quit

就可以在http://127.0.0.15:6006/地址中可视化网络结构了。

- 确定yolov3和yolov3-tiny的输出节点

其中,yolov3的三个输出节点:yolov3/yolov3_head/feature_map_1,yolov3/yolov3_head/feature_map_2,yolov3/yolov3_head/feature_map_3

yolov3-tiny的两个输出节点:

yolov3-tiny/convolutional10/BiasAdd,yolov3-tiny/convolutional13/BiasAdd

- 确定yolov3和yolov3-tiny的输入节点
  • 转换后的pb模型可以用Netron查看网络结构,确定pb模型的输入节点。

    保姆级教程 - atlas500部署yolov3-tiny检测实时视频流 [2] - yolov3-tiny模型转换到om模型_第2张图片

例如本文yolov3的输入节点是:Placeholder:1,416,416,3 NHWC输入格式

确定模型的输入输出节点后,可以进行ATC模型转换。

(3)ATC 模型转换

昇腾张量编译器(Ascend Tensor Compiler,简称ATC)是昇腾CANN架构体系下的模型转换工具, 它可以将开源框架的网络模型或Ascend IR定义的单算子描述文件(json格式)转换为昇腾AI处理器支持的.om格式离线模型。

本文提供简单的模型转换流程,转换后的模型是否能正确推理,还要结合正确的前处理、后处理操作。

ATC模型转换可参考对应CANN版本的官方文档:https://support.huaweicloud.com/atctool-cann504alpha2infer/atlasatc_16_0001.html

由于atlas500只提供应用推理,上文提供的dockerfile文件中,并没有安装CANN-toolkit。本文是在atlas200DK,安装CANN-toolkit。首先输入atc命令,看环境是否安装:

(关于cann-toolkit环境搭建:https://support.huaweicloud.com/atctool-cann504alpha2infer/atlasatc_16_0004.html)

HwHiAiUser@davinci-mini:~$ atc
ATC start working now, please wait for a moment.
ATC run failed, Please check the detail log, Try 'atc --help' for more information
E10004: Value for [--model] is empty.
        [--framework] is required. Must be [0(Caffe) or 1(MindSpore) or 3(TensorFlow) or 5(Onnx)].

ATC模型转换命令:以yolov3为例,tiny模型相同:

atc --model="./yolov3_416_tf1.15.pb" --framework=3 --input_shape="Placeholder:1,416,416,3" --out_nodes="yolov3/yolov3_head/feature_map_1:0;yolov3/yolov3_head/feature_map_2:0;yolov3/yolov3_head/feature_map_3:0" --insert_op_conf=./yolov3_personcar_416_RGB888_U2BGR_0112.cfg --input_format=NHWC --output="./yolov3_416_tf1.15" --soc_version=Ascend310

–model:输入pb模型路径

–framework:原始框架类型

  • 0:Caffe
  • 1:MindSpore
  • 3:TensorFlow
  • 5:ONNX

–input_shape:指定输入节点的shape

–out_nodes: 指定输出节点

–insert_op_conf:插入算子的配置文件路径与文件名,例如aipp预处理算子。

–input_format:输入数据格式。

  • Caffe默认为NCHW;

  • TensorFlow默认为NHWC

–output:如果是开源框架的网络模型,存放转换后的离线模型的路径以及文件名(不带后缀)

–soc_version:模型转换时指定芯片版本。

(4)AIPP、DVPP预处理算子介绍

由于本文业务需求,需要达到视频流的实时目标检测。对整个前处理、芯片推理、后处理的流程速度要求很高,而atlas500主要作为AI推理端,host侧(Hi3559A cpu芯片)计算能力相对较弱。我们希望大部分前后处理操作都放到硬件端device侧运行,也就是借助acend310。所以我们需要了解Acend提供的硬件端的AIPP和DVPP操作:

  • 官方介绍

AIPP(Artificial Intelligence Pre-Processing)AI预处理,是昇腾AI处理器提供的硬件图像预处理模块

DVPP (数字视觉预处理模块) 作为昇腾AI软件栈中的编解码和图像转换模块,当来自系统内存和网络的视频或图像数据进入昇腾AI处理器的计算资源中运算之前,由于Davinci架构对输入数据有固定的格式要求,如果数据未满足架构规定的输入格式、分辨率等要求,就需要调用DVPP进行格式的转换,才可以进行后续的神经网络计算步骤。

按照我们理解,AIPP是作为预处理模块,对图像前处理的补充。而DVPP可以对视频进行硬件编解码、对图像进行格式转换。

  • 主要功能

AIPP:色域转换、图像归一化、抠图减均值/乘系数等功能

DVPP:视频解码(VDEC)模块、视频编码(VENC)模块、JPEG解码(JPEGD)模块、JPEG编码(JPEGE)模块、PNG解码(PNGD)模块和视觉预处理(VPC)模块。

  • 调用方式

AIPP需要在模型转换时,加载相应参数,AIPP的预处理操作在AI Core上,在模型推理阶段完成(真正输入模型进行推理之前)。

DVPP可以在应用开发的前处理阶段时,通过ACL架构提供的API接口开发。

因此,我们可以回顾yolov3模型部署的前后处理阶段,图像前处理,需要对不同输入尺度的图像resize以符合模型输入尺度。为了检测精度,多数采用等比例缩放 -> padding -> 归一化的操作。其中,等比例缩放、padding可以通过DVPP的VPC接口进行实现。归一化操作可以通过AIPP的减均值/乘系数实现。

同时,由于DVPP视频解码模块的输出为对齐后的YUV420SP类型,但正常我们的模型输入都是RGB,需要我们借助AIPP对输入图像进行色域转换,即,输入YUV420SP 2 RGB。

色域转换参考文档:https://support.huaweicloud.com/atctool-cann504alpha2infer/atlasatc_16_0023.html#section4。

需要理解,AIPP作为模型推理前的操作,文档中YUV420SP_U8转RGB,指的是AIPP算子需要输入 YUV420SP_U8的图像,即,前处理的输出、模型推理阶段的输入应该是YUV420SP_U8。

你可能感兴趣的