ONNX Runtime 在樹莓派上的物聯網部署

瞭解如何使用 ONNX Runtime 和樹莓派在邊緣裝置上執行影像分類,從裝置攝像頭獲取輸入並將分類結果傳送到終端。

如果您之前沒有配置過樹莓派,請查閱 樹莓派文件 來設定您的裝置。

將模型部署到邊緣裝置有許多好處和用例。請檢視我們 物聯網教程主頁 上的列表。

Image of Raspberry Pi and camera.

目錄

先決條件

下載原始碼、ML 模型並安裝軟體包

燒錄樹莓派並配置好後,就可以連線並下載原始碼到您的裝置了。

  • 連線到您的樹莓派裝置

在本教程中,我們使用 VNC Viewer 進行遠端連線。如果您打算使用 VNC Viewer,請務必遵循這些設定步驟來建立連線。一旦在樹莓派上啟用了 VNC,並且您已在計算機上下載了 VNC Viewer 應用,就可以遠端連線到裝置了。

Image of 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
    
  • 終端輸出:VNC Viewer 影像
  • 在樹莓派上進行推理的影像: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)
    

結論

現在我們已經成功地在樹莓派上運行了推理,我們可以使用相同的程式碼在任何支援 ONNX Runtime 的裝置上執行推理。我們還可以使用相同的程式碼在樹莓派上使用不同的模型執行推理。請檢視 ONNX 模型動物園 中的其他模型。

更多示例