MENU

作成したCNNモデルを使用して、リアルタイムでマスクの有無を判定

f:id:hanamichi_sukusuku:20210305175648p:plain

f:id:hanamichi_sukusuku:20210305175715p:plain

実行結果

マスクあり

f:id:hanamichi_sukusuku:20210305181606p:plain


マスクなし

f:id:hanamichi_sukusuku:20210305182026p:plain

 

hanamichi-sukusuku.hatenablog.com

このプログラムでは、上記で作成したモデルを使用してリアルタイムのマスクあり、なしの判定を行っていく。

 

必要な変数の定義とモデル読み込み、dlibのインスタンス生成

import keras
import cv2, dlib, pprint, os
import numpy as np
from keras.models import load_model

# 結果ラベル
res_labels = ['NO MASK!!', 'ok']
save_dir = "./live"

# 保存した学習データを読む --- (※1)
model = load_model('mask_model.h5')

# Dlibをはじめる --- (※2)
detector = dlib.get_frontal_face_detector()
 
red = (0,0,255)
green = (0, 255, 0)
fid = 1
cap = cv2.VideoCapture(0)

 

cv2.VideoCapture()で動画処理のためにVideoCaptureオブジェクトを生成。内臓カメラからのデータを取得するために引数に0を指定。USBなどで追加のカメラを接続する場合は0から順番に番号が割り当てられる。

 

while文でカメラから取得した画像データを繰り返し読み込み処理していく

ok, frame = cap.read()
if not ok: break
# 画像を縮小表示する --- (※5)
frame = cv2.resize(frame, (500,300))
# 顔検出 --- (※6)
dets = detector(frame, 1)

cap.read()でカメラから取得した画像データを取得。

返り値はbool型のオブジェクト(取得できればTrue、できなければFalse),画像データの二つが返されるためif文で変数okがFalseであれば処理を中止するようにしている。

 

dlibを使用して顔検出を行う。第二引数の1は顔と認識する最小領域を指定している。1は40✖️40を最小領域として指定。

 

ウィンドウに描画する内容を記述

f:id:hanamichi_sukusuku:20210305185535p:plain



enumerate(dets)で顔検出した座標データを元に画像に枠とテキストを描画していく。

pprint.pprint()では複数の配列を改行し、見やすくして表示してくれる。

x1~y2にそれぞれの座標を格納。

frame[y1:y2, x1:x2]で顔の部分を切り取る。

入りとったデータをcv2.resize()でモデルが学習できるサイズに変換し、reshape()で三次元の配列に変換することでCNNでのモデルで扱えるようにする。

変換した画像データをmodel.predict()で予測。

argmax()で最も大きな値を持つインデックス番号を取得。

 

if文でv == 1の時、つまりマスクをしている時、描画する枠の色をグリーン、ボーダーの太さを2、マスクをしていない時、枠の色を赤、ボーダーの太さを7にするための変数を定義している。

 

cv2.rectangle()で顔検出した座標に枠を描画。

cv2.putText()でテキストを描画。引数には9個の引数を指定することができる。

第一引数から

  1. cv2.imread()で読み込んだ画像データ
  2. 書き込む文字列
  3. 書き込む位置(文字列の左下の角が指定の位置に配置される。
  4. フォントスタイル(今回はcv2.FONT_HERSHEY_SIMPLEXを指定している。
  5. フォントサイズ
  6. フォントの色
  7. フォントの太さ
  8. ラインタイプ

第三引数の位置の指定ではy1から-7を引くことで枠の大きさより上にテキストを表示できる。

 

画像の保存

f:id:hanamichi_sukusuku:20210305191205p:plain

len(dets) > 0はつまり顔検出できた配列が存在する時に以下の処理を実行するようにしている。

cv2.imwrite()で任意のファイルに画像データを保存。

 

ウィンドウに表示

cv2.imshow('Mask Live Check', frame)

cv2.imshow()でウィンドウを表示し、描画した画像を表示する。第一引数はウィンドウの名前なので任意のもの。

 

任意のキーが入力された時、処理を中断する

k = cv2.waitKey(1) # 1msec確認
if k == 27 or k == 13: break

cv2.waitKey()でキーボードからの入力を処理する。引数は指定した数値ミリ秒の間入力を受け付けるというもの。

escは27、enterキーは13となるのでescとenterキーが押されると処理を中断するようにしている。

 

カメラを閉じ、開いているウィンドウを全て閉じる

cap.release() # カメラを解放
cv2.destroyAllWindows() # ウィンドウの破棄