OrangePi AIpro评测 - AI服务篇

qq_27158179 2024-06-26 08:31:03 阅读 52

0. 环境

●OrangePi AIpro

●windows电脑

●路由器

之前我已经对OrangePi AIpro进行了些嵌入式基本操作的评测。接下来进行AI部分。来看看华为昇腾的特别之处。

1.普通CPU和AI CPU

这里请提前用调试串口或者ssh到板子上,记得用户名和密码,分别是HwHiAiUser,Mind@123。串口波特率是115200.

1.1 npu-smi info

npu-smi info

(base) HwHiAiUser@orangepiaipro:~$ npu-smi info

+--------------------------------------------------------------------------------------------------------+

| npu-smi 23.0.0                                   Version: 23.0.0                                       |

+-------------------------------+-----------------+------------------------------------------------------+

| NPU     Name                  | Health          | Power(W)     Temp(C)           Hugepages-Usage(page) |

| Chip    Device                | Bus-Id          | AICore(%)    Memory-Usage(MB)                        |

+===============================+=================+======================================================+

| 0       310B4                 | Alarm           | 0.0          45                15    / 15            |

| 0       0                     | NA              | 0            1564 / 7545                             |

+===============================+=================+======================================================+

(base) HwHiAiUser@orangepiaipro:~$

1.2 npu-smi info -t cpu-num-cfg

说实话,我也不太会看。只知道是8G,7545表示8GB内存。然后默认4核中,3个核是普通CPU,1个是AI CPU,平时AI CPU占用率是0%的。

这个操作可以查看到目前CPU情况。

(base) HwHiAiUser@orangepiaipro:~$ npu-smi info -t cpu-num-cfg -i 0 -c 0

        Current AI CPU number          : 1

        Current control CPU number     : 3

        Current data CPU number        : 0

(base) HwHiAiUser@orangepiaipro:~$

这个是查看利用率。

(base) HwHiAiUser@orangepiaipro:~$ npu-smi info -t usages -i 0 -c 0

        Memory Capacity(MB)            : 7545

        Memory Usage Rate(%)           : 21

        Hugepages Total(page)          : 15

        Hugepages Usage Rate(%)        : 100

        Aicore Usage Rate(%)           : 0

        Aicpu Usage Rate(%)            : 0

        Ctrlcpu Usage Rate(%)          : 2

        Memory Bandwidth Usage Rate(%) : 1

(base) HwHiAiUser@orangepiaipro:~$

然后参考说明书,这个指令还可以设置AI CPU为普通CPU,不过我暂时不操作了。

2.AI Demo

看用户手册,这里的demo是需要先运行Jupyter Lab的。这距离实际部署又差了一段距离。不过对于新手还是比较友好的,多了图形界面。

2.1 运行 Jupyter Lab

运行这个 Jupyter需要命令行执行:

cd ~/samples/notebooks

./start_notebook.sh

看这里的链接,是无法通过局域网访问的。

我想要通过局域网访问:

jupyter lab --ip 192.168.123.179  --port 5678 --allow-root --no-browser

注意这里192.168.123.179是OrangePi AIpro的ip,和windows电脑处于同一个路由器下。

电脑可以访问了:

2.2 运行yolov5 demo

我也不是很熟悉Jupyter,最开始是在百度Ai Studio类似的工具中看到的,按播放可以运行一个个代码块。

打开 yolov5下的main.ipynb。这个格式的文件都需要用Jupyter打开才可以的,不能直接用python运行的。不便于部署,但是便于入门,也可以带有很多注释。带有注释就弥补了很多python库缺少文档的缺点。c/c++的开源库,往往编程基础扎实,也能输出文档。python的库没那么多规矩。

打开 main.ipynb后,点击>>重新运行。

随后等待一段时间,就会有视频输出了。这个demo未修改下,是处理video的。

Jupyter不错,可以显示处理结果。图片和视频都可以。

根据用户手册,这个demo还可以处理图像。修改第4个代码块中的infer_mode,修改为image,再次执行。

会输出结果:

到这里就运行了第一个demo。本demo其实还可以调用摄像头进行识别。不过我暂时未接入摄像头。

其余的demo用同样的方法就可以执行。目前有这几个demo,只要适当修改,就可以直接应用于特定场景当中。

demo还是做得挺完善的,有图像视频处理、文本、图像HDR、语音分类等。其实实际部署到板卡的AI模型,难点在于基本都是在英伟达的GPU中训练,然后再经过模型转换后放到板子上运行的。我以前在电脑中训练过微小模型(LeNet),用的是Tensorflow+Keras,部署到英伟达的GPU、Jetson都很方便,但是要移植到别的AI板卡,就卡在自己不会算子这里。

3.还原为脚本

我还是偏爱脚本,后续可以直接命令行运行。

切换目录:

cd ~/samples/notebooks/01-yolov5

创建文件:

vim main.py

添加内容:

# 导入代码依赖

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

def preprocess_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

def draw_bbox(bbox, img0, color, wt, names):

"""在图片上画预测框"""

det_result_str = ''

for idx, class_id in enumerate(bbox[:, 5]):

if float(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

def get_labels_from_txt(path):

"""从txt文件获取图片标签"""

labels_dict = dict()

with open(path) as f:

for cat_id, label in enumerate(f.readlines()):

labels_dict[cat_id] = label.strip()

return labels_dict

def draw_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)

def infer_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)

def infer_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

def img2bytes(image):

"""将图片转换为字节码"""

return bytes(cv2.imencode('.jpg', image)[1])

def infer_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)

while True:

ret, img_frame = cap.read()

if not ret:

break

# 对视频帧进行推理

image_pred = infer_frame_with_vis(img_frame, model, labels_dict, cfg, bgr2rgb=True)

image_widget.value = img2bytes(image_pred)

def infer_camera(model, labels_dict, cfg):

"""外设摄像头实时推理"""

def find_camera_index():

max_index_to_check = 10 # Maximum index to check for camera

for index in range(max_index_to_check):

cap = cv2.VideoCapture(index)

if cap.read()[0]:

cap.release()

return index

# If no camera is found

raise 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)

while True:

# 对摄像头每一帧进行推理和可视化

_, 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 = 'image'

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)

运行测试:

python3 main.py

这里用脚本调用AI处理器,比上面的Jupyter更利于实际部署。图形界面给学习上手较好,linux服务器还不一定有图形界面。当服务器是后台服务器,没有前端技术,就会只有命令行执行程序。下文还给设备添加HTTP接口,实现命令行被局域网访问。但是如果要执行特定代码,还需要继续开发。

4.如何通过HTTP被调用

假如本板卡不是个大脑,只是个辅助性的AI。那么本板卡需要开发个接口API,给外部调用。虽然SSH也是可以远程执行脚本,不过还是HTTP接口的API比较友好。HTTP形式的,也利于跨平台跨设备进行互相通信。

接下来演示基于python+flask实现的http接口的hello world。

4.1 创建文件 http_api.py

from flask import Flask

app = Flask(__name__)

app.config['JSON_AS_ASCII'] = False  # 禁止中文转义

@app.route('/HelloWorld')

def hello_world():

    return "Hello World!"

if __name__ == "__main__":

    app.run(host="0.0.0.0")

4.2 安装依赖

python3 -m pip install flask

4.3 运行

python3 http_api.py

4.4 接口测试

浏览器打开 192.168.123.179:5000/HelloWorld

用postman测试http接口:

这里用的是Get方式。后续还可以开发HTTP POST接口用以数据交互。比如可以post图像文件到板卡,然后板子用python调用AI处理器进行图像处理。不过本文暂时没有做到那么多。

小结

本人对华为昇腾的AI架构、AI算子等并不熟悉的。只是个门外汉运行下demo,并没有深入到AI部分的开发。本文通过npu-smi这个指令,查看到昇腾的CPU的特别之处,就是这个处理器支持分配CPU核为普通CPU或者AI CPU,这是一大特色。然后参考了用户手册,运行了第一个AI demo。感觉板卡算力还算可以,处理视频也没消耗很多时间就出结果了。记得以前用opencv处理视频的每一帧,CPU模式下1分钟的图片至少也要处理十几分钟。这显得昇腾的AI处理能力在图片、视频方面发挥得还是不错的。最后本文给出了在板子上开发HTTP接口的hello world示例。AI板卡还是需要个方便调用的接口,便于将小AI整进系统中。

参考

[1]OrangePi_AI_Pro_昇腾_用户手册_v0.3.1.pdf

[2]香橙派AIpro学习资源一站式导航,https://www.hiascend.com/forum/thread-0285140173361311056-1-1.html

[3]香橙派AIpro官网资料下载,http://www.orangepi.cn/html/hardWare/computerAndMicrocontrollers/service-and-support/Orange-Pi-AIpro.html



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。