ラズパイで Face Mask Detector with OpenCV, Keras/TensorFlowを使ってみた

コロナ対策として体温測定とマスク検出は必須と思い、COVID-19 face mask detector with OpenCV, Keras/TensorFlowを試してみたので紹介します。

参考にさせていただいたのは、以下のページです。

https://www.pyimagesearch.com/2020/05/04/covid-19-face-mask-detector-with-opencv-keras-tensorflow-and-deep-learning/

上記サイトからコード一式をダウンロードして、ラズパイに転送します。

Face mask detector with OpenCV, Keras/TensorFlowとは?

以下が「Face mask detector with OpenCV, Keras/TensorFlow」の構成です。

大きく分けると、マスク検出の学習フェーズと適用フェーズの2つにわかれます。

学習フェーズでは、マスクあり・なし画像データ(dataset)を元に学習します。学習フェーズが完了すると、学習済のモデル(mask_detector.model)が生成されます。

適用フェースでは、先程学習したモデルを使って、マスク検出を行い結果を表示します。

Face mask detector with OpenCV, Keras/TensorFlowの構成図

ライブラリのインストール

プログラムのインポートモジュールをみると、TensorFlowとimutils,sklearnが必要になるのでインストールします。ライブラリのインストールにはpipを使用します。

参考までに、自分の環境のPythonとPipのバージョンは以下です。Pythonは標準でインストールされているものを使用しました。

$ python3 -V
Python 3.7.3
$ pip3 -V
pip 20.2.3 from /home/xxx/.local/lib/python3.7/site-packages/pip (python 3.7)

まず、TensorFlowをインストールします。

$ pip3 install tensorflow

続いて、imutils,sklearnをインストールします。

$ pip3 install imutils sklearn

以上でインストール作業は完了です。

Phase1:マスク検出データの学習

マスクあり・なしの画像データ(dataset)を元に学習させます。
※引数”–dataset”で学習対象のディレクトリを指定(datasetディレクトリ内にサンプル画像が格納されているのでそのまま使用します)

$ python3 train_mask_detector.py --dataset dataset
2020-10-07 10:02:27.370758: E tensorflow/core/platform/hadoop/hadoop_file_system.cc:132] HadoopFileSystem load error: libhdfs.so: cannot open shared object file: No such file or directory

tensorflowのインポートでエラーが表示されますが、影響はなさそうなので、とりあえず無視しています。

ラズパイ4で学習させようと試みたのですが、ラズパイ4(2GB)モデルだとメモリが足りたいみたいで途中で落ちてしまいます。カーネルを64ビット化してもダメでした。もっとメモリを搭載しているモデル(4GB/8GB)だと上手くいくかもしれません。手元にないので断念・・・

Traceback (most recent call last):
File "train_mask_detector.py", line 66, in
data = np.array(data, dtype="float32")
ValueError: array is too big; arr.size * arr.dtype.itemsize is larger than the maximum possible size.

とりあえず、Debianをインストールした64ビットPC(メモリいっぱい積んでる)で学習させてみました。学習が無事に完了すると、”mask_detector.model”と”plot.png”ファイルが更新されます。実行結果をみてみると、20回ほど学習させて信頼性を上げているようです。

