[{"data":1,"prerenderedAt":246},["ShallowReactive",2],{"content-query-rQ4VZKBpMF":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"cover":11,"type":12,"category":13,"body":14,"_type":240,"_id":241,"_source":242,"_file":243,"_stem":244,"_extension":245},"/technology-blogs/zh/3214","zh",false,"","基于MindSpore案例的香橙派开发板离线推理实践——图片分类","功能：通过ResNet50实现图片分类。 样例输入：原始图片。 样例输出：图片分类的结果","2024-06-29","https://obs-mindspore-file.obs.cn-north-4.myhuaweicloud.com/file/2024/07/12/cee2d800e0644314b87c77f31243edb3.png","technology-blogs","调试调优",{"type":15,"children":16,"toc":224},"root",[17,25,31,37,42,47,52,62,67,102,107,115,122,130,136,144,150,158,164,172,178,183,191,196,201,206],{"type":18,"tag":19,"props":20,"children":22},"element","h1",{"id":21},"基于mindspore案例的香橙派开发板离线推理实践图片分类",[23],{"type":24,"value":8},"text",{"type":18,"tag":26,"props":27,"children":29},"h2",{"id":28},"样例介绍",[30],{"type":24,"value":28},{"type":18,"tag":32,"props":33,"children":34},"p",{},[35],{"type":24,"value":36},"功能：通过ResNet50实现图片分类。 样例输入：原始图片。 样例输出：图片分类的结果。",{"type":18,"tag":26,"props":38,"children":40},{"id":39},"前期准备",[41],{"type":24,"value":39},{"type":18,"tag":32,"props":43,"children":44},{},[45],{"type":24,"value":46},"基础镜像的样例目录中已包含转换后的om模型以及测试图片。",{"type":18,"tag":32,"props":48,"children":49},{},[50],{"type":24,"value":51},"利用atc工具将原始模型转换为om模型。转换命令如下：",{"type":18,"tag":53,"props":54,"children":56},"pre",{"code":55},"atc --framework=1 --model=./resnet50.air --input_format=NCHW --output=resnet50 --log=error --soc_version=Ascend310B4\n",[57],{"type":18,"tag":58,"props":59,"children":60},"code",{"__ignoreMap":7},[61],{"type":24,"value":55},{"type":18,"tag":32,"props":63,"children":64},{},[65],{"type":24,"value":66},"其中各个参数具体含义如下：",{"type":18,"tag":68,"props":69,"children":70},"ul",{},[71,77,82,87,92,97],{"type":18,"tag":72,"props":73,"children":74},"li",{},[75],{"type":24,"value":76},"--framework：原始框架类型, 0: Caffe, 1: MindSpore, 3: TensorFlow, 5: ONNX。",{"type":18,"tag":72,"props":78,"children":79},{},[80],{"type":24,"value":81},"--model：原始air模型文件。",{"type":18,"tag":72,"props":83,"children":84},{},[85],{"type":24,"value":86},"--input_format：输入Tensor的内存排列方式。",{"type":18,"tag":72,"props":88,"children":89},{},[90],{"type":24,"value":91},"--output：输出的模型文件路径。",{"type":18,"tag":72,"props":93,"children":94},{},[95],{"type":24,"value":96},"--log：打印的日志级别。error表示只输出error类别的信息。",{"type":18,"tag":72,"props":98,"children":99},{},[100],{"type":24,"value":101},"--soc_version：昇腾AI处理器型号。",{"type":18,"tag":26,"props":103,"children":105},{"id":104},"模型推理实现",[106],{"type":24,"value":104},{"type":18,"tag":68,"props":108,"children":109},{},[110],{"type":18,"tag":72,"props":111,"children":112},{},[113],{"type":24,"value":114},"注意：本案例在离线推理的过程中可能会出现内存不足的问题，可以根据情况查看FAQ文档中的解决方案。",{"type":18,"tag":116,"props":117,"children":119},"h3",{"id":118},"_1-导入三方库",[120],{"type":24,"value":121},"1. 导入三方库",{"type":18,"tag":53,"props":123,"children":125},{"code":124},"import numpy as np\nimport cv2\nimport matplotlib.pyplot as plt\n\nimport acl\nimport acllite_utils as utils\nimport constants as const\nfrom acllite_imageproc import AclLiteImageProc\nfrom acllite_model import AclLiteModel\nfrom acllite_resource import resource_list\n\nimport mindspore as ms\nimport mindspore.dataset as ds\nfrom mindspore.dataset import vision\n",[126],{"type":18,"tag":58,"props":127,"children":128},{"__ignoreMap":7},[129],{"type":24,"value":124},{"type":18,"tag":26,"props":131,"children":133},{"id":132},"_2-定义acllite资源初始化与去初始化类",[134],{"type":24,"value":135},"2. 定义acllite资源初始化与去初始化类",{"type":18,"tag":53,"props":137,"children":139},{"code":138},"class AclLiteResource:\n    \"\"\"\n    AclLiteResource\n    \"\"\"\n    def __init__(self, device_id=0):\n        self.device_id = device_id\n        self.context = None\n        self.stream = None\n        self.run_mode = None\n        \n    def init(self):\n        \"\"\"\n        init resource\n        \"\"\"\n        print(\"init resource stage:\")\n        ret = acl.init()\n\n        ret = acl.rt.set_device(self.device_id)\n        utils.check_ret(\"acl.rt.set_device\", ret)\n\n        self.context, ret = acl.rt.create_context(self.device_id)\n        utils.check_ret(\"acl.rt.create_context\", ret)\n\n        self.stream, ret = acl.rt.create_stream()\n        utils.check_ret(\"acl.rt.create_stream\", ret)\n\n        self.run_mode, ret = acl.rt.get_run_mode()\n        utils.check_ret(\"acl.rt.get_run_mode\", ret)\n\n        print(\"Init resource success\")\n\n    def __del__(self):\n        print(\"acl resource release all resource\")\n        resource_list.destroy()\n        if self.stream:\n            print(\"acl resource release stream\")\n            acl.rt.destroy_stream(self.stream)\n\n        if self.context:\n            print(\"acl resource release context\")\n            acl.rt.destroy_context(self.context)\n\n        print(\"Reset acl device \", self.device_id)\n        acl.rt.reset_device(self.device_id)\n        print(\"Release acl resource success\")\n",[140],{"type":18,"tag":58,"props":141,"children":142},{"__ignoreMap":7},[143],{"type":24,"value":138},{"type":18,"tag":116,"props":145,"children":147},{"id":146},"_3-定义resnet50类包含前处理推理等操作",[148],{"type":24,"value":149},"3. 定义Resnet50类，包含前处理、推理等操作",{"type":18,"tag":53,"props":151,"children":153},{"code":152},"class Resnet50(object):\n    \"\"\"\n    class for Resnet50\n    \"\"\"\n    def __init__(self, model_path, model_width, model_height):\n        self._model_path = model_path\n        self._model_width = model_width\n        self._model_height = model_height\n        self.device_id = 0\n        self._dvpp = None\n        self._model = None\n\n    def init(self):\n        \"\"\"\n        Initialize\n        \"\"\"\n        # 初始化dvpp\n        self._dvpp = AclLiteImageProc()\n\n        # 加载模型\n        self._model = AclLiteModel(self._model_path)\n        return const.SUCCESS\n    \n    @utils.display_time\n    # 定义数据预处理函数\n    def pre_process(self, input_path):\n        # 利用Cifar10Dataset接口读取测试数据\n        dataset_predict = ds.Cifar10Dataset(dataset_dir=input_path, shuffle=False)\n        # 对数据进行预处理操作：调整数据尺寸、归一化、标准化、调整通道顺序。\n        image_test = [\n            vision.Resize((32, 32)),\n            vision.Rescale(1.0 / 255.0, 0.0),\n            vision.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),\n            vision.HWC2CHW()\n                ]\n        dataset_predict = dataset_predict.map(image_test, 'image')\n        # 设置推理数据的batch\n        dataset_predict = dataset_predict.batch(4)\n\n        return dataset_predict\n    \n    @utils.display_time\n    def inference(self, input_path, dataset_predict1):\n        \"\"\"\n        model inference\n        \"\"\"\n        # 迭代读取数据\n        resized_image = next(dataset_predict1.create_dict_iterator())\n        images = resized_image[\"image\"]\n        labels = resized_image[\"label\"]\n        print(\"resized_image['label']: \", resized_image['label'])\n        result1 = ms.Tensor(resized_image['image'])\n        # 对数据进行推理\n        preds = self._model.execute([result1.asnumpy(), ])\n        \n        return images, labels, preds\n",[154],{"type":18,"tag":58,"props":155,"children":156},{"__ignoreMap":7},[157],{"type":24,"value":152},{"type":18,"tag":116,"props":159,"children":161},{"id":160},"_4-构造主函数串联整个代码逻辑",[162],{"type":24,"value":163},"4. 构造主函数，串联整个代码逻辑",{"type":18,"tag":53,"props":165,"children":167},{"code":166},"from download import download\n\n# 获取数据集\ndataset_url = \"https://mindspore-courses.obs.cn-north-4.myhuaweicloud.com/orange-pi-mindspore/03-ResNet50/cifar-10-batches-bin.zip\"\ndownload(dataset_url, \"./datasets-cifar10-bin\", kind=\"zip\", replace=True)\n\n# 获取模型om文件\nmodel_url = \"https://mindspore-courses.obs.cn-north-4.myhuaweicloud.com/orange-pi-mindspore/03-ResNet50/resnet50.zip\"\ndownload(model_url, \"./model\", kind=\"zip\", replace=True)\n\ndef main():\n\n    # 给定模型路径和输入模型的图片尺寸\n    MODEL_PATH = \"./model/resnet50.om\"\n    MODEL_WIDTH = 32\n    MODEL_HEIGHT = 32\n    # 初始化acl资源\n    acl_resource = AclLiteResource() \n    acl_resource.init()\n    \n    # 初始化 Resnet50 类\n    resnet50 = Resnet50(MODEL_PATH, MODEL_WIDTH, MODEL_HEIGHT)  # 构造模型对象\n    \n    # 初始化模型类变量\n    ret = resnet50.init()  \n    utils.check_ret(\"Resnet50.init \", ret)  \n    # 给定推理数据的路径\n    input_path = \"./datasets-cifar10-bin/cifar-10-batches-bin\"\n\n    print('===================')\n    # 调用数据预处理函数，对数据进行预处理\n    crop_and_paste_image = resnet50.pre_process(input_path)\n    \n    print(\"crop_and_paste_image: \", crop_and_paste_image)\n    # 进行推理\n    images, labels, result = resnet50.inference(input_path, crop_and_paste_image)\n    pred = np.argmax(result[0], axis=1)\n    print(\"pred: \", pred)\n    \n    classes = []\n\n    with open(input_path + \"/batches.meta.txt\", \"r\") as f:\n        for line in f:\n            line = line.rstrip()\n            if line:\n                classes.append(line)\n\n    # 显示图像及图像的预测值\n    plt.figure()\n    for i in range(4):\n        plt.subplot(2, 2, i + 1)\n        # 若预测正确，显示为蓝色；若预测错误，显示为红色\n        color = 'blue' if pred[i] == labels.asnumpy()[i] else 'red'\n        plt.title('predict:{}'.format(classes[pred[i]]), color=color)\n        picture_show = np.transpose(images.asnumpy()[i], (1, 2, 0))\n        mean = np.array([0.4914, 0.4822, 0.4465])\n        std = np.array([0.2023, 0.1994, 0.2010])\n        picture_show = std * picture_show + mean\n        picture_show = np.clip(picture_show, 0, 1)\n        plt.imshow(picture_show)\n        plt.axis('off')\n\n    plt.show()\n",[168],{"type":18,"tag":58,"props":169,"children":170},{"__ignoreMap":7},[171],{"type":24,"value":166},{"type":18,"tag":116,"props":173,"children":175},{"id":174},"_5-运行",[176],{"type":24,"value":177},"5. 运行",{"type":18,"tag":32,"props":179,"children":180},{},[181],{"type":24,"value":182},"运行完成后，会显示推理后的图片，如下所示。",{"type":18,"tag":53,"props":184,"children":186},{"code":185},"main()\n",[187],{"type":18,"tag":58,"props":188,"children":189},{"__ignoreMap":7},[190],{"type":24,"value":185},{"type":18,"tag":26,"props":192,"children":194},{"id":193},"样例总结",[195],{"type":24,"value":193},{"type":18,"tag":32,"props":197,"children":198},{},[199],{"type":24,"value":200},"我们来回顾一下以上代码，可以包括以下几个步骤：",{"type":18,"tag":32,"props":202,"children":203},{},[204],{"type":24,"value":205},"初始化acl资源：在调用acl相关资源时，必须先初始化AscendCL，否则可能会导致后续系统内部资源初始化出错。",{"type":18,"tag":68,"props":207,"children":208},{},[209,214,219],{"type":18,"tag":72,"props":210,"children":211},{},[212],{"type":24,"value":213},"推理：利用AclLiteModel.execute接口对图片进行推理。",{"type":18,"tag":72,"props":215,"children":216},{},[217],{"type":24,"value":218},"对推理结果进行后处理：包括两个步骤，即转换像素值值域以及将图片缩放到原图大小。",{"type":18,"tag":72,"props":220,"children":221},{},[222],{"type":24,"value":223},"可视化图片：利用plt将结果画出。",{"title":7,"searchDepth":225,"depth":225,"links":226},4,[227,229,230,234,239],{"id":28,"depth":228,"text":28},2,{"id":39,"depth":228,"text":39},{"id":104,"depth":228,"text":104,"children":231},[232],{"id":118,"depth":233,"text":121},3,{"id":132,"depth":228,"text":135,"children":235},[236,237,238],{"id":146,"depth":233,"text":149},{"id":160,"depth":233,"text":163},{"id":174,"depth":233,"text":177},{"id":193,"depth":228,"text":193},"markdown","content:technology-blogs:zh:3214.md","content","technology-blogs/zh/3214.md","technology-blogs/zh/3214","md",1776506127336]