ONNX Runtime 在树莓派上的物联网部署
了解如何使用 ONNX Runtime 和树莓派在边缘设备上执行图像分类,从设备摄像头获取输入并将分类结果发送到终端。
如果您之前没有配置过树莓派,请查阅 树莓派文档 来设置您的设备。
将模型部署到边缘设备有许多好处和用例。请查看我们 物联网教程主页 上的列表。
目录
先决条件
- 树莓派 3B 开发板
- 使用 树莓派镜像工具中的 Debian 烧录的 SD 卡
- 树莓派 摄像头模块 或其他兼容摄像头。
- 用于远程访问的 VNC Viewer。您也可以选择将开发板连接到显示器。
- 本教程不涵盖树莓派的镜像烧录和设置。假定您对如何在树莓派上配置和使用 Python 进行编程有基本了解。
下载源代码、ML 模型并安装软件包
烧录树莓派并配置好后,就可以连接并下载源代码到您的设备了。
- 连接到您的树莓派设备
在本教程中,我们使用 VNC Viewer 进行远程连接。如果您打算使用 VNC Viewer,请务必遵循这些设置步骤来建立连接。一旦在树莓派上启用了 VNC,并且您已在计算机上下载了 VNC Viewer 应用,就可以远程连接到设备了。
-
将源代码下载到您的树莓派。源代码包含运行推理所需的一切,包括来自模型动物园的
mobilenet
ONNX 模型和imagenet_classes.txt
类别文件。git clone https://github.com/cassiebreviu/onnxruntime-raspberrypi.git
-
导航到
onnxruntime-raspberrypi
下载位置,并使用以下命令从requirements.txt
安装软件包。cd onnxruntime-raspberrypi pip install -r requirements.txt
在本教程中,我们使用树莓派摄像头模块。我们想使用提供的
cameratest.py
脚本测试摄像头。如果摄像头无法正常工作,请运行sudo apt update sudo apt upgrade
来更新开发板和固件。 -
通过运行以下命令配置和测试摄像头。这将在当前目录中创建一个名为
test.jpg
的图像捕获,并打开摄像头输出的实时视频流。按ESC
键取消实时视频输出。python cameratest.py
-
下方是
cameratest.py
脚本供参考import numpy as np import cv2 # Create test image using opencv. cap = cv2.VideoCapture(0) cap.set(3,640) # set Width cap.set(4,480) # set Height ret, frame = cap.read() frame = cv2.flip(frame, -1) # Flip camera vertically cv2.imwrite('test.jpg', frame) # Start live video feed until `ESC` is pressed to quit. while(True): ret, frame = cap.read() frame = cv2.flip(frame, -1) # Flip camera vertically gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) cv2.imshow('frame', frame) cv2.imshow('gray', gray) k = cv2.waitKey(30) & 0xff if k == 27: # press 'ESC' to quit break cap.release() cv2.destroyAllWindows()
使用
inference_mobilenet.py
脚本在树莓派上运行推理
现在我们已经验证了摄像头已连接并在树莓派上正常工作,是时候对源代码中提供的 ONNX 模型进行推理了。该模型是一个 MobileNet 模型,可对 1000 个类别进行图像分类。
- 使用以下命令运行推理脚本。
python inference_mobilenet.py
- 终端输出:
-
在树莓派上进行推理的图像:
-
下方是
inference_mobilenet.py
脚本供参考# Import the packages. from PIL import Image import numpy as np import onnxruntime import torch import cv2 def preprocess_image(image_path, height, width, channels=3): image = Image.open(image_path) image = image.resize((width, height), Image.LANCZOS) image_data = np.asarray(image).astype(np.float32) image_data = image_data.transpose([2, 0, 1]) # transpose to CHW mean = np.array([0.079, 0.05, 0]) + 0.406 std = np.array([0.005, 0, 0.001]) + 0.224 for channel in range(image_data.shape[0]): image_data[channel, :, :] = (image_data[channel, :, :] / 255 - mean[channel]) / std[channel] image_data = np.expand_dims(image_data, 0) return image_data def softmax(x): """Compute softmax values for each sets of scores in x.""" e_x = np.exp(x - np.max(x)) return e_x / e_x.sum() def run_sample(session, image_file, categories): output = session.run([], {'input':preprocess_image(image_file, 224, 224)})[0] output = output.flatten() output = softmax(output) # this is optional top5_catid = np.argsort(-output)[:5] for catid in top5_catid: print(categories[catid], output[catid]) # Write the result to a file. with open("result.txt", "w") as f: for catid in top5_catid: f.write(categories[catid] + " " + str(output[catid]) + " \r") # Create main function to run inference. if __name__ == "__main__": # Read the categories from the classes file. with open("imagenet_classes.txt", "r") as f: categories = [s.strip() for s in f.readlines()] # Create Inference Session session = onnxruntime.InferenceSession("mobilenet_v2_float.onnx") # Get image from the camera. cap = cv2.VideoCapture(0) cap.set(3,640) # set Width cap.set(4,480) # set Height ret, frame = cap.read() frame = cv2.flip(frame, -1) # Flip camera vertically cv2.imwrite('capture.jpg', frame) cap.release() cv2.destroyAllWindows() # Run inference run_sample(session, 'capture.jpg', categories)
结论
现在我们已经成功地在树莓派上运行了推理,我们可以使用相同的代码在任何支持 ONNX Runtime 的设备上运行推理。我们还可以使用相同的代码在树莓派上使用不同的模型运行推理。请查看 ONNX 模型动物园 中的其他模型。