0


[嵌入式AI从0开始到入土]12_yolov5在昇腾上应用

[嵌入式AI从0开始到入土]嵌入式AI系列教程

注:等我摸完鱼再把链接补上

可以关注我的B站号工具人呵呵的个人空间,后期会考虑出视频教程,务必催更,以防我变身鸽王。

第1期 昇腾Altas 200 DK上手
第2期 下载昇腾案例并运行
第3期 官方模型适配工具使用
第4期 炼丹炉的搭建(基于Ubuntu23.04 Desktop)
第5期 炼丹炉的搭建(基于wsl2_Ubuntu22.04)
第6期 Ubuntu远程桌面配置
第7期 下载yolo源码及样例运行验证
第8期 在线Gpu环境训练(基于启智ai协作平台)
第9期 转化为昇腾支持的om离线模型
第10期 jupyter lab的使用
第11期 yolov5在昇腾上推理
第12期 yolov5在昇腾上应用
未完待续…


文章目录


前言

注:本文基于Atlas 200 Dk编写,其他版本可能会有版本依赖问题

上一节中,我们已经完成了图片推理,但是仅仅图像的推理怎么够,起码得视频或者摄像头吧。因此我参考了案例,进行了修改。

一、获取案例

我扒了200i DK A2的案例下来(似乎官方没有给案例的下载地址),当然你也可以使用上一节的资源包,然后新建这个案例文件。
当然你可以使用我本文置顶的资源,都是我测试完成的。

1、获取系统镜像

下载地址:https://ascend-repo.obs.cn-east-2.myhuaweicloud.com/Atlas%20200I%20DK%20A2/DevKit/images/23.0.RC3/1.2.3/A200I-DK-A2_desktop-image_1.2.3_ubuntu22.04-aarch64.img.xz

2、获取案例

下载完后,解压,在Ubuntu中挂载

A200I-DK-A2_desktop-image_1.2.3_ubuntu22.04-aarch64.img

镜像文件,案例在

root_fs/home/HwHiAiUser/samples/notebooks

下。这次我们取第一个案例即可。
复制出来,上传到200DK。

3、原始案例

这里贴一份出来,毕竟镜像有一点点大。挂资源大概率过不了审核。

# 导入代码依赖import cv2
import numpy as np
import ipywidgets as widgets
from IPython.display import display
import torch
from skvideo.io import vreader, FFmpegWriter
import IPython.display
from ais_bench.infer.interface import InferSession

from det_utils import letterbox, scale_coords, nms

defpreprocess_image(image, cfg, bgr2rgb=True):"""图片预处理"""
    img, scale_ratio, pad_size = letterbox(image, new_shape=cfg['input_shape'])if bgr2rgb:
        img = img[:,:,::-1]
    img = img.transpose(2,0,1)# HWC2CHW
    img = np.ascontiguousarray(img, dtype=np.float32)return img, scale_ratio, pad_size

defdraw_bbox(bbox, img0, color, wt, names):"""在图片上画预测框"""
    det_result_str =''for idx, class_id inenumerate(bbox[:,5]):iffloat(bbox[idx][4]<float(0.05)):continue
        img0 = cv2.rectangle(img0,(int(bbox[idx][0]),int(bbox[idx][1])),(int(bbox[idx][2]),int(bbox[idx][3])),
                             color, wt)
        img0 = cv2.putText(img0,str(idx)+' '+ names[int(class_id)],(int(bbox[idx][0]),int(bbox[idx][1]+16)),
                           cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,255),1)
        img0 = cv2.putText(img0,'{:.4f}'.format(bbox[idx][4]),(int(bbox[idx][0]),int(bbox[idx][1]+32)),
                           cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,0,255),1)
        det_result_str +='{} {} {} {} {} {}\n'.format(
            names[bbox[idx][5]],str(bbox[idx][4]), bbox[idx][0], bbox[idx][1], bbox[idx][2], bbox[idx][3])return img0

defget_labels_from_txt(path):"""从txt文件获取图片标签"""
    labels_dict =dict()withopen(path)as f:for cat_id, label inenumerate(f.readlines()):
            labels_dict[cat_id]= label.strip()return labels_dict

