# -*- coding: utf-8 -*-
##------------------------------------------
## Reception System Ver 0.03
## with face recognition
## platform: linux / windows
##
## 2022.10.05 Masahiro Izutsu
##------------------------------------------
## reception.py (face_rec4.py ver 0.04 2022.09.15)
## ver 0.03 2022.11.09 ドア制御/同一認識フレーム数・記録制限秒数ファイル化
# import処理
import cv2
import numpy as np
import face_recognition
import cvui
import os
import argparse
import my_logging
from my_print import printG, printR, printY, printC, printB, printN
import my_puttext
import my_csv
import my_file
import my_winstat
import my_fps
import my_datetime
import my_movedlg
import my_dialog
import my_process
import face_rec_yaml
import door_ctrl
import rec_result
# 定数定義
title = 'Reception System Ver 0.03'
IMAGE_EXT = {'.bmp', '.png', '.jpeg', '.jpg', '.JPG', '.tif'}
ATTEND_LOG = 'attend.csv' # 記録ファイル名
STATUS_H = 40 # ステータスラインの高さ
STATUS_LV = 200 # ステータスラインの背景レベル
INPUT_IMAGE_DEF = 'cam' # 入力イメージ・パラメータ初期値
# 入力パラメータの定義
# -o 出力ファイルパス(出力ファイル指定) 'xxxx/xxxxxx.xxx' フォルダは存在していること
# 静止画ファイルの拡張子 '.jpg 動画ファイルは '.mp4'
#
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--input', metavar = 'INPUT_IMAGE', type=str, default = INPUT_IMAGE_DEF,
help = 'Absolute path to image file or cam for camera stream.'
'Default value is \'cam\'')
parser.add_argument('-m', '--mode', metavar = 'ACTION_MODE', type=str, default = '1',
help = 'Action mode (0/1/2/3) Default value is \'1\'')
parser.add_argument('-o', '--out', metavar = 'IMAGE_OUT', default = 'non',
help = 'Processed image file path. Default value is \'non\'')
return parser
# 入力パラメータの表示
def display_info(input_str, facefol, action_mode, toler, log, titleflg, speedflg, outpath):
printG(f' - Program title : {title}')
printG(f' - OpenCV version : {cv2.__version__}')
printY(f' - Input image : {input_str}')
printY(f' - Face Folder : {facefol}')
printY(f' - Action mode : {action_mode}')
printY(f' - tolerance : {toler}')
printY(f' - Log level : {log}')
printY(f' - Program Title : {titleflg}')
printY(f' - Speed flag : {speedflg}')
printY(f' - Processed out : {outpath}')
# 128次元の顔エンコーディングのリスト
def find_encodings(images):
encode_list = []
for img in images:
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
encode = face_recognition.face_encodings(img)[0]
encode_list.append(encode)
return encode_list
# 顔の領域取得
# in: 画像イメージ (OpenCV)
# out: 顔の領域リスト (1/4サイズ座標)
#
def get_face_locations(img):
img0 = cv2.resize(img, (0, 0), None, 0.25, 0.25)
img0 = cv2.cvtColor(img0, cv2.COLOR_BGR2RGB)
face_frame = face_recognition.face_locations(img0)
return face_frame
# 顔検出記録
# in: attend_logfile 記録ファイル名
# name 検出した顔の名前
# logger ログ出力オブジェクト
# door 自動ドア制御オブジェクト
# out: 結果 (True/False)
#
def mark_attendance(attend_logfile, name, logger, door):
attend_dissec = face_rec_yaml.get_attend_disable_sec() # 記録制限秒数
result = False
encoding = 'utf_8_sig'
key = 'Name'
attime ='Time'
my_csv_treatment = my_csv.CSVtreatment(attend_logfile, encoding)
s = my_csv_treatment.read_csv()
if len(s) == 0: # 新規ファイル作成
data = [key, attime]
my_csv_treatment.write_csv(data)
time_now = my_datetime.now_strftime('%Y/%m/%d %H:%M:%S')
time = my_csv_treatment.read_csv_row_value(key, name, attime)
if time is None: # 記録なし
result = True
else: # 記録あり
result = my_datetime.time_check(time, time_now, attend_dissec)
if result:
data = [name, time_now]
my_csv_treatment.append_csv(data)
rec_result.recognition_result(name, time_now, logger, door)
return result
# 顔登録
# in: facefol 顔登録フォルダ
# match_name 一致した名前
# img 登録する顔のイメージ
# my_csv_treatment CSV リストファイルのオブジェクト
# logger ログ出力オブジェクト
# out: 登録フラグ
#
def face_registration(facefol, match_name, img, my_csv_treatment, logger):
list1, list2, list3 = my_csv_treatment.read_list3_csv()
file_path = my_datetime.now_strftime('%Y%m%d_%H%M%S') + '.jpg'
retf = True
savef = False
in1 = ''
in2 = ''
regf = False
for n in range(len(list2)): # 名前を検索
if list2[n] == match_name:
in1 = list2[n]
in2 = list3[n]
regf = True
break
ttle = f"'{file_path}'の登録"
msg = '登録する名前を入力してください。'
msg_r = ''
while(retf):
file_name, yomi = my_movedlg.input_dialog2(ttle, msg, text1 = 'お名前', text2 = 'フリガナ',init1 = in1, init2 = in2)
if file_name == None or len(file_name) == 0: # [X] ボタン キャンセル
msg_r = 'キャンセル'
retf = False # リトライ・ループ終了
break
# 登録名が入力された場合
retf = False # リトライ・ループ終了
row_data = [file_path, file_name, yomi] # 登録データ
if len(list1) <= 0:
msg_r = '初回登録'
my_csv_treatment.write_csv(row_data)
savef = True
else:
if regf:
if my_movedlg.yesno_dialog('TEST', '登録済みです。入れ替えますか?'):
msg_r = '入れ替え'
for n in range(len(list2)):
if list2[n] == file_name:
os.remove(f'{facefol}/{list1[n]}')
list1[n] = file_path
list3[n] = yomi
my_csv_treatment.write_list3_csv(list1, list2, list3)
savef = True
else:
msg_r = '再設定'
retf = True
else:
msg_r = '追加登録'
list1.insert(0, file_path)
list2.insert(0, file_name)
list3.insert(0, yomi)
my_csv_treatment.write_list3_csv(list1, list2, list3)
savef = True
if savef:
cv2.imwrite(f'{facefol}/{file_path}', img)
logger.debug(f'{msg_r}: {file_path} → {file_name}, 読み → {yomi}')
return savef
# 登録画像のリストアップ
# in: facefol 顔登録フォルダ
# my_file_treatment ファイル処理のオブジェクト
# my_csv_treatment CSV リストファイルのオブジェクト
# logger ログ出力オブジェクト
# out: face_names 登録された顔の名前(日本語)
# encode_list_known 登録された顔のエンコード・リスト
#
def get_encode_list(facefol, my_file_treatment, my_csv_treatment, logger):
face_images = [] # 登録画像のイメージリスト
face_names = [] # 登録画像の名前リスト(日本語名)
facelist = my_file_treatment.get_file_list_sel(f'{facefol}/*', IMAGE_EXT)
fname, jname = my_csv_treatment.read_list2_csv()
for reg_face in facelist:
current_img = cv2.imread(reg_face)
face_images.append(current_img)
logger.debug(f"'{reg_face}' read <{facelist is not None}>")
f = os.path.basename(reg_face)
s = os.path.splitext(f)[0]
# 日本語の登録名を設定する
n = len(fname)
if n > 0:
for i in range(n):
if f == fname[i]:
s = jname[i]
break
face_names.append(s)
logger.debug(f'face list: {face_names}')
encode_list_known = find_encodings(face_images)
logger.debug(f'Find {len(encode_list_known)} face registration images !!')
return face_names, encode_list_known
# 表示画像のキャプチャー
# in: logger ログ情報オブジェクト
# face_cap 表示フレーム
# window_cap キャプチャー・ウインドウ名
# out: save_flg キャプチャー・フラグ
# frame_cap_still キャプチャー・画像イメージ
#
def face_capture(logger, frame_cap, window_cap):
img_w = frame_cap.shape[1]
img_h = frame_cap.shape[0]
logger.debug("'Save' button pushed !!")
frame_cap_still = frame_cap.copy() # 静止画フレーム
frame_cap_disp = frame_cap.copy() # 表示画像
face_fr = get_face_locations(frame_cap_still)
if len(face_fr) > 0:
save_flg = True
# 顔の検出領域表示
for face in face_fr:
y1, x2, y2, x1 = face
y1, x2, y2, x1 = y1*4, x2*4, y2*4, x1*4
cv2.rectangle(frame_cap_disp, (x1, y1), (x2, y2), (0, 0, 255), 1)
else:
x = int(img_w/2) - 100
y = int(img_h/2) - 50
cv2.rectangle(frame_cap_disp, (x, y), (x+100, y+ 40), (0, 0, 255), -1)
my_puttext.cv2_putText(frame_cap_disp, '顔が検出できません !!', (x + 12, y + 30), fontFace, 16, (255, 255, 255), 0)
save_flg = False
cv2.namedWindow(window_cap, flags=cv2.WINDOW_AUTOSIZE | cv2.WINDOW_GUI_NORMAL)
cv2.moveWindow(window_cap, img_w + 100, 0)
cv2.imshow(window_cap, frame_cap_disp)
return save_flg, frame_cap_still
# ** main関数 **
def main():
# 日本語フォント指定
fontFace = my_puttext.get_font()
# 入力パラメータの処理
ARGS = parse_args().parse_args()
input_str = ARGS.input
action_mode = int(ARGS.mode)
outpath = ARGS.out
# アプリケーション設定値
facefol = face_rec_yaml.get_facefolder() # 登録画像フォルダパス
toler = face_rec_yaml.get_tolerance() # 認証しきい値 (0.0〜1.0)文字列
titleflg = face_rec_yaml.get_titleflg() # タイトル表示 (y/n
speedflg = face_rec_yaml.get_speedflg() # F.P.S.表示 (y/n)
uart_enbl = face_rec_yaml.get_uart_enable() # UART 許可 (自動ドア制御)
uart_port = face_rec_yaml.get_uart_port() # UART ポート
logsel = face_rec_yaml.get_loglevel() # ログ表示レベル (-1/0/1/2/3/4/5)
face_list = face_rec_yaml.get_face_list() # 登録リストファイル
attend_count = face_rec_yaml.get_attend_count() # 同一認識フレーム数
# ファイル処理クラスのインスタンス
my_file_treatment = my_file.FileTreatment(logsel)
my_csv_treatment = my_csv.CSVtreatment(f'{facefol}/{face_list}', 'utf_8_sig', logsel)
# 入力ソースの違いによる前処理
if input_str == '0':
input_str = my_dialog.select_image_movie_file()
if len(input_str) <= 0:
printR('Program canceled.')
return 0
input_stream = input_str
if input_str.lower() == "cam" or input_str.lower() == "camera":
input_stream = 0
isstream = True
else:
filetype = my_file_treatment.is_pict(input_stream)
isstream = filetype == 'None'
if (filetype == 'NotFound'):
printR(f"'{input_stream}': Input file Not found.")
return 0
if isstream and outpath != 'non' and os.path.splitext(outpath)[1] != '.mp4':
printR(f"'{outpath}': Output file type is '.mp4'")
return 0
# 記録ファイル名
s = input_str if input_stream == 0 else os.path.basename(input_str)
s = s.replace('.','_')
attend_logfile = f'{s}_{ATTEND_LOG}'
# アプリケーション・ログ設定
module = os.path.basename(__file__)
module_name = os.path.splitext(module)[0]
logger = my_logging.get_module_logger_sel(module_name, logsel)
logger.info('Starting..')
# 情報表示
display_info(input_str, facefol, action_mode, toler, logsel, titleflg, speedflg, outpath)
# 自動ドア制御オブジェクト生成
door = door_ctrl.Door()
if uart_enbl == 'Yes':
ser = door.set_port(uart_port)
if ser is None:
printR(f"'{uart_port}' port not found.")
else:
printG(f"'{uart_port}' port ready.")
# 登録画像のリストアップ
face_names, encode_list_known = get_encode_list(facefol, my_file_treatment, my_csv_treatment, logger)
# 関数内パラメータ
window_name = title + " (hit 'q' or 'esc' key to exit)"
window_cap = 'Capture window'
inface_count = 0 # フレーム内に検出した顔の数
match_name = '' # 一致した名前
match_count = 0 # 連続で一致した回数
facerec_flg = False # 顔検出フラグ
save_flg = False # 登録フラグ
frame_cap_still = None # 静止画フレーム
# 入力準備
if (isstream):
# カメラ
cap = cv2.VideoCapture(input_stream)
success, img_frame = cap.read()
if success == False:
logger.error('camera read error !!')
loopflg = cap.isOpened()
img_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
img_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
else:
# 画像ファイル読み込み
img_frame = cv2.imread(input_stream)
if img_frame is None:
logger.error('unable to read the input.')
return 0
# アスペクト比を固定してリサイズ(スクリーンに収まるサイズ)
h, w = my_movedlg.get_display_size()
mx = h - 10 if h > w else w - 10
img_frame = my_process.frame_resize(img_frame, mx)
loopflg = True # 1回ループ
img_width = img_frame.shape[1]
img_height = img_frame.shape[0]
# 画面ステータス領域 (画面下部 STATUS_H pixel)の確保
y = STATUS_H if action_mode > 1 else 0
frame = np.zeros((img_height + y, img_width, 3), np.uint8)
frame[:,:,:] = STATUS_LV # 背景色 (200, 200, 200)
btn_x, btn_y = 40, img_height + 6 # 'Save'ボタン位置
btn_w, btn_h = 70, 32 # ボタン 幅/高さ
# 顔撮影位置(action_mode = 3)
x = int(img_width/8)
y = int(img_height/8)
face_x0, face_y0, face_x1, face_y1 = x*3, y*2, x*5, y*5
# ウインドウ初期設定
cv2.namedWindow(window_name, flags=cv2.WINDOW_AUTOSIZE | cv2.WINDOW_GUI_NORMAL)
cv2.moveWindow(window_name, 20, 0)
cvui.init(window_name)
# 処理結果の記録 step1
if (outpath != 'non'):
if (isstream):
fps = int(cap.get(cv2.CAP_PROP_FPS))
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
outvideo = cv2.VideoWriter(outpath, fourcc, fps, (img_width, img_height))
# 計測値初期化
fpsWithTick = my_fps.fpsWithTick()
frame_count = 0
fps_total = 0
fpsWithTick.get() # fps計測開始
# メインループ
while (loopflg):
if img_frame is None:
logger.error('unable to read the input.')
return 0
# フレーム(img_frame)内の顔検出
frame_cap = img_frame.copy() # 現在のフレームを保存
img_resize = cv2.resize(img_frame, (0, 0), None, 0.25, 0.25)
img_resize = cv2.cvtColor(img_resize, cv2.COLOR_BGR2RGB)
face_frame = face_recognition.face_locations(img_resize)
encode_frame = face_recognition.face_encodings(img_resize, face_frame)
# 画面上部に画像を配置
frame[0:img_height,:] = img_frame
frame[img_height:,:,:] = STATUS_LV
# 検出した顔の領域表示
inface_count = len(face_frame)
c = ( 0,102, 51) if inface_count > 0 else (71, 99, 255)
s = f'face:{inface_count:2}'
cv2.rectangle(frame, (10, 42), (68, 59), c, -1)
cv2.putText(frame, s, (15, 54), cv2.FONT_HERSHEY_DUPLEX, fontScale=0.4, color=(255, 255, 255), lineType=cv2.LINE_AA)
for encode_face, face_loc in zip(encode_frame, face_frame):
# フレーム内に顔が検出された場合
matches = face_recognition.compare_faces(encode_list_known, encode_face, tolerance=float(toler))
face_dis = face_recognition.face_distance(encode_list_known, encode_face)
logger.debug(f'count: {match_count:03} distance: {face_dis}')
match_idx = np.argmin(face_dis)
if matches[match_idx]:
name = face_names[match_idx].upper()
color = (102, 102, 0)
else:
name = '未登録'
color = (71, 99, 255)
if match_name == '':
match_name = name
if match_name != name:
match_name = ''
match_count = 0
elif match_count < 500:
match_count = match_count + 1
if match_count == attend_count:
if name == '未登録':
logger.debug("Detect unknown faces !!")
if action_mode == 1:
save_flg, frame_cap_still = face_capture(logger, frame_cap, window_cap)
# 顔登録
if save_flg and face_registration(facefol, match_name, frame_cap_still, my_csv_treatment, logger):
# 登録画像の再リストアップ
face_names, encode_list_known = get_encode_list(facefol, my_file_treatment, my_csv_treatment, logger)
cv2.destroyWindow(window_cap)
save_flg = False
match_name = ''
match_count = 0
elif action_mode < 2:
result = mark_attendance(attend_logfile, name, logger, door) # 名前登録
logger.debug(f'Mark attendancs !! {result}')
# 顔の検出領域の処理
y1, x2, y2, x1 = face_loc
y1, x2, y2, x1 = y1*4, x2*4, y2*4, x1*4
cv2.rectangle(frame, (x1, y1-30), (x2, y1), color, cv2.FILLED)
cv2.rectangle(frame, (x1, y1), (x2, y2), color, 2)
my_puttext.cv2_putText(frame, name, (x1+6, y1-6), fontFace, 16, (255, 255, 255), 0)
if inface_count == 1:
# フレーム内に顔が一つの場合
if action_mode == 3:
facerec_flg = True if x1 < face_x0 and y1 < face_y0 and x2 > face_x1 and y2 > face_y1 else False
else:
facerec_flg = True
elif inface_count <= 0:
# フレーム内に顔が検出できない場合
logger.debug("Face can't be detected !!")
match_name = ''
match_count = 0
facerec_flg = False
elif inface_count > 1:
# フレーム内に顔が2つ以上ある場合
facerec_flg = False
# FPSを計算する
fps = fpsWithTick.get()
st_fps = 'fps: {:>6.2f}'.format(fps)
if (speedflg == 'y'):
cv2.rectangle(frame, (80, 42), (165, 59), (90, 90, 90), -1)
cv2.putText(frame, st_fps, (85, 54), cv2.FONT_HERSHEY_DUPLEX, fontScale=0.4, color=(255, 255, 255), lineType=cv2.LINE_AA)
# タイトル描画
if (titleflg == 'y'):
cv2.putText(frame, title, (12, 32), cv2.FONT_HERSHEY_DUPLEX, fontScale=0.8, color=(0, 0, 0), lineType=cv2.LINE_AA)
cv2.putText(frame, title, (10, 30), cv2.FONT_HERSHEY_DUPLEX, fontScale=0.8, color=(200, 200, 0), lineType=cv2.LINE_AA)
# 顔撮影位置表示
if action_mode == 3:
cv2.rectangle(frame, (face_x0, face_y0), (face_x1, face_y1), (0, 0, 255), 1)
# -----------------------------------------
# ステータスライン・イベント処理
if (isstream and action_mode > 1):
# 'Save' ボタン・イベント処理
if facerec_flg:
if cvui.button(frame, btn_x, btn_y, "&Save"):
logger.debug("'Save' button pushed !!")
save_flg, frame_cap_still = face_capture(logger, frame_cap, window_cap)
# 'Name' ボタン・イベント処理
if save_flg and my_winstat._is_visible(window_cap):
if cvui.button(frame, btn_x + btn_w + 10, btn_y, "&Name"):
logger.debug("'Name' button pushed !!")
# 顔登録
if input_str == 'cam' and face_registration(facefol, match_name, frame_cap_still, my_csv_treatment, logger):
# 登録画像の再リストアップ
face_names, encode_list_known = get_encode_list(facefol, my_file_treatment, my_csv_treatment, logger)
cv2.destroyWindow(window_cap)
save_flg = False
# -----------------------------------------
# ウインドウの更新/画像表示
cvui.update()
cv2.imshow(window_name, frame)
# 処理結果の記録 step2
if (outpath != 'non'):
if (isstream):
outvideo.write(frame)
else:
cv2.imwrite(outpath, frame)
# 何らかのキーが押されたら終了
breakflg = False
while(True):
key = cv2.waitKey(1) # (カメラ・アクセス速度調整)
if key == 27 or key == 113: # 'esc' or 'q'
breakflg = True
break
if not my_winstat._is_visible(window_name): # 'Close' button
breakflg = True
break
if (isstream):
break
if ((breakflg == False) and isstream):
# 次のフレームを読み出す
success, img_frame = cap.read()
if success == False: # 動画終了
break
loopflg = cap.isOpened()
else:
loopflg = False
# 終了処理
if (isstream):
cap.release()
# 処理結果の記録 step3
if (outpath != 'non'):
if (isstream):
outvideo.release()
cv2.destroyAllWindows()
if uart_enbl == 'Yes':
door.finish()
printC('FPS average: {:>10.2f}'.format(fpsWithTick.get_average()))
logger.info('Finished.\n')
# main関数エントリーポイント(実行開始)
if __name__ == "__main__":
main()
# -*- coding: utf-8 -*-
##------------------------------------------
## Face Recognition Setting ver 0.03
## platform: linux / windows
##
## 2022.09.16 Masahiro Izutsu
##------------------------------------------
## face_rec_yaml.py
## ver 0.02 2022.10.14 FACE_LISTキー追加
## ver 0.03 2022.11.09 KEY_ATTEND_COUNT/KEY_ATTEND_DSECキー追加
from os.path import expanduser
import my_yaml
# 定数定義
FACE_YAML_PATH = expanduser('./face_rec.yaml') # 設定ファイルパス
FACE_REC_SET = '.FaceRec' # セクション名: Face Recognition
UART_SET = 'UARTport' # UART
JTALK_SET = 'JTalkVoice' # OpenJTalk
MAIL_SET = 'MailServer' # SMTPサーバー
KEY_ACCOUNT = 'account' # キー名: アカウント
KEY_PASSWORD = 'password' # パスワード
KEY_HOST = 'host' # ホスト・サーバー
KEY_PORT = 'port' # ポート
KEY_FROM = 'from' # 送信元
KEY_TO ='to' # 送信先
KEY_VOICE = 'voice' # 音声選択 (0-5)
KEY_ENABLE = 'enable' # 許可 (Yes/No)
KEY_FACE_FOLDER = 'FaceFolder' # 登録画像フォルダパス
KEY_TOLERANCE = 'tolerance' # 認証しきい値 (0.0〜1.0)文字列
KEY_TILE_FLG = 'TitleDisp' # タイトル表示 (y/n)
KEY_SPEED_FLG = 'SpeedSisp' # F.P.S.表示 (y/n)
KEY_LOGSELECT = 'Loglevel' # ログ表示レベル (-1/0/1/2/3/4/5)
KEY_FACE_LIST = 'FaceList' # 登録リストファイル
KEY_ATTEND_COUNT = 'AttendCount' # 同一認識フレーム数
KEY_ATTEND_DSEC = 'AttendDisSec' # 記録制限秒数
# 初期設定ファイル・オブフェクト
myyaml = my_yaml.YamlProcess(FACE_YAML_PATH)
# 設定値読み出し
def get_facefolder():
return myyaml.load_section_key(FACE_REC_SET, KEY_FACE_FOLDER)
def get_tolerance():
return myyaml.load_section_key(FACE_REC_SET, KEY_TOLERANCE)
def get_titleflg():
return myyaml.load_section_key(FACE_REC_SET, KEY_TILE_FLG)
def get_speedflg():
return myyaml.load_section_key(FACE_REC_SET, KEY_SPEED_FLG)
def get_loglevel():
return myyaml.load_section_key(FACE_REC_SET, KEY_LOGSELECT)
def get_face_list():
return myyaml.load_section_key(FACE_REC_SET, KEY_FACE_LIST)
def get_attend_count():
return myyaml.load_section_key(FACE_REC_SET, KEY_ATTEND_COUNT)
def get_attend_disable_sec():
return myyaml.load_section_key(FACE_REC_SET, KEY_ATTEND_DSEC)
def get_uart_enable():
return myyaml.load_section_key(UART_SET, KEY_ENABLE)
def get_uart_port():
return myyaml.load_section_key(UART_SET, KEY_PORT)
def get_jtalk_enable():
return myyaml.load_section_key(JTALK_SET, KEY_ENABLE)
def get_jtalk_voice():
return myyaml.load_section_key(JTALK_SET, KEY_VOICE)
def get_mail_enable():
return myyaml.load_section_key(MAIL_SET, KEY_ENABLE)
def get_mail_account():
return myyaml.load_section_key(MAIL_SET, KEY_ACCOUNT)
def get_mail_password():
return myyaml.load_section_key(MAIL_SET, KEY_PASSWORD)
def get_mail_host():
return myyaml.load_section_key(MAIL_SET, KEY_HOST)
def get_mail_port():
return myyaml.load_section_key(MAIL_SET, KEY_PORT)
def get_mail_from():
return myyaml.load_section_key(MAIL_SET, KEY_FROM)
def get_mail_to():
return myyaml.load_section_key(MAIL_SET, KEY_TO)
# 設定値書き込み
def set_facefolder(facefol):
myyaml.write_append_key(FACE_REC_SET, KEY_FACE_FOLDER, facefol)
def set_tolerance(toler):
myyaml.write_append_key(FACE_REC_SET, KEY_TOLERANCE, toler)
def set_titleflg(titleflg):
myyaml.write_append_key(FACE_REC_SET, KEY_TILE_FLG, titleflg)
def set_speedflg(speedflg):
myyaml.write_append_key(FACE_REC_SET, KEY_SPEED_FLG, speedflg)
def set_loglevel(logsel):
myyaml.write_append_key(FACE_REC_SET, KEY_LOGSELECT, logsel)
def set_face_list(face_list):
myyaml.write_append_key(FACE_REC_SET, KEY_FACE_LIST, face_list)
def set_attend_count(attend_count):
myyaml.write_append_key(FACE_REC_SET, KEY_ATTEND_COUNT, attend_count)
def set_attend_disable_sec(attend_dissec):
myyaml.write_append_key(FACE_REC_SET, KEY_ATTEND_DSEC, attend_dissec)
def set_uart_enable(enbl):
myyaml.write_append_key(UART_SET, KEY_ENABLE, enbl)
def set_uart_port(port):
myyaml.write_append_key(UART_SET, KEY_PORT, port)
def set_jtalk_enable(enbl):
myyaml.write_append_key(JTALK_SET, KEY_ENABLE, enbl)
def set_jtalk_voice(voice):
myyaml.write_append_key(JTALK_SET, KEY_VOICE, voice)
def set_mail_enable(enbl):
myyaml.write_append_key(MAIL_SET, KEY_ENABLE, enbl)
def set_mail_account(account):
myyaml.write_append_key(MAIL_SET, KEY_ACCOUNT, account)
def set_mail_password(password):
myyaml.write_append_key(MAIL_SET, KEY_PASSWORD, password)
def set_mail_host(host):
myyaml.write_append_key(MAIL_SET, KEY_HOST, host)
def set_mail_port(port):
myyaml.write_append_key(MAIL_SET, KEY_PORT, port)
def set_mail_from(from_email):
myyaml.write_append_key(MAIL_SET, KEY_FROM, from_email)
def set_mail_to(to_email):
myyaml.write_append_key(MAIL_SET, KEY_TO, to_email)
#-----Test routine-----
# $ python3 face_list.py
#
if __name__ == "__main__":
# 設定を書き込む
import platform
facefol = 'face_img' # face_rec
set_facefolder(facefol)
toler = '0.5'
set_tolerance(toler)
titleflg = 'y'
set_titleflg(titleflg)
speedflg = 'y'
set_speedflg(speedflg)
logsel = 3
set_loglevel(logsel)
face_list = 'facelist.txt'
set_face_list(face_list)
attend_count = 10
set_attend_count(attend_count)
attend_dissec = 20
set_attend_disable_sec(attend_dissec)
enbl = 'No' # UART
set_uart_enable(enbl)
port = 'COM3' if platform.system()=='Windows' else '/dev/ttyUSB0'
set_uart_port(port)
enbl = 'Yes' # OpenJTalk
set_jtalk_enable(enbl)
voice = 0
set_jtalk_voice(voice)
enbl = 'No' # SMTP server
set_mail_enable(enbl)
account = 'aipromotion999@gmail.com'
set_mail_account(account)
password = 'emhu kdvo pkby txxc'
set_mail_password(password)
host = 'smtp.gmail.com'
set_mail_host(host)
port = 465
set_mail_port(port)
from_email = 'aipromotion999@gmail.com'
set_mail_from(from_email)
to_email = 'izutsum-sp@docomo.ne.jp'
set_mail_to(to_email)
# 設定を読み出す
facefol = get_facefolder()
print(f"Read '{FACE_REC_SET}' '{KEY_FACE_FOLDER}' : '{facefol}'", type(facefol))
toler = get_tolerance()
print(f"Read '{FACE_REC_SET}' '{KEY_TOLERANCE}' : '{toler}'", type(toler))
titleflg = get_titleflg()
print(f"Read '{FACE_REC_SET}' '{KEY_TILE_FLG}' : '{titleflg}'", type(titleflg))
speedflg = get_speedflg()
print(f"Read '{FACE_REC_SET}' '{KEY_SPEED_FLG}' : '{speedflg}'", type(speedflg))
logsel = get_loglevel()
print(f"Read '{FACE_REC_SET}' '{KEY_LOGSELECT}' : '{logsel}'", type(logsel))
face_list = get_face_list()
print(f"Read '{FACE_REC_SET}' '{KEY_FACE_LIST}' : '{face_list}'", type(face_list))
attend_count = get_attend_count()
print(f"Read '{FACE_REC_SET}' '{KEY_ATTEND_COUNT}' : '{attend_count}'", type(attend_count))
attend_dissec = get_attend_disable_sec()
print(f"Read '{FACE_REC_SET}' '{KEY_ATTEND_DSEC}' : '{attend_dissec}'", type(attend_dissec))
enbl = get_uart_enable()
print(f"Read '{UART_SET}' '{KEY_ENABLE}' : '{enbl}'", type(enbl))
port = get_uart_port()
print(f"Read '{UART_SET}' '{KEY_PORT}' : '{port}'", type(port))
enbl = get_jtalk_enable()
print(f"Read '{JTALK_SET}' '{KEY_ENABLE}' : '{enbl}'", type(enbl))
voice = get_jtalk_voice()
print(f"Read '{JTALK_SET}' '{KEY_VOICE}' : '{voice}'", type(voice))
enbl = get_mail_enable()
print(f"Read '{MAIL_SET}' '{KEY_ENABLE}' : '{enbl}'", type(enbl))
account = get_mail_account()
print(f"Read '{MAIL_SET}' '{MAIL_SET}' : '{account}'", type(account))
password = get_mail_password()
print(f"Read '{MAIL_SET}' '{KEY_PASSWORD}' : '{password}'", type(password))
host = get_mail_host()
print(f"Read '{MAIL_SET}' '{KEY_HOST}' : '{host}'", type(host))
port = get_mail_port()
print(f"Read '{MAIL_SET}' '{KEY_PORT}' : '{port}'", type(port))
from_email = get_mail_from()
print(f"Read '{MAIL_SET}' '{KEY_FROM}' : '{from_email}'", type(from_email))
to_email = get_mail_to()
print(f"Read '{MAIL_SET}' '{KEY_TO}' : '{to_email}'", type(to_email))
# -*- coding: utf-8 -*-
##------------------------------------------
## Face Recognition result ver 0.03
## ~顔認証結果の処理サンプル~
## platform: linux / windows
##
## 2022.09.14 Masahiro Izutsu
##------------------------------------------
## rec_result.py
## ver 0.02 2022.10.14 facelistファイル名を設定ファイルで指定
## ver 0.03 2022.11.09 ドア制御/同一認識フレーム数・記録制限秒数ファイル化
import my_csv
import platform
import datetime
import my_mail
import face_rec_yaml
if platform.system()=='Windows':
import jtalkw as jtalk
else:
import jtalk
def get_kana(name):
facefol = face_rec_yaml.get_facefolder() # 登録画像フォルダパス
face_list = face_rec_yaml.get_face_list() # 登録リストファイル
my_csv_treatment = my_csv.CSVtreatment(f'{facefol}/{face_list}')
list1, list2, list3 = my_csv_treatment.read_list3_csv()
kana = ''
n = len(list1)
if n > 0 and len(list2) > 0 and len(list3) > 0:
for i in range(n):
if name == list2[i]:
kana = list3[i]
break
return kana
def get_speak_string(name):
kana = get_kana(name)
if len(kana) == 0:
kana = name
s = f'{kana}様 いらっしゃいませ' if len(kana) > 0 else ''
return s
def speak_welcom(name, voice = 0, waitf = False):
s = get_speak_string(name)
jtalk.jtalk(s, voice, waitf)
# 顔認証結果の処理(例)
# in: name 顔認証した名前
# time 顔認証した時刻
# logger ログ出力オブジェクト
# door 自動ドア制御オブジェクト
#
def recognition_result(name, time, logger, door):
import socket
hostname = socket.gethostname()
# 受付音声
jtalk_enbl = face_rec_yaml.get_jtalk_enable() # JTalk 許可フラグ
voice = face_rec_yaml.get_jtalk_voice()
s = get_speak_string(name)
logger.debug(s)
if jtalk_enbl == 'Yes':
jtalk.jtalk(s, voice, True)
# 自動ドア開閉
uart_enbl = face_rec_yaml.get_uart_enable() # UART 許可フラグ
uart_port = face_rec_yaml.get_uart_port() # UART ポート
if uart_enbl == 'Yes':
ser = door.get_port()
if ser is None:
logger.info(f"'{uart_port}' port not found.")
else:
logger.info(f"'{uart_port}' port ready. Door open !!")
door.open_close() # 自動ドア開閉 !!!
d = datetime.datetime.strptime(time, '%Y/%m/%d %H:%M:%S')
s = '%s月%s日、%s時%s分%s秒' % (d.month, d.day, d.hour, d.minute, d.second)
logger.debug(s)
if jtalk_enbl == 'Yes':
jtalk.jtalk(s, voice)
# メール送信
mail_enbl = face_rec_yaml.get_mail_enable() # メール送信許可フラグ
logger.debug(f"e-mail : '{mail_enbl}'\n")
if mail_enbl == 'Yes':
account = face_rec_yaml.get_mail_account()
password = face_rec_yaml.get_mail_password()
host = face_rec_yaml.get_mail_host()
port = face_rec_yaml.get_mail_port()
from_email = face_rec_yaml.get_mail_from()
to_email = face_rec_yaml.get_mail_to()
logger.debug(f"send e-mail to : '{to_email}'")
subject = f'{time} : 受付'
message = f'{name} 様 来社です\nhostname : {hostname}\nfrom : {from_email}\nto : {to_email}'
logger.info(f"subject : '{subject}'")
logger.info(f"message : '{message}'")
mime = my_mail.createMIMEText(from_email, to_email, message, subject)
my_mail.send_email(mime, account, password, host, port)
#-----Test routine-----
# $ python3 face_list.py
#
if __name__ == "__main__":
import my_logging
import door_ctrl
logsel = 1
logger = my_logging.get_module_logger_sel(__name__, logsel)
door = door_ctrl.Door()
uart_port = face_rec_yaml.get_uart_port() # UART ポート
ser = door.set_port(uart_port)
recognition_result('桶川 秀次', '2022/9/15 9:15:01', logger, door)