LoginSignup
0
0

More than 1 year has passed since last update.

機械が言うと角が立たない3

Last updated at Posted at 2021-05-04

背景

前回からの続きです
ローカル環境でしゃべる所まで完成

何をする

これも前回からの続きです

各処理の内容を作ってゆく

処理を以下の順番に実行する

  1. takepic
    カメラを使って写真を撮る
  2. extract_face
    写真の中から顔を抜き出す
  3. judge_mask
    マスクをしているか否か判定
  4. speak_judge
    判定内容に合わせてしゃべる内容を決定
  5. 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

処理内容はシンプル。が、マイコンボードに移して稼働確認する時に何か起こりそう

takepic.py
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を叩くだけの処理

extract_face.py
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から呼び出せるように改修。
写真を投入して判定結果を返す

judge_mask.py
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

出力されたサンプルコードにコードを追加して呼び出せるように改修

tflight_example.py
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

マスク着用は判定されているので、同一人物の判定を行い出力内容を決定する

speak_judge.py
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ファイルに変換しておく

speak_out.py
import os
from playsound import playsound
def speak_out_message(str):
    playsound('./message_file/' + str + '.wav')
    return True

全体的にブロックを積み上げて、繋ぎのところちょっと作ったイメージ。
判定処理はすべてありものを使っている。改めて見てみるとすべてMicrosoftのプロダクト。
それが無料で使えるようになっているとは、、すごい世界になったものだ。

確認とこのあと

前回のcontrol.pyを実行するとsufaceのカメラがちらっと動いて判定結果に応じた音声ファイルを再生する。
エラー処理やログ出力がないとかは置いておいて、マイコンボードを調達して環境を再現してみる。
動くことは確認できているので、マイコンボード上で何があっても迷いなく対応できる( ´艸`)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0