Tensorflow模型部署到昇腾310虚拟平台进行推理运算

Tensorflow模型部署到昇腾310虚拟平台进行推理运算

Tensorflow代码准备与任务分析

由于华为应用案例中有不少例子了,咱们今天做一个不一样的。
前几天课程作业需要做一个车牌识别的项目,今天我们就把它部署到华为昇腾310平台上推理一下试试吧
因为懒惰,我直接从github上找了一个车牌识别的项目网址。效果非常好。
训练步骤大致分为分割车牌-车牌矫正-识别字符,具体细节就不说了,可以自己看一下代码。
推理阶段大致分为四部分

  1. 利用分割网络分割出车牌mask
  2. 车牌矫正(需要用C++重写)
  3. 将矫正后的车牌输入CNN网络进行字符识别
  4. 最后在图片上打印识别车牌结果(原程序做了个界面,我就直接用C++实现自己的功能了)

环境配置

我使用的是华为的云平台,具体环境是有视频讲解的,我就不赘述了

模型转换

程序是Tensorflow训练的,并且是用Keras输出的模型,就是两个.h5文件。保险起见,我们先把他们转换成.pb。

from tensorflow.keras.models import load_model
import tensorflow as tf
import os
from tensorflow.keras import backend as K

#转换函数
def h5_to_pb(h5_model,output_dir,model_name,out_prefix = "output_",log_tensorboard = True):
    if os.path.exists(output_dir) == False:
        os.mkdir(output_dir)
    out_nodes = []
    for i in range(len(h5_model.outputs)):
        out_nodes.append(out_prefix + str(i + 1))
        tf.identity(h5_model.output[i],out_prefix + str(i + 1))
    sess = K.get_session()
    from tensorflow.python.framework import graph_util,graph_io
    init_graph = sess.graph.as_graph_def()
    main_graph = graph_util.convert_variables_to_constants(sess,init_graph,out_nodes)
    graph_io.write_graph(main_graph,output_dir,name = model_name,as_text = False)
    if log_tensorboard:
        from tensorflow.python.tools import import_pb_to_tensorboard
        import_pb_to_tensorboard.import_to_tensorboard(os.path.join(output_dir,model_name),output_dir)

if __name__ == "__main__":
    # 路径参数
    weight_file_path = "./cnn.h5"
    #输出路径
    output_dir = "./"
    #加载模型
    h5_model = load_model(weight_file_path)
    h5_to_pb(h5_model,output_dir = output_dir,model_name = "cnn.pb")
    print('model saved')

转换以后得到两个.pb文件,分别为 unet.pb 和 cnn.pb,分别对应着分割网络与字符识别网络。

将两个.pb文件上传到云平台,进行模型转换,输出两个.om文件,使第三方框架的模型可以在昇腾平台跑通。
废话不多说,直接上代码
在模型所在的文件夹中,命令行执行:

atc --model="./unet.pb" --framework=3 --output="unet" --soc_version=Ascend310 --input_format=NHWC --input_shape="input_1:1,512,512,3"
atc --model="./cnn.pb" --framework=3 --output="cnn" --soc_version=Ascend310 --input_format=NHWC --input_shape="input_1:1,80,240,3"

我们来仔细看一下这些参数

–model:输入模型的路径
–framework:第三方框架的代号,比如Caffe是0,mindspore是1,tensorflow是3,ONNX是5
–soc_version:处理器的版本,可以是Ascend310或者Ascend910,根据自己的硬件填写
–input_format:当原始框架是TensorFlow时,支持NCHW、NHWC、ND、NCDHW、NDHWC五种输入格式,默认为NHWC。
–input_shape:模型输入的shape信息,例如:“input_name1:n1,c1,h1,w1;input_name2:n2,c2,h2,w2”。指定的节点必须放在双引号中,节点中间使用英文分号分隔。input_name必须是转换前的网络模型中的节点名称。节点名称可以使用可视化工具netron来看,我自己是使用在线工具:
Netron

在这里插入图片描述
最后得到两个模型文件:unet.om,cnn.om

推理代码适配

华为有很多sample,给个链接
我们随便挑一个拉下来修改
华为工程师已经帮我们写好框架了哈哈,不嫖白不嫖,给黑白图片上色

先看一下代码结构:
在这里插入图片描述
├App名称
├── model //该目录下存放模型转换相关的配置文件
│ ├── xxx.cfg

├── data
│ ├── xxx.jpg //测试数据

├── inc //该目录下存放声明函数的头文件
│ ├── xxx.h

├── out //该目录下存放输出结果

├── src //该目录下存放系统初始化的配置文件、编译脚本、函数的实现文件
│ ├── xxx.json //系统初始化的配置文件
│ ├── CMakeLists.txt //编译脚本
│ ├── xxx.cpp //实现文件

我们来模仿着写一个。
首先确定.h文件,构建推理类 Class PlateRec,需要实现的功能及流程如下:

  1. 需要进行AscendCL的初始化: init()
  2. 申请运行管理资源:init_resources()
  3. 数据处理(车牌矫正与标记车牌):plate_correct(), plate_draw()
  4. 推理:inference()
  5. 运行资源释放,AscendCL去初始化:destroy_resource()
