背景
前回からの続きです
ローカル環境でしゃべる所まで完成
何をする
これも前回からの続きです
各処理の内容を作ってゆく
処理を以下の順番に実行する
- takepic
カメラを使って写真を撮る - extract_face
写真の中から顔を抜き出す - judge_mask
マスクをしているか否か判定 - speak_judge
判定内容に合わせてしゃべる内容を決定 - speak_out
しゃべる
環境など
- SurfacePro3
- Lobeを実行できる手持ちのwin10環境。HWの条件がそろわないとLobeはインストールすらできなかった
- pythonのバージョンは3.7。環境には3.8もあるものの、tfliteが対応していなかった。Lobeが出力したサンプルは3.6を前提にしているみたいだが、用意するのが面倒だった、、
- Azureのアカウント
- FaceDetection、顔検証の機能を使用。1分当たり20件、月10,000件までは無料という設定。月30日とした場合、1日当たり300回程度までは無料なので今回の件を試してみるには十分。
takepic
処理内容はシンプル。が、マイコンボードに移して稼働確認する時に何か起こりそう
import cv2
import os
import glob
import datetime
def take_pic():
dt_now = datetime.datetime.now()
file_name = dt_now.strftime('%Y%m%d%M%S%f')
# フォルダ初期化
file_list = glob.glob('./image_raw/*')
for file in file_list:
os.remove(file)
# front
video_capture = cv2.VideoCapture(1)
# back(フロントカメラとバックカメラで繋ぎ先が異なる。今回はフロントカメラでテスト)
# video_capture = cv2.VideoCapture(0)
ret, img = video_capture.read()
if ret == True:
cv2.imwrite('./image_raw/raw_' + file_name + '.jpg', img)
return True
extract_face
azureからFaceAPIの設定をクイックスタート通りに設定
マイコンボードでAzure用のモジュールが動けばAPIを叩くだけの処理
import glob
import os
import cv2
from azure.cognitiveservices.vision.face import FaceClient
from msrest.authentication import CognitiveServicesCredentials
# AzureAPIに写真を送り、顔の部分を取得する
KEY = "PASTE_YOUR_FACE_SUBSCRIPTION_KEY_HERE"
ENDPOINT = "PASTE_YOUR_FACE_ENDPOINT_HERE"
face_client = FaceClient(ENDPOINT, CognitiveServicesCredentials(KEY))
def fetch_face_and_info():
img_file = glob.glob('./image_raw/*.jpg')
image_raw_path = img_file[0]
single_image_name = os.path.basename(image_raw_path)
img = open(image_raw_path, 'r+b')
img_org = cv2.imread(image_raw_path)
# モデルを選択できるようになっている。精度が出ないとき、調整の余地があるということか、、
detected_faces = face_client.face.detect_with_stream(
img, detection_model='detection_03', return_face_landmarks=True)
if not detected_faces:
raise Exception(
'No face detected from image {}'.format(single_image_name))
# img_faceフォルダのクリア
file_list = glob.glob('./image_face/*')
for file in file_list:
os.remove(file)
for face in detected_faces:
cv2.imwrite('./image_face/' + face.face_id + '.jpg',
img_org[face.face_rectangle.top: face.face_rectangle.top + face.face_rectangle.height,
face.face_rectangle.left: face.face_rectangle.left + face.face_rectangle.width])
# face_idの保存。同一人物判定に使用する
with open('./face_info/face_info.txt', 'a') as f:
for info in detected_faces:
f.write(info.face_id)
f.write('\n')
return True
judge_mask
Lobeが出力したサンプルスクリプトをcontrolから呼び出せるように改修。
写真を投入して判定結果を返す
import tflite_example
import glob
def judge_mask_ctrl():
file_path = glob.glob('./image_raw/*.jpg')
if len(file_path) > 0:
tflite_example.judge_mask(file_path[0])
return True, tflite_example.judge_mask(file_path[0])
else:
return False
出力されたサンプルコードにコードを追加して呼び出せるように改修
def judge_mask(file_path):
model_dir = os.path.join(os.getcwd(), "..")
if os.path.isfile(file_path):
image = Image.open(file_path)
model = TFLiteModel(model_dir)
model.load()
outputs = model.predict(image)
print(f"Predicted: {outputs}")
return outputs
else:
print(f"Couldn't find image file")
return False
speak_judge
マスク着用は判定されているので、同一人物の判定を行い出力内容を決定する
from azure.cognitiveservices.vision.face import FaceClient
from msrest.authentication import CognitiveServicesCredentials
KEY = "PASTE_YOUR_FACE_SUBSCRIPTION_KEY_HERE"
ENDPOINT = "PASTE_YOUR_FACE_ENDPOINT_HERE"
face_client = FaceClient(ENDPOINT, CognitiveServicesCredentials(KEY))
def judge_similarity():
# face_infoから最後の2件のidを取り出し、同じ人か確認
face_id_list = []
with open('./face_info/face_info.txt', 'r') as f:
face_id_list = f.read().split('\n')
face_id_list.pop()
if len(face_id_list) < 2:
print('not enough data to check similarity')
return False
else:
face_list = []
face_list.append(face_id_list[len(face_id_list)-2])
similar_faces = face_client.face.find_similar(face_id=face_id_list[len(
face_id_list)-1], face_ids=face_list)
if similar_faces[0].confidence < 0.9:
print('No similar faces found in', face_id_list[len(
face_id_list)-1], face_id_list[len(face_id_list)-2], '.')
return False
return True
def speak_judge(process_control, judge_m):
ret = judge_similarity()
if ret is False:
# 前回と同一人物ではないか十分なデータがない
if judge_m == 'Mask':
return('Congra')
else:
return('FirstAndUnMask')
else:
# 前回と同一人物
if judge_m == 'Mask':
return('Congra')
else:
return('SameAndUnMask')
speak_out
決定に従って音声ファイルを再生する
処理自体は超シンプルだが、マイコンボードから音を出すときにドライバーとかモジュールで困難がありそう。
出力する内容は音読さんで作成し、wavファイルに変換しておく
import os
from playsound import playsound
def speak_out_message(str):
playsound('./message_file/' + str + '.wav')
return True
全体的にブロックを積み上げて、繋ぎのところちょっと作ったイメージ。
判定処理はすべてありものを使っている。改めて見てみるとすべてMicrosoftのプロダクト。
それが無料で使えるようになっているとは、、すごい世界になったものだ。
確認とこのあと
前回のcontrol.pyを実行するとsufaceのカメラがちらっと動いて判定結果に応じた音声ファイルを再生する。
エラー処理やログ出力がないとかは置いておいて、マイコンボードを調達して環境を再現してみる。
動くことは確認できているので、マイコンボード上で何があっても迷いなく対応できる( ´艸`)