Skip to content

1.Face Mask Detection with Machine Learning

DeepLearning
Resource:Face Mask Detection with Machine Learning


前言

使用機器學習進行口罩檢測的流程

  • 步驟1:提取用於訓練的臉部數據。
  • 步驟2:訓練分類器,將有口罩的臉部和無口罩的標籤進行分類。
  • 步驟3:在測試數據中使用SSD臉部檢測器進行臉部檢測。
  • 步驟4:使用訓練好的分類器對檢測到的臉部進行分類。

在上述流程的第三步中,你必須思考什麼是SSD臉部檢測器?SSD是一種單次多框檢測器,是一種使用單個深度神經網絡來檢測圖像中物體的技術。

它常用於圖像中物體的檢測。SSD使用VGG-16基本架構,其在速度和準確性方面都能優於其他物體檢測器,如YOLO和Faster R-CNN。

在上述過程的第三步,你必須了解什麼是SSD人臉檢測器?SSD是單次多框檢測器的縮寫。這是一種使用==單個==深度神經網絡來檢測圖像中物體的技術。
它被用於圖像中物體的檢測。SSD使用VGG-16架構的基本結構,以在速度和準確性方面勝過其他物體檢測器,如YOLO和Faster R-CNN。


使用資料集

Resource


操作步驟
  1. 請由Resource登入Kaggle並點選New Notebook
  2. 跟隨Face Mask Detection提供的程式碼依序於Notebook中輸入

Warning

由於seaborn更新之原因,位於In[7]:位置的程式碼
sns.countplot(p)會產生錯誤
請直接將其註解掉


程式碼解析
  1. 導入必要的模組:
    import pandas as pd
    import numpy as np
    import cv2
    import json
    import os
    import matplotlib.pyplot as plt
    import random
    import seaborn as sns
    from keras.models import Sequential
    from keras import optimizers
    from keras import backend as K
    from keras.layers import Dense, Dropout, Activation, Flatten
    from keras.layers import Conv2D, MaxPooling2D, BatchNormalization
    from sklearn.model_selection import train_test_split
    from keras.preprocessing.image import ImageDataGenerator
    

說明:

