COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測

資料派THU發表於2020-06-03
透過本篇文章你將會學到如何利用Opencv,Keras/Tensorflow和深度學習設計一個口罩檢測器。
 
上週我寫了一篇關於利用深度學習在X光影像中檢測COVID-19的部落格,讀者反饋很喜歡這種及時且具有實際意義的應用,因此今天我們學習另一個與COVID相關的計算機視覺應用,即利用Opencv,Keras/Tensorflow檢測人是否佩戴口罩。
 
我寫這篇部落格主要是受以下幾個因素的影響:
  • 很多讀者要求我寫一篇相關部落格;

  • 看到其他人有相關的實驗(其中我最欣賞的是Prajna Bhandary的實現,也就是我們今天要用到的)。

如果部署正確的話,我們設計的COVID-19面罩檢測器可能幫助確保你和其他人的安全(但我把實施和在戶外分發這件事留給專業醫療人員來決定)。
 
COVID-19: 利用Opencv,Keras/Tensorflow和深度學習進行口罩檢測
 
在本教程中,我們將會討論兩段COVID-19口罩檢測器,詳細說明如何實現一個基於計算機視覺/深度學習的pipeline。
 
首先,我們會了解用於訓練自定義口罩檢測器的資料集。
 
然後,我將向大家展示如何使用Keras和TensorFlow實現一個Python指令碼在資料集中來訓練口罩檢測器。
 
我們將使用此Python指令碼來訓練口罩檢測器並檢視結果。
 
給定一個訓練好的COVID-19口罩檢測器,我們將繼續實現另外兩個Python指令碼,這些指令碼可用於:
  • 檢測圖片中的COVID-19口罩;

  • 檢測實時影片流中的口罩。

文章最後我們會給出一些口罩檢測器的結果,同時給出一些改進意見。
 
兩段COVID-19口罩檢測器
 

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測圖一: 使用Python,OpenCV和TensorFlow/ Keras構建具有計算機視覺和深度學習功能的COVID-19口罩檢測器的階段和各個步驟。

為了訓練自定義的口罩檢測器,我們將專案分為兩個不同的階段,每個階段都有各自的子步驟(如圖1所示):
  1. 訓練:在該階段我們主要是從磁碟載入口罩檢測資料集,在該資料集上訓練模型(使用Keras / TensorFlow),然後將模型序列化到磁碟;

  2. 部署:訓練完口罩檢測器後,載入訓練好的口罩檢測器,進行人臉檢測,然後將人臉分類為戴口罩或不戴口罩。

在本教程的其餘部分中,我們將學習這兩個階段及其相關的子階段,但與此同時,讓我們看一下將用於訓練COVID-19面罩檢測器的資料集。
 
COVID-19 口罩檢測資料集

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測圖2:口罩檢測資料集由“戴口罩”和“不戴口罩”影像組成。我們將使用該資料集,以及Python,OpenCV和TensorFlow/ Keras構建一個口罩檢測器。

我們用的資料集是由PyImageSearch 的讀者Prajna Bhandary提供。
 
資料集共含有1376張圖片,包含兩類:
  • 戴口罩: 690張圖片;

  • 不戴口罩: 686張圖片。

我們的目標是訓練一個自定義的深度學習模型,以檢測一個人是否佩戴口罩。
 
注意:為方便起見,我將Prajna建立的資料集包含在本教程的“下載”部分中。

如何製作口罩資料集?

Prajna和我一樣,一直對世界的狀況感到沮喪,每天有成千上萬的人死亡,而對於我們大部分人來說,我們幾乎無能為力。

為了保持精神振奮,Prajna決定透過應用計算機視覺和深度學習來解決現實問題來分散自己的注意力:

  • 最好的情況——她可以利用自己的專案來幫助他人;

  • 最壞的情況——這給了她急需的心理逃生。

無論哪種方式,它都是雙贏的!

作為程式設計師,開發者和計算機視覺/深學習的從業者,我們都需要從Prajna那裡學到一些東西——讓你的技術,成為你的專注,成為你的天堂。
 
為了建立口罩資料集,Prajna提出瞭如下幾種方案:
  • 拍攝正常的臉部影像;

  • 建立一個Python指令碼向圖片中的人臉新增口罩,從而建立一個人造的(但仍適用於現實世界)資料集。

新增面部標誌(facial landmarks)可以簡化這個問題,面部標誌可以幫我們自動推斷出面部結構的位置,包括:
  • 眼眉

  • 鼻子

  • 顎線

要使用面部標誌構建戴著口罩的面部資料集,我們首先需要從不戴著口罩的人的影像開始:

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測圖3:要構建COVID-19口罩資料集,我們首先從不戴口罩的人的照片開始。首先,我們利用人臉檢測來計算影像中人臉的邊界框位置:

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測圖4:下一步是應用人臉檢測。在這裡,我們藉助了深度學習和OpenCV進行人臉檢測。知道人臉在影像中的位置之後,我們就可以提取出我們感興趣的區域(ROI):

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測

圖5:下一步是使用OpenCV和NumPy切片提取面部ROI。
使用面部標誌定位眼睛鼻子和嘴等:

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測圖6:然後,我們使用dlib檢測面部標誌,找到將口罩放置在臉上的位置。

 下一步我們需要一個口罩的圖片(背景透明),如下:

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測圖7:COVID-19 口罩的示例。由於我們知道面部標誌位置,因此可將該口罩自動覆蓋在人臉的ROI上。透過使用面部標誌(即沿著下巴和鼻子的點)來計算該口罩的放置位置,然後調整口罩的大小,旋轉,將其放在臉上:

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測圖8:在此圖中,我們已將口罩新增到人臉上。不仔細看的話我們很難看出口罩是透過opencv和dlib面部標誌人為新增上去的。然後,對所有輸入影像重複此過程,建立一個口罩資料集:

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測

圖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
Dataset目錄中包含“COVID19口罩檢測資料集”一節中提到的資料。
 
Example目錄中提供了三張可用於測試靜態口罩圖片檢測器用的圖片。
 
本教程中我們會解釋下面三個pyhton指令碼:
  • train_mask_detector.py:接受輸入資料,精調MobileNetV2,建立make_detector.model。同時以圖片的形式輸出訓練過程中的準確度/損失曲線;

  • Detect_mask_image.py:在靜態圖片上進行口罩檢測;

  • Detector_mask_video.py:此指令碼將口罩檢測應用於影片流中的每一幀。

在接下來的兩個部分中,我們將訓練我們的口罩檢測器。
 
利用keras/tensorflow實現COVID-19口罩檢測器訓練指令碼

在檢查完了我們的口罩資料集之後,接下來我們要學習如何使用Keras和Tensorflow訓練一個可以自動檢測一個人是否佩戴口罩的分類器。
 
為了完成此任務,我們將對MobileNet V2進行微調,MobileNet V2是一種高效的架構,可應用於計算能力有限的嵌入式裝置(例如,樹莓派,Google Coral,NVIDIA Jetson Nano等)。
 
注意:如果您對嵌入式計算機視覺感興趣,請務必閱讀我的《 Raspberry Pi for Computer Vision》一書,其中涵蓋了如何在計算資源有限的裝置上使用計算機視覺和深度學習。
 
將我們的口罩檢測器部署到嵌入式裝置可以降低製造此類口罩檢測系統的成本,這就是我們選擇使用這種架構的原因。
 
讓我們開始訓練吧!
 
在目錄結構中開啟train_mask_detector.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
訓練指令碼中的這麼多import可能看起來很嚇人。如果你剛入門深度學習,我建議在繼續之前閱讀我的Keras教程(https://www.pyimagesearch.com/2018/09/10/keras-tutorial-how-to-get-started-with-keras-deep-learning-and-python/)和精調教程(https://www.pyimagesearch.com/2019/06/03/fine-tuning-with-keras-and-deep-learning/)。
 
我們的tensorflow.keras匯入集合允許:
  1. 資料增強;

  2. 載入MobilNetV2分類器(我們將使用預訓練的ImageNet權重對該模型進行精調);

  3. 建立一個新的全連線(FC)頭;

  4. 預處理;

  5. 載入影像資料。

我們將使用scikit-learn(sklearn)對類標籤進行二值化處理,細分資料集並列印分類報告。
 
Imutils庫中的paths模組將幫助我們在資料集中查詢並列出影像。然後,我們將使用matplotlib繪製訓練曲線。
 
為確保可以成功匯入這些庫,請遵循我的Tensorflow 2.0+安裝指南:
  1. 如何在Ubuntu上安裝TensorFlow2.0;

  2. 如何在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
在這裡,我指定了超引數常量,包括我的初始學習率,訓練次數和batch size。之後,我們會使用學習率衰減時間表,這就是為什麼我們將學習率變數命名為初始學習率 INIT_LR的原因。
 
準備載入和預處理我們的訓練資料:

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測

在這個部分中,我們將:
  1. 抓取資料集中的所有imagePath(第44行);

  2. 初始化資料和標籤列表(第45和46行);

  3. 迴圈遍歷imagePaths並載入+預處理影像(第49-60行)。預處理步驟包括將尺寸調整為224×224畫素,轉換成陣列格式並將輸入影像中的畫素值縮放到[-1,1]範圍(透過preprocess_input函式);

  4. 將預處理的影像和相關標籤分別新增到資料和標籤列表中(第59行和第60行);

  5. 確保我們的訓練資料是NumPy陣列格式(第63和64行)。

上面的程式碼行假定你的整個資料集足夠小,可以放到記憶體中。如果資料集大於可用記憶體,建議使用HDF5. 我在《使用Python進行計算機視覺的深度學習》(https://www.pyimagesearch.com/deep-learning-computer-vision-python-book/)(第9和10章)中介紹這個方法。
 
我們的資料準備工作還沒有完成。接下來,我們將對標籤進行編碼,劃分資料集,併為資料增強做準備:

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測

第67-69行對類標籤進行獨熱編碼,這意味著我們的資料將採用以下格式:

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測

labels陣列的每個元素都由一個陣列組成,該陣列中只有一個索引是“ hot”(例如1)。
 
使用scikit-learn中的函式,第73行和第74行將我們的資料分為80%的訓練集和20%的測試集。
 
在訓練過程中,我們將對影像進行動態修改,以提高泛化效能。這稱為資料增強,其中在第77-84行設定隨機旋轉,縮放,剪下,移位和翻轉引數。我們將在訓練時使用增強後的圖片。
 
但是首先,我們需要準備MobileNetV2進行精調:

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測

精調設定過程分為三個步驟:
  1. 向MobileNet載入預訓練的ImageNet權重,而不用擔心網路的損失(第88和89行);

  2. 構造一個新的全連線層,並將其附加到模型最後以代替舊的全連線層(第93-102行);

  3. 凍結網路的基礎層(106和107行)。這些基礎層的權重在反向傳播過程中不會更新,而頂層的權重將被調整。

我經常建議別人使用精調的方法構建一個基線模型,這樣可以節省大量時間。要了解有關理論,目的和策略的更多資訊,請參閱我關於精調的部落格和“使用Python進行計算機視覺的深度學習”(https://www.pyimagesearch.com/deep-learning-computer-vision-python-book/)
 
準備好資料和一個待精調的模型後,我們現在可以編譯和訓練我們的口罩檢測器:

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測

第111-113行使用Adam最佳化器,學習率衰減時間表和二分類交叉熵來編譯我們的模型。如果您要使用此訓練指令碼訓練多個類(大於2),請確保使用多分類交叉熵。
 
在117-122行開始進行口罩訓練。請注意,我們如何用資料增強物件(aug)提供批次變化的影像資料。
 
訓練完成後,我們將在測試集中評估結果模型:

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測

第126-130行在測試集上進行預測,找到最高機率類別標籤索引。然後,我們在終端中列印分類報告以進行檢查。
 
第138行將我們的口罩分類模型序列化到磁碟。
 
我們的最後一步是繪製精度和損失曲線:

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測


準備好繪圖後,第152行使用--plot檔案路徑將影像儲存到磁碟。
 
使用Keras / TensorFlow訓練COVID-19口罩檢測器

現在,我們準備使用Keras,TensorFlow和DeepLearning訓練我們的口罩檢測器。
 
確保已使用本教程的“下載”部分來下載原始碼和麵罩資料集。
 
下面開啟一個終端,然後執行以下命令:
$ 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

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測

圖10:COVID-19口罩檢測器的訓練精度/損失曲線顯示出模型具有很高的準確率,並且在資料上幾乎沒有過擬合的跡象。現在,我們準備使用Python,OpenCV和TensorFlow/ Keras並應用我們的計算機視覺和深度學習知識來執行口罩檢測。

如圖所示,我們的測試集獲得了約99%的準確性。
 
從圖10可以看出,幾乎沒有過擬合的跡象,同時驗證損失低於訓練損失(我在這篇博文(https://www.pyimagesearch.com/2019/10/14/why-is-my-validation-loss-lower-than-my-training-loss/)中討論的現象)。
 
鑑於這些結果,我們希望我們的模型能夠很好地推廣到我們訓練和測試集之外的影像。
 
利用OpenCV實現COVID-19口罩檢測器

訓練好我們的口罩檢測器後,下面我們將學習:
  1. 從磁碟載入輸入影像;

  2. 檢測影像中的人臉;

  3. 應用我們的口罩檢測器將人臉分類為戴口罩或不戴口罩。

在目錄結構中開啟detect_mask_image.py檔案,讓我們開始吧:
# 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
我們的驅動指令碼需要以上三個TensorFlow / Keras函式去載入MaskNet模型和以及預處理輸入影像。
 
OpenCV用來顯示和對影像進行操作。

下一步是解析命令列引數:
# 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"])
有了我們的深度學習模型後,我們的下一步就是載入和預處理輸入影像:

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測

從磁碟載入--image後(第37行),我們複製並記錄圖片尺寸資訊以供將來縮放和顯示(第38和39行)。
 
預處理由OpenCV的blobFromImage函式處理(第42和43行)。如引數所示,我們將尺寸調整為300×300 pixels並執行均值減法。
 
然後,第47行和第48行執行人臉檢測以定點陣圖像中所有人臉的位置。
 
知道每張臉的預測位置後,我們首先確保它們是否滿足--confidence閾值,然後再提取臉部區域即faceROI:

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測

我們遍歷檢測結果並提取置信度與--confidence作比較(第51-58行)。
 
然後,我們計算人臉的邊界框值,並確保該框落在影像的邊界內(第61-67行)。
 
接下來,我們將透過MaskNet模型執行面部ROI:

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測

在這部分程式碼中,我們:
  1. 透過NumPy切片提取面部ROI(第71行);

  2. 採用與訓練期間相同的方式對ROI進行預處理(第72-76行);

  3. 執行口罩檢測以預測“戴口罩”或“不戴口罩”(第80行)。

接下來,我們將註釋並顯示結果!

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測

首先,我們根據口罩檢測器返回的機率確定類別標籤(第84行),併為註釋分配關聯的顏色(第85行)。戴口罩的顏色是“綠色”,不戴口罩的顏色將為“紅色”。

然後,我們使用OpenCV繪製功能(第92-94行)繪製標籤文字(包括類別和機率),以及面部的邊框矩形。

處理完所有檢測後,第97和98行將顯示輸出影像。

使用OpenCV在影像中進行COVID-19口罩檢測

讓我們使用我們的COVID-19口罩檢測器!

確保已使用本教程的“下載”部分來下載原始碼,示例影像和預訓練的口罩檢測器。

接下來開啟一個終端,然後執行以下命令:
$ 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...

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測

圖11:這個男人在公共場所帶口罩了嗎?可以看出,我們的檢測器檢測到圖中的人帶著口罩. 使用Python,OpenCV和TensorFlow/ Keras的計算機視覺和深度學習方法使自動檢測口罩成為可能。(圖片來源:https://www.sunset.com/lifestyle/shopping/fashionable-flu-masks-germ-protection)

如圖所示,我們的口罩檢測器已將該影像正確標記為Mask(戴口罩)。
 
讓我們嘗試另一張圖片,這個人沒有戴口罩:
$ 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...

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測

圖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...

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測

圖13:為什麼未檢測到前景中的女士戴著口罩?使用Python,OpenCV和TensorFlow/ Keras構建的具有計算機視覺和深度學習功能的面罩檢測器是否無效?(圖片來源:https://www.medicaldevice-network.com/news/coronavirus-outbreak-mask-production/)

為什麼會產生這樣的結果?
 
為什麼我們能夠在背景中檢測到兩位男性的臉,併為他們正確分類戴口罩/不戴口罩,卻無法檢測到前景中的那個女人?
 
我將在課程的“改善建議”一節中討論這個問題的原因,這個問題的關鍵在於我們過於依賴我們的兩階段流程。
 
請記住,為了對人是否戴著口罩進行分類,我們首先需要執行人臉檢測-如果未找到人臉(此影像中就發生了這種情況),則不能使用口罩檢測器!
 
我們無法檢測到前景中的人臉的原因是:
  • 口罩遮蓋區域太大;

  • 用於訓練人臉檢測器的資料集不包含戴口罩的人臉示例影像。

因此,如果人臉大部分割槽域被遮擋,我們的臉部檢測器很可能無法檢測到臉部。
 
我將在本教程的“進一步改進的建議”部分中更詳細地討論此問題,包括如何提高口罩檢測器的精度。
 
使用OpenCV在實時影片流中實現我們的COVID-19口罩檢測器

至此,我們知道可以對靜態影像應用口罩檢測了,但是在實時影片流該如何做呢?
 
我們的COVID-19口罩檢測模型是否可以實時執行?
 
讓我們來嘗試一下。
 
在目錄結構中開啟detect_mask_video.py檔案,並插入以下程式碼:
# 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
該指令碼的演算法與在靜態圖片中應用口罩檢測演算法是相同的,但它需要處理網路攝像流中的每一幀。
 
因此,我們還需要匯入一個VideoStream類和time。兩者將用來處理影片流。我們還將利用imutils的方面感知尺寸調整方法。
 
此指令碼的面部檢測/口罩預測邏輯在detect_and_predict_mask函式中:
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 = []

在此處定義該函式,便於稍後理解我們的幀處理迴圈。
 
此函式會檢測人臉,然後將我們的口罩分類器應用於每個 face ROI。這樣的功能可以使我們的程式碼更加健壯。如果你願意的話,可以把它移動到單獨的Python檔案中。
 
我們的detect_and_predict_mask函式接受三個引數:
  • 幀:我們資訊流中的幀;

  • faceNet:用於檢測人臉在影像中的位置的模型;

  • maskNet:我們的COVID-19口罩分類器模型。


在該函式內部,我們構造一個Blob,檢測人臉並初始化一系列列表,並將其中兩個列表作為返回值返回。這些列表包括我們的人臉(即ROI),位置(人臉位置)和預測值(口罩/無口罩預測列表)。
 
從這裡開始,我們將遍歷人臉檢測:

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測


在迴圈內部,我們過濾掉較差的檢測結果(第34-38行),提取邊界框並確保邊界框座標值不要超出圖片邊界(第41-47行)。
 
然後,我們將面部ROI 加到對應的兩個列表裡:

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測


在提取了面部ROI並進行了預處理(第51-56行)之後,我們將面部ROI和邊界框新增到它們各自的列表中。

現在,我們可以透過口罩預測器來進行預測:

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測

上述程式碼邏輯主要用於提高速度。首先,我們確保至少檢測到一張臉(第64行),否則,我們將返回空的pred。
 
其次,我們要在框架中對全部人臉進行推理,以使我們的pipeline更快(第68行)。由於開銷的原因(特別是如果你使用的GPU需要在系統匯流排上進行大量開銷通訊),我們不必編寫另一個迴圈來分別對每個人臉進行預測,批次執行預測更為有效。
 
第72行返回我們的人臉邊界框位置和相應的戴口罩/不戴口罩預測值。
 
接下來,我們將定義命令列引數:
# 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口罩檢測器;

  • 網路攝像頭影片流。

讓我們試下歷遍處理影片流:

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測

我們開始遍歷影片中的幀(第103行)。其中,我們從流中抓取一個幀並調整其大小(106和107行)。
 
同時我們使用便捷工具;第111行會檢測並預測人們是否戴著口罩。
 
讓我們對COVID-19口罩檢測結果做一些後處理:

COVID-19:利用Opencv, Keras/Tensorflow和深度學習進行口罩檢測

在對預測結果的迴圈中(從115行開始),我們:
  1. 展開人臉邊界框和戴口罩/不戴口罩的預測(第117和118行);

  2. 確定標籤和顏色(122-126行);

  3. 註釋標籤和麵邊界框(第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()
影片幀被顯示後,我們捕獲按鍵。如果使用者按q(退出),我們將跳出迴圈並執行釋放記憶體。
 
用Python,OpenCV和TensorFlow/ Keras進行深度學習來實現一個實時口罩檢測器真是太好了!
 
使用OpenCV實時檢測COVID-19口罩

要檢視實時COVID-19口罩檢測器的效果,請確保使用本教程的“下載”部分下載原始碼和預訓練的口罩檢測器模型。
 
然後使用以下命令在實時影片流中啟動口罩檢測器:
$ python detect_mask_video.py
[INFO] loading face detector model...
[INFO] loading face mask detector model...
[INFO] starting video stream...
可以看到我們的口罩檢測器能夠實時執行(並且準確預測)。
 
改善建議

從上面的結果部分可以看到,我們的口罩檢測器可以很好地工作,儘管:
  • 訓練資料有限;

  • 人工生成的戴口罩資料集(請參見上面的“如何建立我們的面罩資料集?”部分)。

為了進一步改善我們的口罩檢測模型,你應該收集戴口罩的人的實際影像(而不是人工生成的影像)。
 
雖然我們的人工資料集在這種情況下效果很好,但並不能代替真實的戴口罩人像。
 
其次,你還應該收集可能會“迷惑分類器的人臉影像,這些圖片會讓分類器誤認為照片中的人戴口罩但實際上沒有戴口罩。比如說:包裹在臉部的襯衫,遮擋在嘴部的頭巾等. 所有這些都是可以“迷惑”我們的口罩檢測器將其判斷為戴口罩的示例。
 
最後,你應該考慮訓練專用的兩類目標檢測器,而不是簡單的影像分類器。
 
我們目前的人臉口罩檢測的方法分為兩個步驟:
  • 步驟1:執行人臉檢測;

  • 步驟2:對每張臉進行口罩檢測。

這種方法的問題在於,根據定義,口罩會遮蓋臉部的一部分。如果遮擋了區域過大,則無法檢測到臉部,也就無法使用口罩檢測器。
 
為了避免該問題,我們應訓練一個兩類的目標檢測器,該目標檢測器由戴口罩類和不戴口罩類組成。
 
將目標檢測器與戴口罩類結合使用將在以下兩個方面改進模型。
 
首先,目標檢測器將能夠自然地檢測戴著口罩的人,否則由於過多的面部被遮蓋,人臉檢測器將無法檢測到這些物件。
 
其次,這種方法將我們的計算機視覺流程簡化為一步-而不是先應用人臉檢測,再應用口罩檢測器模型,我們要做的就是在網路的一次前向傳遞過程中應用目標檢測器對影像中戴口罩和不戴口罩的人計算出邊界框。
 
這種方法不僅計算效率更高,更“優雅”而且是端到端。

原文標題:
COVID-19: Face Mask Detector with OpenCV, Keras/TensorFlow, and Deep Learning
原文連結:
https://www.pyimagesearch.com/2020/05/04/covid-19-face-mask-detector-with-opencv-keras-tensorflow-and-deep-learning/  

相關文章