defdraw_prediction(pred, image, labels):"""在图片上画出预测框并进行可视化展示"""
    imgbox = widgets.Image(format='jpg', height=720, width=1280)
    img_dw = draw_bbox(pred, image,(0,255,0),2, labels)
    imgbox.value = cv2.imencode('.jpg', img_dw)[1].tobytes()
    display(imgbox)definfer_image(img_path, model, class_names, cfg):"""图片推理"""# 图片载入
    image = cv2.imread(img_path)# 数据预处理
    img, scale_ratio, pad_size = preprocess_image(image, cfg)# 模型推理
    output = model.infer([img])[0]

    output = torch.tensor(output)# 非极大值抑制后处理
    boxout = nms(output, conf_thres=cfg["conf_thres"], iou_thres=cfg["iou_thres"])
    pred_all = boxout[0].numpy()# 预测坐标转换
    scale_coords(cfg['input_shape'], pred_all[:,:4], image.shape, ratio_pad=(scale_ratio, pad_size))# 图片预测结果可视化
    draw_prediction(pred_all, image, class_names)definfer_frame_with_vis(image, model, labels_dict, cfg, bgr2rgb=True):# 数据预处理
    img, scale_ratio, pad_size = preprocess_image(image, cfg, bgr2rgb)# 模型推理
    output = model.infer([img])[0]

    output = torch.tensor(output)# 非极大值抑制后处理
    boxout = nms(output, conf_thres=cfg["conf_thres"], iou_thres=cfg["iou_thres"])
    pred_all = boxout[0].numpy()# 预测坐标转换
    scale_coords(cfg['input_shape'], pred_all[:,:4], image.shape, ratio_pad=(scale_ratio, pad_size))# 图片预测结果可视化
    img_vis = draw_bbox(pred_all, image,(0,255,0),2, labels_dict)return img_vis

defimg2bytes(image):"""将图片转换为字节码"""returnbytes(cv2.imencode('.jpg', image)[1])definfer_video(video_path, model, labels_dict, cfg):"""视频推理"""
    image_widget = widgets.Image(format='jpeg', width=800, height=600)
    display(image_widget)# 读入视频
    cap = cv2.VideoCapture(video_path)whileTrue:
        ret, img_frame = cap.read()ifnot ret:break# 对视频帧进行推理
        image_pred = infer_frame_with_vis(img_frame, model, labels_dict, cfg, bgr2rgb=True)
        image_widget.value = img2bytes(image_pred)definfer_camera(model, labels_dict, cfg):"""外设摄像头实时推理"""deffind_camera_index():
        max_index_to_check =10# Maximum index to check for camerafor index inrange(max_index_to_check):
            cap = cv2.VideoCapture(index)if cap.read()[0]:
                cap.release()return index

        # If no camera is foundraise ValueError("No camera found.")# 获取摄像头
    camera_index = find_camera_index()
    cap = cv2.VideoCapture(camera_index)# 初始化可视化对象
    image_widget = widgets.Image(format='jpeg', width=1280, height=720)
    display(image_widget)whileTrue:# 对摄像头每一帧进行推理和可视化
        _, img_frame = cap.read()
        image_pred = infer_frame_with_vis(img_frame, model, labels_dict, cfg)
        image_widget.value = img2bytes(image_pred)