import項目 使用原因
pandas、numpy 這兩個模組分別用於數據分析和處理。
cv2 這是一個包含許多影像處理功能的模組。
json, os 用於處理JSON格式的數據和檔案路徑。
matplotlib、seaborn 用於製作數據視覺化圖表。
keras 這是一個用於建立深度學習模型的模組,裡面包括Sequential(用於建立模型的框架)、optimizers(優化器,用於優化模型的參數)、backend(底層操作)、各種網路層(例如Dense, Dropout等)、以及影像處理的ImageDataGenerator等
sklearn 其中的train_test_split用於將數據分割成訓練集和驗證集。

  1. 數據路徑與讀取:
    directory = "../input/face-mask-detection-dataset/Medical mask/Medical mask/Medical Mask/annotations"
    image_directory = "../input/face-mask-detection-dataset/Medical mask/Medical mask/Medical Mask/images"
    df = pd.read_csv("../input/face-mask-detection-dataset/train.csv")
    df_test = pd.read_csv("../input/face-mask-detection-dataset/submission.csv")
    cvNet = cv2.dnn.readNetFromCaffe('../input/caffe-face-detector-opencv-pretrained-model/architecture.txt',
                                     '../input/caffe-face-detector-opencv-pretrained-model/weights.caffemodel')```
    
    說明
    
    - 設定包含標註資料的目錄directory)、圖像的目錄image_directory)、以及讀入訓練和測試的CSV檔案
    - cvNet讀取一個已經訓練過的Caffe模型這個模型用於人臉檢測
    ---
     3. 定義函數
    ```python
    def getJSON(filePathandName):
        with open(filePathandName,'r') as f:
            return json.load(f)
    def adjust_gamma(image, gamma=1.0):
        invGamma = 1.0 / gamma
        table = np.array([((i / 255.0) ** invGamma) * 255 for i in np.arange(0, 256)])
        return cv2.LUT(image.astype(np.uint8), table.astype(np.uint8))
    

    說明 :
    - getJSON:用於從指定的檔案路徑讀取JSON格式的數據。
    - adjust_gamma:用於調整影像的gamma值,以改變影像的亮度。這在某些光線條件下可以改進影像的品質。
  2. 讀取與處理圖像數據:
    jsonfiles= []
    for i in os.listdir(directory):
        jsonfiles.append(getJSON(os.path.join(directory,i)))
    jsonfiles[0]
    data = []
    img_size = 124
    mask = ['face_with_mask']
    non_mask = ["face_no_mask"]
    labels={'mask':0,'without mask':1}
    for i in df["name"].unique():
        f = i+".json"
        for j in getJSON(os.path.join(directory,f)).get("Annotations"):
            if j["classname"] in mask:
                x,y,w,h = j["BoundingBox"]
                img = cv2.imread(os.path.join(image_directory,i),1)
                img = img[y:h,x:w]
                img = cv2.resize(img,(img_size,img_size))
                data.append([img,labels["mask"]])
            if j["classname"] in non_mask:
                x,y,w,h = j["BoundingBox"]
                img = cv2.imread(os.path.join(image_directory,i),1)
                img = img[y:h,x:w]
                img = cv2.resize(img,(img_size,img_size))    
                data.append([img,labels["without mask"]])
    random.shuffle(data)
    
    p = []
    for face in data:
        if(face[1] == 0):
            p.append("Mask")
        else:
            p.append("No Mask")
    **sns**{: #sns .hash}.countplot(p) **註解掉**{: #註解掉 .hash}
    

    說明:
  • 從JSON檔案中讀取口罩的標註資料,包括標註的區域(BoundingBox)和類別(classname)。
  • 從對應的圖像中切割出標註的區域,並調整大小到124x124的尺寸。
  • 將切割和調整大小後的圖像以及對應的標籤(是否佩戴口罩)存入變數data。
    5. 數據預處理:

    X = []
    Y = []
    for features,label in data:
        X.append(features)
        Y.append(label)
    
    X = np.array(X)/255.0
    X = X.reshape(-1,124,124,3)
    Y = np.array(Y)
    

    說明:

  • 將圖像數據(特徵)和標籤數據分別儲存到變數X和Y。

  • 進行歸一化:將X中的圖像數據從0-255的整數變成0-1的浮點數。
    6. 建立深度學習模型:
    model = Sequential()
    
    model.add(Conv2D(32, (3, 3), padding = "same", activation='relu', input_shape=(124,124,3)))
    model.add(Conv2D(64, (3, 3), activation='relu'))
    model.add(Conv2D(128, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2,2)))
    model.add(Dropout(0.25))
    
    model.add(Flatten())
    model.add(Dropout(0.5))
    model.add(Dense(50, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(1, activation='sigmoid'))
    
    model.compile(loss='binary_crossentropy', optimizer='adam' ,metrics=['accuracy'])
    

說明:

  • 使用Sequential來建立一個新的深度學習模型。
  • 這個模型包含了卷積層、池化層、全連接層和Dropout層。
    7. 切分訓練和驗證集:’
    xtrain,xval,ytrain,yval=train_test_split(X, Y,train_size=0.8,random_state=0)
    

    說明:
  • 使用train_test_split來將X和Y分割成訓練集和驗證集。
    8. 數據增強:

    datagen = ImageDataGenerator(
            featurewise_center=False,  
            samplewise_center=False,  
            featurewise_std_normalization=False,  
            samplewise_std_normalization=False,  
            zca_whitening=False,    
            rotation_range=15,    
            width_shift_range=0.1,
            height_shift_range=0.1,  
            horizontal_flip=True,  
            vertical_flip=False)
    
    datagen.fit(xtrain)
    

    說明:

  • 使用ImageDataGenerator來增強圖像數據,增強的方法包括旋轉、平移、翻轉等。
    9. 模型訓練:

    history = model.fit_generator(datagen.flow(xtrain, ytrain, batch_size=32),
                        epochs=20,
                        verbose=1,
                        validation_data=(xval, yval))
    

    說明:

  • 使用訓練數據來訓練模型,並使用驗證數據來評估模型的性能。
    10. 結果視覺化:

    plt.plot(history.history['accuracy'],'g')
    plt.plot(history.history['val_accuracy'],'b')
    plt.title('Training Accuracy vs Validation Accuracy')
    plt.ylabel('Accuracy')
    plt.xlabel('Epoch')
    plt.legend(['Train', 'Validation'], loc='upper left')
    plt.show()
    
    plt.plot(history.history['loss'],'g')
    plt.plot(history.history['val_loss'],'b')
    plt.title('Training Loss vs Validation Loss')
    plt.ylabel('Loss')
    plt.xlabel('Epoch')
    plt.legend(['Train', 'Validation'], loc='upper left')
    plt.show()
    

說明:

  • 畫出訓練和驗證過程中模型的準確率和損失值變化曲線,這可以幫助我們了解模型的學習狀況和是否出現過擬合的問題。
    11. 以下程式碼的主要目的是將先前訓練好的模型用來對新的圖片進行預測,並將預測結果直觀地顯示在圖像上。
    model.save("Mask_Model.h5")
    test_images = ['2756.png','5342.jpg', '4591.png','3939.png','3939.png','3911.png']
    
    gamma = 2.0
    fig = plt.figure(figsize = (14,14))
    rows = 3
    cols = 2
    axes = []
    assign = {'0':'Mask','1':"No Mask"}
    for j,im in enumerate(test_images):
        image =  cv2.imread(os.path.join(image_directory,im),1)
        image =  adjust_gamma(image, gamma=gamma)
        (h, w) = image.shape[:2]
        blob = cv2.dnn.blobFromImage(cv2.resize(image, (300,300)), 1.0, (300, 300), (104.0, 177.0, 123.0))
        cvNet.setInput(blob)
        detections = cvNet.forward()
        for i in range(0, detections.shape[2]):
            try:
                box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
                (startX, startY, endX, endY) = box.astype("int")
                frame = image[startY:endY, startX:endX]
                confidence = detections[0, 0, i, 2]
                if confidence > 0.2:
                    im = cv2.resize(frame,(img_size,img_size))
                    im = np.array(im)/255.0
                    im = im.reshape(1,124,124,3)
                    result = model.predict(im)
                    if result>0.5:
                        label_Y = 1
                    else:
                        label_Y = 0
                    cv2.rectangle(image, (startX, startY), (endX, endY), (0, 0, 255), 2)
                    cv2.putText(image,assign[str(label_Y)] , (startX, startY-10), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (36,255,12), 2)
    
            except:pass
        axes.append(fig.add_subplot(rows, cols, j+1))
        plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
    plt.show()
    

具體步驟如下:

  1. model.save("Mask_Model.h5"):將訓練好的模型存儲到檔案”Mask_Model.h5”中。
  2. 定義一個待預測的圖片清單 test_images
  3. 定義了一個調整影像亮度的gamma值。
  4. 創建一個用於顯示預測結果的圖表。
  5. 使用迴圈依次處理每一張測試圖片:
    • 讀取並調整圖像的亮度。
    • 使用人臉檢測模型(cvNet)來檢測圖像中的人臉。cvNet會返回一個包含多個檢測框的清單,每個檢測框包含了位置、大小和信心分數等信息。
    • 使用另一個迴圈來處理每個檢測框:
      • 如果檢測框的信心分數大於0.2,則進行後續處理。這裡的0.2是一個閾值,通常會根據模型的性能和需求來設定。
      • 將檢測框中的圖像調整大小並正規化,然後送入先前訓練好的模型進行預測。
      • 根據模型的預測結果,將檢測框標記為”Mask”或”No Mask”。
      • 在原始圖像上繪製檢測框,並在檢測框上方寫上預測結果。
  6. 最後,將所有處理過的圖像顯示出來。這些圖像中每個人臉周圍都有一個標記為”Mask”或”No Mask”的檢測框,這可以幫助我們直觀地看出模型的預測結果。

Last update : 13 novembre 2024
Created : 13 novembre 2024

Comments

Comments