很多讀者要求我寫一篇相關部落格;
看到其他人有相關的實驗(其中我最欣賞的是Prajna Bhandary的實現,也就是我們今天要用到的)。
檢測圖片中的COVID-19口罩;
檢測實時影片流中的口罩。
訓練:在該階段我們主要是從磁碟載入口罩檢測資料集,在該資料集上訓練模型(使用Keras / TensorFlow),然後將模型序列化到磁碟;
部署:訓練完口罩檢測器後,載入訓練好的口罩檢測器,進行人臉檢測,然後將人臉分類為戴口罩或不戴口罩。
戴口罩: 690張圖片;
不戴口罩: 686張圖片。
最好的情況——她可以利用自己的專案來幫助他人;
最壞的情況——這給了她急需的心理逃生。
拍攝正常的臉部影像;
建立一個Python指令碼向圖片中的人臉新增口罩,從而建立一個人造的(但仍適用於現實世界)資料集。
眼
眼眉
鼻子
嘴
顎線
首先,我們利用人臉檢測來計算影像中人臉的邊界框位置:
知道人臉在影像中的位置之後,我們就可以提取出我們感興趣的區域(ROI):
透過使用面部標誌(即沿著下巴和鼻子的點)來計算該口罩的放置位置,然後調整口罩的大小,旋轉,將其放在臉上:
然後,對所有輸入影像重複此過程,建立一個口罩資料集:
圖9:展示了一組人工製作的COVID-19口罩影像。這將成為我們“戴口罩” /“不戴口罩”資料集的一部分,該資料集將被用於使用Python、OpenCV、Tensorflow/Keras的計算機視覺和深度學習技術訓練的COVID-19面部口罩檢測器。
參考Prajna的GitHub;
參考PyImageSearch上另一篇教程,如何利用面部標誌自動將太陽鏡戴在人臉上(https://www.pyimagesearch.com/2018/11/05/creating-gifs-with-opencv/)。
$ tree --dirsfirst --filelimit 10 ├── dataset │ ├── with_mask [690 entries] │ └── without_mask [686 entries] ├── examples │ ├── example_01.png │ ├── example_02.png │ └── example_03.png ├── face_detector │ ├── deploy.prototxt │ └── res10_300x300_ssd_iter_140000.caffemodel ├── detect_mask_image.py ├── detect_mask_video.py ├── mask_detector.model ├── plot.png └── train_mask_detector.py 5 directories, 10 files
train_mask_detector.py:接受輸入資料,精調MobileNetV2,建立make_detector.model。同時以圖片的形式輸出訓練過程中的準確度/損失曲線;
Detect_mask_image.py:在靜態圖片上進行口罩檢測;
Detector_mask_video.py:此指令碼將口罩檢測應用於影片流中的每一幀。
# import the necessary packages from tensorflow.keras.preprocessing.image import ImageDataGenerator from tensorflow.keras.applications import MobileNetV2 from tensorflow.keras.layers import AveragePooling2D from tensorflow.keras.layers import Dropout from tensorflow.keras.layers import Flatten from tensorflow.keras.layers import Dense from tensorflow.keras.layers import Input from tensorflow.keras.models import Model from tensorflow.keras.optimizers import Adam from tensorflow.keras.applications.mobilenet_v2 import preprocess_input from tensorflow.keras.preprocessing.image import img_to_array from tensorflow.keras.preprocessing.image import load_img from tensorflow.keras.utils import to_categorical from sklearn.preprocessing import LabelBinarizer from sklearn.model_selection import train_test_split from sklearn.metrics import classification_report from imutils import paths import matplotlib.pyplot as plt import numpy as np import argparse import os
資料增強;
載入MobilNetV2分類器(我們將使用預訓練的ImageNet權重對該模型進行精調);
建立一個新的全連線(FC)頭;
預處理;
載入影像資料。
如何在Ubuntu上安裝TensorFlow2.0;
如何在macOS上安裝TensorFlow2.0。
# construct the argument parser and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-d", "--dataset", required=True, help="path to input dataset") ap.add_argument("-p", "--plot", type=str, default="plot.png", help="path to output loss/accuracy plot") ap.add_argument("-m", "--model", type=str, default="mask_detector.model", help="path to output face mask detector model") args = vars(ap.parse_args())
--dataset:人臉和戴口罩的人臉的輸入資料集的路徑;
--plot:輸出訓練過程圖的路徑,將使用matplotlib生成這些圖;
--model:生成的序列化口罩分類模型的路徑。
# initialize the initial learning rate, number of epochs to train for, # and batch size INIT_LR = 1e-4 EPOCHS = 20 BS = 32
抓取資料集中的所有imagePath(第44行);
初始化資料和標籤列表(第45和46行);
迴圈遍歷imagePaths並載入+預處理影像(第49-60行)。預處理步驟包括將尺寸調整為224×224畫素,轉換成陣列格式並將輸入影像中的畫素值縮放到[-1,1]範圍(透過preprocess_input函式);
將預處理的影像和相關標籤分別新增到資料和標籤列表中(第59行和第60行);
確保我們的訓練資料是NumPy陣列格式(第63和64行)。
向MobileNet載入預訓練的ImageNet權重,而不用擔心網路的損失(第88和89行);
構造一個新的全連線層,並將其附加到模型最後以代替舊的全連線層(第93-102行);
凍結網路的基礎層(106和107行)。這些基礎層的權重在反向傳播過程中不會更新,而頂層的權重將被調整。
$ python train_mask_detector.py --dataset dataset [INFO] loading images... [INFO] compiling model... [INFO] training head... Train for 34 steps, validate on 276 samples Epoch 1/20 34/34 [==============================] - 30s 885ms/step - loss: 0.6431 - accuracy: 0.6676 - val_loss: 0.3696 - val_accuracy: 0.8242 Epoch 2/20 34/34 [==============================] - 29s 853ms/step - loss: 0.3507 - accuracy: 0.8567 - val_loss: 0.1964 - val_accuracy: 0.9375 Epoch 3/20 34/34 [==============================] - 27s 800ms/step - loss: 0.2792 - accuracy: 0.8820 - val_loss: 0.1383 - val_accuracy: 0.9531 Epoch 4/20 34/34 [==============================] - 28s 814ms/step - loss: 0.2196 - accuracy: 0.9148 - val_loss: 0.1306 - val_accuracy: 0.9492 Epoch 5/20 34/34 [==============================] - 27s 792ms/step - loss: 0.2006 - accuracy: 0.9213 - val_loss: 0.0863 - val_accuracy: 0.9688 ... Epoch 16/20 34/34 [==============================] - 27s 801ms/step - loss: 0.0767 - accuracy: 0.9766 - val_loss: 0.0291 - val_accuracy: 0.9922 Epoch 17/20 34/34 [==============================] - 27s 795ms/step - loss: 0.1042 - accuracy: 0.9616 - val_loss: 0.0243 - val_accuracy: 1.0000 Epoch 18/20 34/34 [==============================] - 27s 796ms/step - loss: 0.0804 - accuracy: 0.9672 - val_loss: 0.0244 - val_accuracy: 0.9961 Epoch 19/20 34/34 [==============================] - 27s 793ms/step - loss: 0.0836 - accuracy: 0.9710 - val_loss: 0.0440 - val_accuracy: 0.9883 Epoch 20/20 34/34 [==============================] - 28s 838ms/step - loss: 0.0717 - accuracy: 0.9710 - val_loss: 0.0270 - val_accuracy: 0.9922 [INFO] evaluating network... precision recall f1-score support with_mask 0.99 1.00 0.99 138 without_mask 1.00 0.99 0.99 138 accuracy 0.99 276 macro avg 0.99 0.99 0.99 276 weighted avg 0.99 0.99 0.99 276
圖10:COVID-19口罩檢測器的訓練精度/損失曲線顯示出模型具有很高的準確率,並且在資料上幾乎沒有過擬合的跡象。現在,我們準備使用Python,OpenCV和TensorFlow/ Keras並應用我們的計算機視覺和深度學習知識來執行口罩檢測。
從磁碟載入輸入影像;
檢測影像中的人臉;
應用我們的口罩檢測器將人臉分類為戴口罩或不戴口罩。
# import the necessary packages from tensorflow.keras.applications.mobilenet_v2 import preprocess_input from tensorflow.keras.preprocessing.image import img_to_array from tensorflow.keras.models import load_model import numpy as np import argparse import cv2 import os
# construct the argument parser and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, help="path to input image") ap.add_argument("-f", "--face", type=str, default="face_detector", help="path to face detector model directory") ap.add_argument("-m", "--model", type=str, default="mask_detector.model", help="path to trained face mask detector model") ap.add_argument("-c", "--confidence", type=float, default=0.5, help="minimum probability to filter weak detections") args = vars(ap.parse_args())
--image:輸入影像的路徑,其中包含用於推理的人臉影像;
--face:人臉檢測模型目錄的路徑(我們需要先對人臉進行定位,然後再對其進行分類);
--model:口罩檢測器模型的路徑;
--confidence:可選項將機率閾值設定為覆蓋50%,以過濾較差的人臉檢測結果。
# load our serialized face detector model from disk print("[INFO] loading face detector model...") prototxtPath = os.path.sep.join([args["face"], "deploy.prototxt"]) weightsPath = os.path.sep.join([args["face"], "res10_300x300_ssd_iter_140000.caffemodel"]) net = cv2.dnn.readNet(prototxtPath, weightsPath) # load the face mask detector model from disk print("[INFO] loading face mask detector model...") model = load_model(args["model"])
透過NumPy切片提取面部ROI(第71行);
採用與訓練期間相同的方式對ROI進行預處理(第72-76行);
執行口罩檢測以預測“戴口罩”或“不戴口罩”(第80行)。
$ python detect_mask_image.py --image examples/example_01.png [INFO] loading face detector model... [INFO] loading face mask detector model... [INFO] computing face detections...
圖11:這個男人在公共場所帶口罩了嗎?可以看出,我們的檢測器檢測到圖中的人帶著口罩. 使用Python,OpenCV和TensorFlow/ Keras的計算機視覺和深度學習方法使自動檢測口罩成為可能。(圖片來源:https://www.sunset.com/lifestyle/shopping/fashionable-flu-masks-germ-protection)
$ python detect_mask_image.py --image examples/example_02.png [INFO] loading face detector model... [INFO] loading face mask detector model... [INFO] computing face detections...
圖12:我在這張照片中沒有戴口罩。使用Python,OpenCV和TensorFlow/ Keras,我們的系統已正確檢測到我的臉部為No Mask(“無口罩”)。
$ python detect_mask_image.py --image examples/example_03.png [INFO] loading face detector model... [INFO] loading face mask detector model... [INFO] computing face detections...
圖13:為什麼未檢測到前景中的女士戴著口罩?使用Python,OpenCV和TensorFlow/ Keras構建的具有計算機視覺和深度學習功能的面罩檢測器是否無效?(圖片來源:https://www.medicaldevice-network.com/news/coronavirus-outbreak-mask-production/)
口罩遮蓋區域太大;
用於訓練人臉檢測器的資料集不包含戴口罩的人臉示例影像。
# import the necessary packages from tensorflow.keras.applications.mobilenet_v2 import preprocess_input from tensorflow.keras.preprocessing.image import img_to_array from tensorflow.keras.models import load_model from imutils.video import VideoStream import numpy as np import argparse import imutils import time import cv2 import os
def detect_and_predict_mask(frame, faceNet, maskNet): # grab the dimensions of the frame and then construct a blob # from it (h, w) = frame.shape[:2] blob = cv2.dnn.blobFromImage(frame, 1.0, (300, 300), (104.0, 177.0, 123.0)) # pass the blob through the network and obtain the face detections faceNet.setInput(blob) detections = faceNet.forward() # initialize our list of faces, their corresponding locations, # and the list of predictions from our face mask network faces = [] locs = [] preds = []
幀:我們資訊流中的幀;
faceNet:用於檢測人臉在影像中的位置的模型;
maskNet:我們的COVID-19口罩分類器模型。
# construct the argument parser and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-f", "--face", type=str, default="face_detector", help="path to face detector model directory") ap.add_argument("-m", "--model", type=str, default="mask_detector.model", help="path to trained face mask detector model") ap.add_argument("-c", "--confidence", type=float, default=0.5, help="minimum probability to filter weak detections") args = vars(ap.parse_args())
--face:人臉檢測器目錄的路徑;
--model:訓練好的口罩分類器的路徑;
--confidence:用來過濾較差檢測的最小機率閾值。
# load our serialized face detector model from disk print("[INFO] loading face detector model...") prototxtPath = os.path.sep.join([args["face"], "deploy.prototxt"]) weightsPath = os.path.sep.join([args["face"], "res10_300x300_ssd_iter_140000.caffemodel"]) faceNet = cv2.dnn.readNet(prototxtPath, weightsPath) # load the face mask detector model from disk print("[INFO] loading face mask detector model...") maskNet = load_model(args["model"]) # initialize the video stream and allow the camera sensor to warm up print("[INFO] starting video stream...") vs = VideoStream(src=0).start() time.sleep(2.0)
人臉檢測器;
COVID-19口罩檢測器;
網路攝像頭影片流。
展開人臉邊界框和戴口罩/不戴口罩的預測(第117和118行);
確定標籤和顏色(122-126行);
註釋標籤和麵邊界框(第130-132行)。
# show the output frame cv2.imshow("Frame", frame) key = cv2.waitKey(1) & 0xFF # if the `q` key was pressed, break from the loop if key == ord("q"): break # do a bit of cleanup cv2.destroyAllWindows() vs.stop()
$ python detect_mask_video.py [INFO] loading face detector model... [INFO] loading face mask detector model... [INFO] starting video stream...
訓練資料有限;
人工生成的戴口罩資料集(請參見上面的“如何建立我們的面罩資料集?”部分)。
步驟1:執行人臉檢測;
步驟2:對每張臉進行口罩檢測。