ONNX Runtime 在 Raspberry Pi 上的 IoT 部署
了解如何使用 ONNX Runtime 和 Raspberry Pi 在边缘设备上执行图像分类,从设备摄像头获取输入并将分类结果发送到终端。
如果您之前没有配置过 Raspberry Pi,请查看 Raspberry Pi 文档来设置您的设备。
将模型部署到边缘设备有很多好处和用例。请查看我们的 IoT 教程主页上的列表。
目录
先决条件
- Raspberry Pi 3 B 开发板
- 使用 Raspberry Pi Imager 烧录 Debian 系统的 SD 卡
- Raspberry Pi 摄像头模块或其他兼容摄像头。
- 用于远程访问的 VNC Viewer。您也可以选择将开发板连接到显示器。
- 本教程将不涵盖 Raspberry Pi 的烧录和设置。假定您对如何在 Raspberry Pi 上进行配置和使用 Python 编程有基本了解。
下载源代码、机器学习模型并安装软件包
烧录 Raspberry Pi 并配置好后,就可以连接并下载源代码到您的设备了。
- 连接到您的 Raspberry Pi 设备
在本教程中,我们使用 VNC Viewer 进行远程连接。如果您打算使用 VNC Viewer,请务必遵循 这些设置步骤来建立连接。 在 Raspberry Pi 上启用 VNC 并在您的计算机上 下载 VNC Viewer 应用后,您就可以远程访问设备了。
-
下载源代码到您的 Raspberry Pi。源代码包含运行推理所需的一切,包括来自 模型库 的
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
在本教程中,我们使用的是 Raspberry Pi 摄像头模块。我们想使用提供的
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
脚本在 Raspberry Pi 上运行推理
现在我们已经验证了摄像头在 Raspberry Pi 上连接并正常工作,是时候对源代码中提供的 ONNX 模型进行推理了。该模型是一个 MobileNet 模型,可对 1000 个类别进行图像分类。
- 使用以下命令运行推理脚本。
python inference_mobilenet.py
- 终端输出:
-
在 Raspberry Pi 上进行推理的图像:
-
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)
结论
既然我们已经在 Raspberry Pi 上成功运行了推理,我们可以使用相同的代码在任何支持 ONNX Runtime 的设备上运行推理。我们还可以使用相同的代码在 Raspberry Pi 上运行不同的模型。请查看 ONNX 模型库 中的其他模型。