iT邦幫忙

2022 iThome 鐵人賽

DAY 30
0

這篇教學會使用 Teachable Machine 訓練「戴口罩」以及「沒戴口罩」的影像模型,再透過 OpenCV 搭配 tensorflow 讀取攝影鏡頭影像進行「是否有戴口罩」的影像辨識。

原文參考:辨識是否戴口罩

因為程式使用 Jupyter 搭配 Tensorflow 進行開發,所以請先閱讀「使用 Anaconda」和「Jupyter 安裝 Tensorflow」,安裝對應的套件,如果不要使用 Juputer,也可參考「使用 Python 虛擬環境」,建立虛擬環境進行實作。

Python 教學 - 辨識是否戴口罩

Teachable Machine 訓練戴口罩的模型

開啟 Teachable Machine 網站後,點擊「開始使用」建立新專案 ( 最下方可以切換語系為繁體中文 ),選擇 「圖片專案 > 標準圖片模型」,進入圖片模型訓練流程。

Python 教學 - 辨識是否戴口罩

準備 40~50 張人物戴戴口罩的圖片,圖片要求人物臉部清楚,背景從全白到複雜 ( 可以使用 Google 圖片搜尋一些名人戴口罩的照片 )。

Python 教學 - 辨識是否戴口罩

再準備 40~50 張人物沒有戴口罩的圖片,圖片要求人物臉部清楚,背景從全白到複雜 ( 可以使用 Google 圖片搜尋一些名人沒有戴口罩的照片 )。

Python 教學 - 辨識是否戴口罩

參考「使用 Teachable Machine」文章,使用「上傳圖片」的方式,建立「戴口罩」、「沒戴口罩」和「背景」共三個分類。

為什麼要訓練「背景」呢?因為如果沒有背景分類,會在沒有出拳的時候自動判斷最接近的分類,導致判斷出錯,所以建議一定要訓練一個背景的分類 ( 背景的分類除了單純的背景,也可以加入許多雜亂的圖片,增加背景的準確度 )。

Python 教學 - 辨識是否戴口罩

分類建立後點擊「訓練模型」,等待訓練完成,可以從預覽區域測試模型。

Python 教學 - 辨識是否戴口罩

確認辨識結果沒問題,就可以將模型匯出為 Keras 類型,解壓縮後將 .h5 的模型檔案放到指定的資料夾裡。

Python 教學 - 辨識是否戴口罩

搭配 OpenCV 進行辨識,並加入文字

下方的程式碼使用 OpenCV 讀取攝影鏡頭的影像,即時判斷現在出現的影像是什麼分類,並透過 putText() 方法,在影像中加入分類的名稱。

參考:影像加入文字

import tensorflow as tf
import cv2
import numpy as np

model = tf.keras.models.load_model('keras_model.h5', compile=False)  # 載入模型
data = np.ndarray(shape=(1, 224, 224, 3), dtype=np.float32)          # 設定資料陣列

def text(text):      # 建立顯示文字的函式
    global img       # 設定 img 為全域變數
    org = (0,50)     # 文字位置
    fontFace = cv2.FONT_HERSHEY_SIMPLEX  # 文字字型
    fontScale = 1                        # 文字尺寸
    color = (255,255,255)                # 顏色
    thickness = 2                        # 文字外框線條粗細
    lineType = cv2.LINE_AA               # 外框線條樣式
    cv2.putText(img, text, org, fontFace, fontScale, color, thickness, lineType) # 放入文字

cap = cv2.VideoCapture(0)
if not cap.isOpened():
    print("Cannot open camera")
    exit()
while True:
    ret, frame = cap.read()
    if not ret:
        print("Cannot receive frame")
        break
    img = cv2.resize(frame , (398, 224))
    img = img[0:224, 80:304]
    image_array = np.asarray(img)
    normalized_image_array = (image_array.astype(np.float32) / 127.0) - 1
    data[0] = normalized_image_array
    prediction = model.predict(data)
    a,b,bg= prediction[0]    # 印出每個項目的數值資訊
    print(a,b,bg)
    if a>0.999:              # 判斷有戴口罩
        text('ok~')
    if b>0.001:              # 判斷沒戴口罩
        text('no mask!!')
    cv2.imshow('oxxostudio', img)
    if cv2.waitKey(1) == ord('q'):
        break  # 按下 q 鍵停止
cap.release()
cv2.destroyAllWindows()

Python 教學 - 辨識是否戴口罩

如果要加入中文,必須要使用 pillow 函式庫,開啟命令提示字元或終端機,啟動 tensorflow 虛擬環境安裝 pillow 函式庫,再使用下方的程式碼,就能夠加入中文的文字。

參考:建立 tensorflow 的虛擬環境使用中文字型

import tensorflow as tf
import cv2
import numpy as np
from PIL import ImageFont, ImageDraw, Image  # 載入 PIL 相關函式庫

fontpath = 'NotoSansTC-Regular.otf'          # 設定字型路徑

model = tf.keras.models.load_model('keras_model_3.h5', compile=False)  # 載入模型
data = np.ndarray(shape=(1, 224, 224, 3), dtype=np.float32)          # 設定資料陣列

def text(text):   # 建立顯示文字的函式
    global img    # 設定 img 為全域變數
    font = ImageFont.truetype(fontpath, 30)  # 設定字型與文字大小
    imgPil = Image.fromarray(img)            # 將 img 轉換成 PIL 影像
    draw = ImageDraw.Draw(imgPil)            # 準備開始畫畫
    draw.text((0, 0), text, fill=(255, 255, 255), font=font)  # 寫入文字
    img = np.array(imgPil)                   # 將 PIL 影像轉換成 numpy 陣列

cap = cv2.VideoCapture(0)
if not cap.isOpened():
    print("Cannot open camera")
    exit()
while True:
    ret, frame = cap.read()
    if not ret:
        print("Cannot receive frame")
        break
    img = cv2.resize(frame , (398, 224))
    img = img[0:224, 80:304]
    image_array = np.asarray(img)
    normalized_image_array = (image_array.astype(np.float32) / 127.0) - 1
    data[0] = normalized_image_array
    prediction = model.predict(data)
    a,b,bg= prediction[0]
    print(a,b,bg)
    if a>0.999:
        text('很乖')
    if b>0.001:
        text('沒戴口罩!!')
    cv2.imshow('oxxostudio', img)
    if cv2.waitKey(1) == ord('q'):
        break    # 按下 q 鍵停止
cap.release()
cv2.destroyAllWindows()

Python 教學 - 辨識是否戴口罩

更多 Python 教學

大家好,我是 OXXO,是個即將邁入中年的斜槓青年,我已經寫了超過 400 篇 Python 的教學,有興趣可以參考下方連結呦~ ^_^


上一篇
( Day 29 ) 辨識剪刀、石頭、布
下一篇
( Day 31 ) 辨識手寫數字
系列文
Python x AI 影像辨識好好玩32
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言