[INFO] compiling model…
[INFO] training head…
Epoch 1/20
WARNING:tensorflow:From /home/user1/.local/lib/python3.7/site-packages/tensorflow/python/ops/math_grad.py:1250: add_dispatch_support..wrapper (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.
Instructions for updating:
Use tf.where in 2.0, which has the same broadcast rule as np.where
4/4 [==============================] - 6s 2s/step - loss: 0.9033 - acc: 0.5000 - val_loss: 0.5485 - val_acc: 0.7568
Epoch 2/20
4/4 [==============================] - 4s 1s/step - loss: 0.8019 - acc: 0.5938 - val_loss: 0.5715 - val_acc: 0.6216
Epoch 3/20
4/4 [==============================] - 4s 1s/step - loss: 0.7502 - acc: 0.6053 - val_loss: 0.5899 - val_acc: 0.5946
Epoch 4/20
4/4 [==============================] - 4s 1s/step - loss: 0.6791 - acc: 0.5965 - val_loss: 0.5493 - val_acc: 0.5946
Epoch 5/20
4/4 [==============================] - 4s 994ms/step - loss: 0.6822 - acc: 0.6228 - val_loss: 0.5115 - val_acc: 0.6216
Epoch 6/20
4/4 [==============================] - 4s 956ms/step - loss: 0.5556 - acc: 0.7105 - val_loss: 0.4572 - val_acc: 0.7027
Epoch 7/20
4/4 [==============================] - 4s 1s/step - loss: 0.5516 - acc: 0.7368 - val_loss: 0.3600 - val_acc: 0.7838
Epoch 8/20
4/4 [==============================] - 4s 1s/step - loss: 0.4679 - acc: 0.7807 - val_loss: 0.3677 - val_acc: 0.7838
Epoch 9/20
4/4 [==============================] - 4s 1s/step - loss: 0.4024 - acc: 0.8203 - val_loss: 0.3479 - val_acc: 0.7838
Epoch 10/20
4/4 [==============================] - 4s 975ms/step - loss: 0.3760 - acc: 0.8684 - val_loss: 0.3092 - val_acc: 0.7838
Epoch 11/20
4/4 [==============================] - 4s 969ms/step - loss: 0.3607 - acc: 0.8246 - val_loss: 0.3538 - val_acc: 0.7838
Epoch 12/20
4/4 [==============================] - 4s 1s/step - loss: 0.3129 - acc: 0.8772 - val_loss: 0.2926 - val_acc: 0.7838
Epoch 13/20
4/4 [==============================] - 4s 1s/step - loss: 0.3048 - acc: 0.8828 - val_loss: 0.3156 - val_acc: 0.8108
Epoch 14/20
4/4 [==============================] - 4s 1s/step - loss: 0.2768 - acc: 0.8947 - val_loss: 0.2923 - val_acc: 0.8108
Epoch 15/20
4/4 [==============================] - 4s 995ms/step - loss: 0.2336 - acc: 0.9298 - val_loss: 0.2712 - val_acc: 0.8649
Epoch 16/20
4/4 [==============================] - 4s 952ms/step - loss: 0.2683 - acc: 0.8947 - val_loss: 0.2412 - val_acc: 0.8649
Epoch 17/20
4/4 [==============================] - 4s 1s/step - loss: 0.2506 - acc: 0.9062 - val_loss: 0.2837 - val_acc: 0.8108
Epoch 18/20
4/4 [==============================] - 4s 912ms/step - loss: 0.2548 - acc: 0.8900 - val_loss: 0.2290 - val_acc: 0.8649
Epoch 19/20
4/4 [==============================] - 4s 1s/step - loss: 0.2065 - acc: 0.9453 - val_loss: 0.2376 - val_acc: 0.9189
Epoch 20/20
4/4 [==============================] - 4s 995ms/step - loss: 0.2424 - acc: 0.9035 - val_loss: 0.2381 - val_acc: 0.9189
[INFO] evaluating network…
precision recall f1-score support
with_mask 0.87 1.00 0.93 20
without_mask 1.00 0.82 0.90 17
accuracy 0.92 37
macro avg 0.93 0.91 0.92 37
weighted avg 0.93 0.92 0.92 37
[INFO] saving mask detector model…

学習結果は、出力される”plot.png”ファイルで確認することができます。Epoch#(学習回数)が増えるごとにLossが下がって、Accuracyが上がっているのが分かりますね。

学習結果のグラフ(plot.png)

今回は、この学習済のモデルをラズパイにコピーして使用しました。ただ、初期状態でも学習済みのモデルが入ってるようなので、学習せずにマスク検出のみを試すこともできると思います。

Phase2:マスク検出データの適用

学習済のデータを元にサンプル画像を使ってマスク検出を行います。

$ python3 detect_mask_image.py --image images/pic1.jpeg

サンプル画像(pic1.jpeg)から正しくマスクを検出できています。
※緑枠と緑文字(Mask)がマスクあり判定で、赤枠と赤文字(No_Mask)がマスクなし判定

次は映像入力を使って、リアルタイムにマスクあり・なしを検出してみます。

$ python3 detect_mask_video.py

マスクをつけたり、はずしたりして正しく認識できているか確認します。

マスクなしの場合は赤枠と赤文字(No_Mask)で、マスクありの場合は緑枠と緑文字(Mask)が表示されています。

ラズパイで検出するとパワー不足なのか画像がカクカクなるので、体温測定結果を表示する際に、マスク検出を行ってマスク有無の結果表示のみするようにすれば使えそうです。

コロナ禍で、マスク有無を検出する場合にはとても助かりますね。

体温測定と組み合わせて試してみようと思います。

Follow me!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA