iT邦幫忙

2021 iThome 鐵人賽

0
AI & Data

觀賞魚辨識的YOLO全餐系列 第 37

Day 37 - 在 AWS Lambda 建立 OpenCV Layer

Day 37 - 在 AWS Lambda 建立 OpenCV Layer

因為 OpenCV 在影像視覺中時常需要用到,所以現在嘗試在 AWS Lambda 中建立一層 OpenCV ,並將 Day 12 - 標籤圖片的方法與實作 這個練習,在 AWS Lambda 上完成。操作的流程如下:

  1. 打包 Python 的 OpenCV 函式庫
  2. 在 AWS Lambda 建立 OpenCV 層
  3. 打包程式以及圖片上傳到 S3
  4. 在 AWS Lambda 執行

步驟 1.打包 Python 的 OpenCV 函式庫

這個動作很重要,務必要在 Linux 環境下完成這個操作,不可以在 Windows/macOS,因為都會執行失敗,推論可能是因為 AWS Lambda 上執行 OpenCV 的 Container 是 Linux-based,但是這又很奇怪的是,其他 Python 的函式不會有這個問題。

登錄 Amazon Linux 2 的主機,執行下列程式,主要的操作內容是:

  • 創建一個新的 Python 虛擬環境
  • 檢查 Python 版本
  • 更新 pip
  • 安裝 opencv
  • 將安裝好的套件壓縮到 python 這個目錄下
  • 檢視壓縮內容
python3 -m venv opencv
cd opencv
. bin/activate
python -V
pip install pip -U
pip install opencv-python
cd lib/python3.7/
ln -s site-packages/ python
zip -r opencv37-45.zip python/
unzip -l opencv37-45.zip

目前這個壓縮包是針對 Python 3.7 且 opencv 的版本是 4.5.3.56,numpy 是 opencv 的相依包,所以會一併被安裝進來,整個檔案的大小是 72 MB左右

https://ithelp.ithome.com.tw/upload/images/20211110/20129510OL7z4hFP8b.png
圖 1、Python OpenCV 壓縮包的相關版本

接著直接上傳壓縮檔到 S3,記得需要先完成 aws configure 的使用者認證。

aws s3 cp opencv37-45.zip s3://[S3存儲桶的名稱]

https://ithelp.ithome.com.tw/upload/images/20211110/20129510qBf7Jsu4wB.png
圖 2、Python OpenCV 壓縮包上傳到 S3

步驟 2.在 AWS Lambda 建立 OpenCV 層

進入 AWS Lambda 管理控制台,選擇建立 Layer,輸入 Layer 名稱,並上傳先前建立的壓縮檔,在選擇相容架構 x86_64,而相容的執行時間指的是希望可以在哪些版本的 python 中執行,只能選擇 Python 3.7 ,選其他版本會出錯,確定後按下 建立 鍵即完成建立 Layer,如下圖所示。

https://ithelp.ithome.com.tw/upload/images/20211110/20129510L6uMJwZR6O.png
圖 3、建立 OpenCV Layer 設定畫面

步驟 3.打包程式以及圖片上傳到 S3

登錄 EC2 ,創建一個目錄,並將相關檔案放入該目錄中,壓縮後上傳到 S3 存儲桶內,相關指令如下, yoloDrawLabel.py 這個程式碼請參考 Day 12 - 標籤圖片的方法與實作

# 建立 lambda 專屬目錄,目錄名稱沒有強制要求
mkdir lambda 
cd lambda 
# 產生使用 opencv 的程式碼
vi yoloDrawLabel.py
mkdir labels images
# 上傳標籤所需要的圖片與標籤檔
aws s3 cp s3://[S3存儲桶的名稱]/00-frame-608x608-0001.jpg ./images
aws s3 cp s3://[S3存儲桶的名稱]/00-frame-0001.txt ./labels
# 執行程式,確保可以在虛擬環境中執行
python yoloDrawLabel.py
# 將所需要檔案壓縮並上傳到 S3
zip -r lambda.zip .
aws s3 cp lambda.zip s3://[S3存儲桶的名稱]

下圖為 EC2 執行畫面。

https://ithelp.ithome.com.tw/upload/images/20211110/20129510QmCuLb5Bmp.png
圖 4、在 EC2 中建立 Lambda 壓縮檔

./yoloDrawLabel.py

import cv2

# 設定輸入與輸出
inputLabelPath = './labels/00-frame-0001.txt'
inputImgPath = './images/00-frame-608x608-0001.jpg'
outputImgPath = './labels/00-frame-608x608-0001.jpg'
# 圖片大小固定為 608*608
img_w= img_h = 608
# 載入圖片
cv2image = cv2.imread(inputImgPath)