cfg ={'conf_thres':0.4,# 模型置信度阈值,阈值越低,得到的预测框越多'iou_thres':0.5,# IOU阈值,高于这个阈值的重叠预测框会被过滤掉'input_shape':[640,640],# 模型输入尺寸}

model_path ='yolo.om'
label_path ='./coco_names.txt'# 初始化推理模型
model = InferSession(0, model_path)
labels_dict = get_labels_from_txt(label_path)

infer_mode ='video'if infer_mode =='image':
    img_path ='world_cup.jpg'
    infer_image(img_path, model, labels_dict, cfg)elif infer_mode =='camera':
    infer_camera(model, labels_dict, cfg)elif infer_mode =='video':
    video_path ='racing.mp4'
    infer_video(video_path, model, labels_dict, cfg)

二、修改案例

1、打开jupyter

yolov5_ascend_example

文件夹下打开终端,输入

jupyter lab --ip192.168.3.2 --allow-root

电脑浏览器访问

http://192.168.3.2:8888

,右侧打开我们的

mian.ipynb

文件。

2、atc转换模型

200DK照抄,200I DK A2最后改成Ascend 310B1

atc --model=models/best.onnx --framework=5--output=models/mymodel --input_format=NCHW --input_shape="images:1,3,640,640"--input_fp16_nodes=images --log=error --soc_version=Ascend310

运行结果如下,大约5到10分钟。当然,你也可以用ubuntu主机去做,会快很多,我用pc转换只需要半分钟左右,还是一台4代i7的老年机。
在这里插入图片描述

3、安装依赖

使用我的案例代码的直接运行即可
在这里插入图片描述

其他的请按照以下方法安装

!pip install scikit_video
!pip install pip_packages/aclruntime-0.0.2-cp39-cp39-linux_aarch64.whl
!pip install pip_packages/ais_bench-0.0.2-py3-none-any.whl

注意,aclruntime和ais_bench推理程序的whl包请前往昇腾gitee仓库下载。

4、修改预处理函数

这里我们使用自己训练的模型,需要做如下修改。

img = np.ascontiguousarray(img, dtype=np.float32)

改为

img = np.ascontiguousarray(img, dtype=np.float16)/255.0

在这里插入图片描述

5、修改模型和标签路径

在这里插入图片描述

6、选择你需要的推理模式

在这里插入图片描述
这里务必注意,如果是在vscode里远程打开main.ipynb的,不要推理视频!!! 不仅不显示推理的图像,还会导致内存占用不断升高,且无法终止内核,甚至杀不死进程,最后爆内存断开ssh连接。最终我只能按下复位。

注意

200DK不支持opencv调用摄像头

三、问题

1、No module named ‘scikit’

pip install scikit-video

别搞错名字就行。

2、No module named ‘ais_bench’

访问Gitee仓库,这里有三种方法,作为懒人肯定是选择whl包安装啦。
在这里插入图片描述
我的pc机python是3.9,所以下载这两个,按照下方说明进行安装就行。
咱就粗暴一点,强制覆盖安装啦。

pip3 install ./aclruntime-{version}-{python_version}-linux_{arch}.whl --force-reinstall
pip3 install ./ais_bench-{version}-py3-none-any.whl --force-reinstall

安装成功会提示

# 成功安装aclruntime
Successfully installed aclruntime-{version}# 成功安装ais_bench推理程序
Successfully installed ais_bench-{version}

安装失败的话检查版本然后祭出重启大法。

3、 InputTensor Data Type mismatches.

在这里插入图片描述
这里是折磨了我三天的问题,甚至进行了一下几个可能的排列组合(请不要笑)

1、怀疑导出onnx模型问题

我对比了两个onnx模型结构
在这里插入图片描述
发现只有这里不一样,但是不应该会导致这个问题啊

2、怀疑版本问题

这里怀疑的是转换时的版本问题。因此进行了一波友好的控制变量法测试(手动狗头)。键盘差点不保!

  1. pc机cann7.0
  2. 200dkcann5.1
  3. best.onnx我自己的模型
  4. yolov5s.onnx 200i案例的模型
  5. yolo.om 200i案例的模型
  6. best.om我pc机转的模型
  7. mymodel.om 200dk转的模型

最终,耗时一下午,还是失败了。

3、om模型有问题!!!

最后,只能怀疑是om模型有问题,于是我使用atc指令查询其信息,果然发现了问题所在。关于用法请参考文档。
在这里插入图片描述
对比两个模型,在

Atc command line

best.om

多了

--input_fp16_nodes=images

。我回去一查,嘿,mindx似乎只能用fp16做输入,而我之后转换的模型都是fp32的,怪不得main.py报错。但是,这时

ais_bench

推理的

main.ipynb

又报错了,我们只需要把这个32改成16.
在这里插入图片描述

4、预测框错乱

在这里插入图片描述
这里在经过我刨地三尺,翻了三遍论坛,终于找到了罪魁祸首。详情请参考原文链接。
在这里插入图片描述
我们只需要在这个案例这一行后面添加

/255.0

即可。

5、can’t open camera by index

在这里插入图片描述
使用

ls /dev

命令发现确实没有video类似的设备
在这里插入图片描述
花了两天,最后在昇腾社区找到了答案。
atlas200dk不支持opencv,atlas200dk需要使用自己的媒体处理接口
接口描述:https://www.hiascend.com/document/detail/zh/Atlas200DKDeveloperKit/1013/MediaAPI/atlasma_07_0001.html
摄像头样例:https://gitee.com/ascend/samples/tree/master/cplusplus/level1_single_api/5_200dk_peripheral/ascendcamera

总结

不要问我为什么放鸽子,当你被bug折磨,别说解决方案了,甚至这个报错百度都搜不到,那是心态直接爆炸啊。
强烈建议直接使用我置顶提供的案例文件,避免踩坑,从我做起!!!
我是替你们踩坑的工具人呵呵,下期继续,希望能尽快爬出来吧。

标签: 人工智能 YOLO

本文转载自: https://blog.csdn.net/weixin_44354614/article/details/135368091
版权归原作者 工具人呵呵 所有, 如有侵权,请联系我们删除。

“[嵌入式AI从0开始到入土]12_yolov5在昇腾上应用”的评论:

还没有评论