ONNX Runtime 树莓派上的物联网部署

了解如何使用 ONNX Runtime 和树莓派在边缘执行图像分类,从设备的摄像头获取输入并将分类结果发送到终端。

如果您之前没有配置过 Raspberry Pi,请查看 Raspberry Pi 文档 以设置您的设备。

将模型部署到边缘设备有很多好处和用例。请查看我们的 IoT 教程主页 上的列表。

Image of Raspberry Pi and camera.

目录

先决条件

下载源代码、ML 模型并安装软件包

一旦您对 Raspberry Pi 进行映像化并配置好以供使用,就可以连接并下载源代码到您的设备了。

  • 连接到您的 Raspberry Pi 设备

在本教程中,我们使用 VNC Viewer 进行远程登录。 如果您要使用 VNC Viewer,请务必按照 这些设置步骤建立连接。 一旦在 Raspberry Pi 上启用了 VNC,并且您在计算机上 下载了 VNC Viewer 应用程序,您就可以远程登录到设备。

Image of 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
    
  • 终端输出: VNC Viewer 图像
  • 在 Raspberry Pi 上推理的图像: VNC Viewer 图像

  • 下面的 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 模型动物园 中的其他模型。

更多示例