使用API接口进行推理应用开发
收藏回复举报
使用API接口进行推理应用开发
发表于2024-03-14 11:52:05
0 查看

本章节内容建立在已经完成安装SDK并正确运行的前提下,如还未完成以上步骤可参考:

https://www.hiascend.com/forum/thread-0258123493959172046-1-1.html

https://www.hiascend.com/forum/thread-0238119074346434022-1-1.html

本章节将使用一个样例讲解如何使用API接口进行快速的用例开发

模型同样使用首次运行中的YOLOV3,分别使用DVPP和opencv进行图像预处理处理并进行推理,后处理使用内置方法(如需使用自定义或开源方法使用nps对象即可)

import numpy as np
from mindx.sdk import base
from mindx.sdk.base import Tensor, Model, Size, log, ImageProcessor, post
import cv2
"""
本样例使用以下模型:
https://gitee.com/ascend/ModelZoo-TensorFlow/tree/master/ACL_TensorFlow/built-in/cv/YOLOv3_for_ACL/
其中ATC命令需添加输出节点指定:
--out_nodes="yolov3/yolov3_head/Conv_6/BiasAdd:0;yolov3/yolov3_head/Conv_14/BiasAdd:0;yolov3/yolov3_head/Conv_22/BiasAdd:0"
"""
device_id = 0  # 芯片ID
image_path = "./test.jpg"  # 输入图片

b_usedvpp = True  # 使用dvpp图像处理器时启用,使用opencv为False
b_useaipp = True   # ATC转换时使用--insert_op_conf参数为模型添加了AIPP时启用
yolo_resizelen = 416  # 模型输入大小,YOLOv3长宽均为416


def main():
    # ****0 初始化
    base.mx_init()  # 全局资源初始化
    imageTensorList = []

    # ****1 模型前处理
    if b_usedvpp:
        print("using ImageProcessor for preprocess.")
        # 创造图像处理器对象,使用该方法处理后数据在device侧
        imageProcessor0 = ImageProcessor(device_id)

        if b_useaipp:
            # 本分支为使用aipp的YOLOV3模型(ATC转换时使用--insert_op_conf参数),限定输入图像为YUV420SP
            model_path = "./model/yolov3_tf_bs1_fp16.om"
            yolov3 = Model(model_path, device_id)  # 创造模型对象

            decodedImg = imageProcessor0.decode(image_path, base.nv12) # HNWC
            size_cof = Size(yolo_resizelen, yolo_resizelen)
            resizeImg = imageProcessor0.resize(decodedImg, size_cof)

            # 推理需要转换为tensor的List(数据已在device侧无需转移)
            imageTensorList = [resizeImg.to_tensor()]
        else:
            # 本分支为未使用aipp的YOLOV3模型(输入同模型原始输入:BGR格式float32)
            model_path = "./model/yolov3_bs1.om"
            yolov3 = Model(model_path, device_id)  # 创造模型对象

            decodedImg = imageProcessor0.decode(image_path, base.bgr) # HNWC
            size_cof = Size(yolo_resizelen, yolo_resizelen)
            resizeImg = imageProcessor0.resize(decodedImg, size_cof)

            resizeImg.to_host()  # 需要在host侧才能自行处理数据
            image_resize = np.array(resizeImg.to_tensor())  # NHWC,取出为numpy数组

            img_ndarray = image_resize.astype(np.float32)/255  # int8->float32
            img_mxtensor = Tensor(img_ndarray) # 转换为Tensor对象
            img_mxtensor.to_device(device_id) # 推理前需部署到device侧
            # 推理需要转换为tensor的List
            imageTensorList = [img_mxtensor]

    else:
        print("using opencv for preprocess.")
        # 本分支为未使用aipp的YOLOV3模型(输入为BGR格式float32)
        model_path = "./model/yolov3_bs1.om"
        yolov3 = Model(model_path, device_id)  # 创造模型对象

        image_cv2 = cv2.imread(image_path)  # HWC
        image_nd_fp32 = image_cv2.astype(np.float32)/255  # int8->float32
        size_cof = (yolo_resizelen, yolo_resizelen)
        resizeImg = cv2.resize(image_nd_fp32, size_cof,
                               interpolation=cv2.INTER_LINEAR)
        np_image_addbatch = np.expand_dims(resizeImg, axis=0)  # NHWC

        imageTensor = Tensor(np_image_addbatch)  # 推理前需要转换为tensor,使用Tensor类来构建。
        imageTensor.to_device(device_id)  # !需要转移至device侧,该函数单独执行
        imageTensorList = [imageTensor]  # 构造tensor的List类型
        """
        !!!如使用了transpose,slice,append,reshape等改变数据内存形状的操作后,需要使用numpy.ascontiguousarray对内存进行重新排序成连续的
        如使用非图像数据,也是转为numpy.ndarray数据类型再进行Tensor转换,使用{tensor_data} = Tensor({numpy_data})方式
        外部文件读入的numpy输入(例如np.fromfile)需要reshpe为对应的shape
        for i in range(input.shape[0]):
            input_tensor = Tensor(inputs[i, :].reshape(1,-1)) # 每个batch的内容转换
            input_tensor.to_device(device_id)
            input_tensors.append(input_tensor)
        """

    # ****2 模型推理
    outputs = yolov3.infer(imageTensorList) 

    post_tensor_inputs = [] # tensor结果数组
    nps = [] # 原始numpy结果数组
    for i in range(len(outputs)):
        outputs[i].to_host()
        n = np.array(outputs[i])
        nps.append(n) # 使用自定义后处理时直接用此numpy数组即可!!!
        tensor = Tensor(n)  # 使用内置后处理类型时需要转换为Tenosr
        post_tensor_inputs.append(tensor)

    # ****3 SDK内置模型后处理/自行编写后处理时建议直接使用numpy结果数组
    config_path = "./model/yolov3_tf_bs1_fp16.cfg"  # 模型配置文件的路径
    label_path = "./model/yolov3.names"  # 分类标签文件的路径

    yolov3_post = post.Yolov3PostProcess(
        config_path=config_path, label_path=label_path)  # 构造对应的后处理对象

    resizeInfo = base.ResizedImageInfo()
    resizeInfo.heightResize = yolo_resizelen
    resizeInfo.widthResize = yolo_resizelen
    if b_usedvpp:
        resizeInfo.heightOriginal = decodedImg.original_height
        resizeInfo.widthOriginal = decodedImg.original_width
    else:
        resizeInfo.heightOriginal = image_cv2.shape[0]
        resizeInfo.widthOriginal = image_cv2.shape[1]

    results = yolov3_post.process(post_tensor_inputs, resizeInfo)
    """
    如果使用多batch进行后处理则需要concat连接tensor,且后处理输出要对应。此处为本样例的示例:
        inputs.append(base.batch_concat([tensor] * 2))
    results = yolov3_post.process(inputs, [resizeInfo] * 2)
    """

    # ****4 结果打印
    print("\nresults:")
    for i in range(len(results)):
        for j in range(len(results[i])):
            print("bbox:", results[i][j].x0, ",", results[i]
                  [j].y0, ",", results[i][j].x1, ",", results[i][j].y1)
            print("confidence:", results[i][j].confidence)
            print("classId:", results[i][j].classId)
            print("className:", results[i][j].className)
            print("******")
            
    base.mx_deinit()

try:
    main()
except Exception as e:
    print(e)

本帖最后由 匿名用户2025/04/01 18:35:16 编辑

我要发帖子