ONNX Runtime 树莓派上的物联网部署
了解如何使用 ONNX Runtime 和树莓派在边缘执行图像分类,从设备的摄像头获取输入并将分类结果发送到终端。
如果您之前没有配置过 Raspberry Pi,请查看 Raspberry Pi 文档 以设置您的设备。
将模型部署到边缘设备有很多好处和用例。请查看我们的 IoT 教程主页 上的列表。
目录
先决条件
- Raspberry Pi 3 B 板
- 使用 Raspberry Pi Imager 中的 Debian 映像化的 SD 卡
- Raspberry Pi 摄像头模块 或其他兼容的摄像头。
- VNC Viewer 用于远程访问。 可选地,您可以将板连接到显示器。
- 本教程不涵盖树莓派的映像化和设置。 预计您基本了解如何在 Raspberry Pi 上使用 Python 进行配置和编程。
下载源代码、ML 模型并安装软件包
一旦您对 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()
在 Raspberry Pi 上使用
inference_mobilenet.py
脚本运行推理
现在我们已经验证了摄像头已连接并在 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 模型动物园 中的其他模型。