class PlateRec {
public:
    PlateRec(const char* modelPath, uint32_t modelWidth, uint32_t modelHeight);
    ~PlateRec();

    AtlasError init();
    AtlasError init_resource();
    AtlasError inference(std::vector<InferenceOutput>& inferOutputs);
    AtlasError plate_correct(const std::string& imageFile, std::vector<InferenceOutput>& modelOutput);
    AtlasError plate_draw(const std::string& imageFile, std::vector<InferenceOutput>& modelOutput);
    void destroy_resource();
};

这肯定是不够的
第二步没必要public,用init()来调用就可以了,第五步由析构函数调用就可以了
第二步中需要申请Device,Context,Stream。Device好理解,Context作为一个容器,管理了所有对象(包括Stream、Event、设备内存等)的生命周期。Stream用于维护一些异步操作的执行顺序,确保按照应用程序中的代码调用顺序在Device上执行。最后,获取当前昇腾AI软件栈的运行模式runMode_,根据不同的运行模式,后续的接口调用方式不同
第三步中也需要一些必要的参数
还要准备数据输入输出的数据结构
改过后的代码:

/**
* PlateRec
*/
class PlateRec {
public:
    PlateRec(const char* modelPath, uint32_t modelWidth, uint32_t modelHeight);
    ~PlateRec();

    AtlasError init();
    AtlasError inference(std::vector<InferenceOutput>& inferOutputs);
    AtlasError plate_correct(const std::string& imageFile, std::vector<InferenceOutput>& modelOutput);
    AtlasError plate_draw(const std::string& imageFile, std::vector<InferenceOutput>& modelOutput);
    
private:
    AtlasError init_resource();
    AtlasError create_input(size_t inputDataSize);
    void save_image(const std::string& origImageFile, cv::Mat& image);
    void destroy_resource();

private:
    int32_t deviceId_;
    aclrtContext context_;
    aclrtStream stream_;
    AtlasModel model_;

    const char* modelPath_;
    uint32_t modelWidth_;
    uint32_t modelHeight_;
    uint32_t inputDataSize_;
    void*    inputBuf_;
    aclrtRunMode runMode_;

    bool isInited_;
};

现在来实现:
构造与析构函数:

PlateRec::PlateRec(const char* modelPath, uint32_t modelWidth, uint32_t modelHeight)
:deviceId_(0), context_(nullptr), stream_(nullptr), inputBuf_(nullptr), 
modelWidth_(modelWidth), modelHeight_(modelHeight), isInited_(false){
    modelPath_ = modelPath;
}

PlateRec::~PlateRec() {
    destroy_resource();
}

申请运行资源时,我们隐式调用了Context和Stream。aclrtSetDevice()申请了三个资源

AtlasError PlateRec::init_resource() {
    // open device
    ret = aclrtSetDevice(deviceId_);
    if (ret != ACL_ERROR_NONE) {
        ATLAS_LOG_ERROR("Acl open device %d failed", deviceId_);
        return ATLAS_ERROR;
    }
    ATLAS_LOG_INFO("Open device %d success", deviceId_);

    ret = aclrtGetRunMode(&runMode_);
    if (ret != ACL_ERROR_NONE) {
        ATLAS_LOG_ERROR("acl get run mode failed");
        return ATLAS_ERROR;
    }

    return ATLAS_OK;
}


未完待续、、

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
华为升腾平台支持运行 YOLOv5 目标检测模型,以下是一个简单的 YOLOv5 案例代码示例: ```python import numpy as np from PIL import Image from atlasutil import ai from atlasutil import camera # 加载模型 model = ai.Model("yolov5s.om") # 打开摄像头 camera.open() while True: # 获取摄像头采集的图像 image = camera.capture() # 图像预处理 image = Image.fromarray(np.uint8(image)) image = image.resize((640, 640)) image_data = np.array(image) # 图像推理 output = model.infer([image_data]) # 解析推理结果 output = output[0] boxes, confidences, class_ids = output['boxes'], output['confidences'], output['class_ids'] # 在图像上绘制检测框 for i in range(len(boxes)): box = boxes[i] confidence = confidences[i] class_id = class_ids[i] if confidence > 0.5: x, y, w, h = box left, top, right, bottom = int(x - w / 2), int(y - h / 2), int(x + w / 2), int(y + h / 2) cv2.rectangle(image_data, (left, top), (right, bottom), (0, 255, 0), 2) cv2.putText(image_data, f"{class_id}", (left, top - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0, 255, 0), 2) # 显示图像 cv2.imshow('Object Detection', image_data) if cv2.waitKey(1) & 0xFF == ord('q'): break # 关闭摄像头 camera.close() ``` 这段代码使用华为升腾平台的 YOLOv5 模型进行实时目标检测,并在图像上绘制检测框和类别标签。请确保已安装好华为升腾平台的开发套件和相关依赖库,并参考华为开发者社区的文档进行模型部署推理

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值