with open(inputLabelPath) as f:
  for line in f:
    line = line.strip() # 刪除多餘的空白
    data = line.split() # 將 YOLO 一列的內容轉成一維陣列
    # 將 YOLO 格式轉換為邊界框的左上角和右下角座標
    bbox_width = float(data[3]) * img_w
    bbox_height = float(data[4]) * img_h
    center_x = float(data[1]) * img_w
    center_y = float(data[2]) * img_h
    min_x, min_y = center_x - (bbox_width / 2), center_y - (bbox_height / 2)
    max_x, max_y = center_x + (bbox_width / 2), center_y + (bbox_height / 2)
    print(min_x,min_y,max_x,max_y)
    # 在圖片上寫上物件名稱
    cv2.putText(cv2image, 'Altolamprologus compressiceps', (int(min_x), int(min_y-6)), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 1, cv2.LINE_AA)
    # 畫出邊界框
    cv2.rectangle(cv2image, (int(min_x),int(min_y)), (int(max_x),int(max_y)), (0,255,255), 2)
    # 將檔案另存新圖片檔
    cv2.imwrite(r'{}'.format(outputImgPath), cv2image)
  f.close()

步驟 4.在 AWS Lambda 執行

進入 AWS Lambda 管理控制台,選擇建立 Lambda 函數,設定內容如下圖所示。

  • 選擇下列選項之一來建立您的函式: 從頭開始撰寫
  • 函式名稱: opencv45Func
  • 執行時間: Python 3.7 (注意:這個選項不能選其他的 Python 版本,會出現錯誤的)
  • 架構: x86_64
  • 執行角色: 建立具備基本 Lambda 許可的新角色

https://ithelp.ithome.com.tw/upload/images/20211110/20129510OCxuBShTVU.png
圖 5、建立 Lambda 函數設定畫面

建立 Lambda 函數後,選擇進入 opencv45Func 函數的設定畫面,在畫面的最底端,為本函數新建 Layer,如下圖所示。

https://ithelp.ithome.com.tw/upload/images/20211110/20129510C3XYKqa0lB.png
圖 6、為 Lambda 函數新增 Layer

進入新增 Layer 畫面後,選擇層來源為 自訂 Layer,接著選擇先前建立的 opencv45 函式庫層,如下圖所示。

https://ithelp.ithome.com.tw/upload/images/20211110/20129510UqYLHALQ0k.png
圖 7、選擇 opencv45 函式庫層

上傳程式碼
我們已經把 Lambda 函數代碼上傳到 S3 ,只需在函數設定主畫面的右邊,可以找到一個 上傳於 按鈕,點擊後選擇 Amazon S3 位置,就可以指定位置,如 https://[S3存儲桶的名稱].s3.ap-southeast-1.amazonaws.com/lambda.zip,畫面如下所示。

https://ithelp.ithome.com.tw/upload/images/20211110/20129510mbbjoBs5vV.png
圖 8、使用 S3 壓縮檔建立 Lambda 函數

打開 yoloDrawLabel.py 檔案,插入 AWS Lambda 的呼叫函數 handler ,修改完畢後記得點擊 Deploy,如下圖所示。

https://ithelp.ithome.com.tw/upload/images/20211110/20129510ITzz6d92e0.png
圖 9、修改 Lambda 函數

拉到畫面下方,修改 執行時間設定,將 處理常式 指定為 yoloDrawLabel.handler,如下圖所示。

https://ithelp.ithome.com.tw/upload/images/20211110/20129510FA2QvC53c5.png
圖 10、修改執行時間設定中的處理常式

透過點擊 Test 來執行 AWS Lambda 函數,第一次執行需要設定測試組態,不需任何更改,只需給定名稱即可。接著再點擊後,就會出現執行結果,輸出結果與在 EC2 上相同,輸出方塊框的左上角與右下角座標,如下圖所示。證明了 OpenCV 層已經正常運作。

https://ithelp.ithome.com.tw/upload/images/20211110/20129510mtKcmn8KJ8.png
圖 11、執行 AWS Lambda 函數

參考資料


上一篇
Day 36 - 使用 Container 建立 Amazon SageMaker 端點
下一篇
Day 38 - 在 AWS Lambda 中使用 YOLO 推估 (Inference)
系列文
觀賞魚辨識的YOLO全餐38

尚未有邦友留言

立即登入留言