概略 FACE01 GRAPHICS
FACE01 GRAPHICSの概略を解説します。それぞれの詳しい説明は以下からご覧ください。
【ドキュメント】オプション変数・戻り値詳細 FACE01 GRAPHICS ver.1.2.8
目次
FACE01 GRAPHICS
Pythonやコマンドラインで顔検出、顔認識を行うライブラリです。オプションを指定することで様々な操作を可能にします。dlibを使用して構築されています。
FACE01 IMAGERと異なりNVIDIA製GPUカードを必要とします。GeForce 1660Tiを基準性能として調整してあります。
デモ
インストール
こちらからダウンロードします。FACE01 GRAPHICSはEXE版とPython版の2種類が存在します。
メリット | デメリット | |
EXE版 | Python実行環境を用意しなくて良い | 起動に少し時間がかかる |
Python版 | 起動が軽快 | Python実行環境を用意する必要がある |
Windows 10、Ubuntu 18.04.5に対応しています。
Python版にはPython実行環境が必要です。暗号化ライブラリPyArmorを使用している関係上Pythonは以下のバージョンを必要とします
- Ubuntu18.04版:Python3.6.9
- Windows10版:Python3.7.7
システム環境を汚したくない場合はpyenvを用います。詳細はこちらのページを参照して下さい。
shape_predictor_68_face_landmarks.dat
本番環境構築の際、shape_predictor_68_face_landmarks.datを東海顔認証が配布するものに差し替えることにより商用利用を可能にします。配布元のshape_predictor_68_face_landmarks.datは商用利用できません。ご注意下さい。
Python実行環境構築
EXE版には必要ありません
詳しくは以下のページをご参照下さい。
# Ubuntu版
## (必要な場合)pyenvによるPythonのバージョン合わせ
pyenv local 3.6.9
## venv仮想環境作成手順
python3 -m venv ./
## 仮想環境に入る
source ./bin/activate
## pip3アップデート
(****_UBUNTU_VENV) pip3 install -U pip ## 文末のpipはpip3ではなくpip
## pip3のバージョン確認
pip3 -V
## ライブラリ確認
(****_UBUNTU_VENV) pip3 freeze
## ライブラリ一括インストール
(****_UBUNTU_VENV) pip3 install -r requirements.txt (OR requirements_GRAPHICS_UBUNTU.txt)
## ライブラリ確認
(****_UBUNTU_VENV) pip3 freeze
# Windows版
## (必要な場合)pyenvによるPythonのバージョン合わせ
pyenv local 3.7.7
## venv仮想環境作成手順
## 仮想環境を作成する
python -m venv .\
## 仮想環境にはいる
>.\Scripts\activate
## pipアップデート
pip install -U pip
## ライブラリ一括インストール
>pip install -r requirements.txt
## ライブラリ確認
pip freeze
## requirementsの内容
dlib
face-recognition
face-recognition-models
numpy
opencv-python
Pillow
PySimpleGUI
使用方法
サンプルアプリケーションの使用方法は各々の備考欄に記載してあります。ここでは設定ファイルを用いる場合をいくつか例にとります。
設定ファイル作成
設定を行うためにはPythonスクリプト中にオプション変数を指定するかiniファイルを作成してスクリプト中から参照します。
スクリプト中にオプション変数を指定する例
スクリプト中にオプション変数を記入します。
from concurrent.futures import ThreadPoolExecutor
import cv2
import PySimpleGUI as sg
import FACE01GRAPHICS128 as fg
# オプション変数設定 ===============
# 指定した数値%以上を本人とする
similar_percentage=99.0
# 検出顔画像エンコーディング回数(変更非推奨)
jitters=0
# 登録顔画像エンコーディング回数
priset_face_images_jitters=100
# 顔検出面積(0: 80x80px, 1: 40x40px)
upsampling=0
# 深層学習モデルを使い顔検出('hog' or 'cnn')
mode='cnn'
# フレームドロップ指定(-1:自動)
frame_skip=-1
# 入力映像データ指定
movie='test.mp4'
# 入力映像に対して処理対象エリアを指定
set_area='NONE'
# 入力映像に対してリサイズする横幅指定
SET_WIDTH=600
# 顔領域にクラシックな枠を表示
rectangle=False
# 顔領域にモダンな枠を表示
target_rectangle=True
# opencv-pythonによるウィンドウの描画
show_video=False
# 顔領域の自動保存
crop_face_image=False
# 顔領域自動保存の頻度(フレーム数指定)
frequency_crop_image=80
# デフォルト顔画像の描画
default_face_image_draw=True
# 情報を半透明で表示
show_overlay=True
# 顔の下に%を表示
show_percentage=True
# 顔の下に名前を表示
show_name=False
# 入力映像データのプロパティを表示して終了
print_property=False
# 1フレーム処理にかかるミリ秒を標準出力
calculate_time=False
# 複数人検出された時に警告を出す
multiple_faces=True
# ウィンドウ下部に情報を表示
bottom_area=True
# ==================================
kaoninshoDir, priset_face_imagesDir=fg.home()
known_face_encodings, known_face_names=fg.load_priset_image(
kaoninshoDir,
priset_face_imagesDir,
jitters=priset_face_images_jitters,
)
xs=fg.face_attestation(
kaoninshoDir,
known_face_encodings,
known_face_names,
similar_percentage=similar_percentage,
jitters=jitters,
upsampling=upsampling,
mode=mode,
model='small',
frame_skip=frame_skip,
movie=movie,
rectangle=rectangle,
target_rectangle=target_rectangle,
show_video=show_video,
frequency_crop_image=frequency_crop_image,
set_area=set_area,
print_property=print_property,
calculate_time=calculate_time,
SET_WIDTH=SET_WIDTH,
default_face_image_draw=default_face_image_draw,
show_overlay=show_overlay,
show_percentage=show_percentage,
crop_face_image=crop_face_image,
show_name=show_name,
multiple_faces=multiple_faces,
bottom_area=bottom_area
)
layout = [
[sg.Image(filename='', key='cam1', pad=(0,0))],
[sg.Button('終了', key='terminate', pad=(0,10))]
]
window = sg.Window(
'window1', layout, alpha_channel=1, margins=(0, 0),
no_titlebar=True, grab_anywhere=True,
location=(350,130), modal=True
)
def multi(x):
name, pict, date, img, location, percentage_and_symbol = x['name'], x['pict'], x['date'], x['img'], x['location'], x['percentage_and_symbol']
if not name==None:
print(name, percentage_and_symbol, location, date)
return img
pool = ThreadPoolExecutor()
for array_x in xs:
for x in array_x:
if x=={}:
continue
result = pool.submit(multi, x)
event, _ = window.read(timeout=1)
if not result.result() is None:
imgbytes=cv2.imencode(".png", result.result())[1].tobytes()
window["cam1"].update(data=imgbytes)
if event=='terminate':
break
else:
continue
break
window.close()
print('終了します')

iniファイルを作成してスクリプト中から参照する例
config_FACE01GRAPHICS128.iniを作成します。
; 変数設定 ==========================
[DEFAULT]
; 指定した数値%以上を本人とする
similar_percentage=99.0
; 検出顔画像エンコーディング回数(変更非推奨)
jitters=0
; 登録顔画像エンコーディング回数
priset_face_images_jitters=100
; 顔検出面積(0: 80x80px, 1: 40x40px)
upsampling=0
; 深層学習モデルを使い顔検出('hog' or 'cnn')
mode=cnn
; フレームドロップ指定(-1:自動)
frame_skip=-1
; 入力映像データ指定
movie=test.mp4
; 入力映像に対して処理対象エリアを指定
set_area=NONE
; 入力映像に対してリサイズする横幅指定
SET_WIDTH=600
; 顔領域にクラシックなな枠を表示
rectangle=False
; 顔領域にモダンな枠を表示
target_rectangle=True
; opencv-pythonによるウィンドウの描画
show_video=False
; 顔領域の自動保存
crop_face_image=False
; 顔領域自動保存の頻度(フレーム数指定)
frequency_crop_image=80
; デフォルト顔画像の描画
default_face_image_draw=True
; 情報を半透明で表示
show_overlay=True
; 顔の下に%を表示
show_percentage=True
; 顔の下に名前を表示
show_name=False
; 入力映像データのプロパティを表示して終了
print_property=False
; 1フレーム処理にかかるミリ秒を標準出力
calculate_time=False
; 複数人検出された時に警告を出す
multiple_faces=True
; ウィンドウ下部に情報を表示
bottom_area=True
; ===================================
上述のiniファイルを参照し、ウィンドウを表示させ並行処理させます。
import configparser
from concurrent.futures import ThreadPoolExecutor
import cv2
import PySimpleGUI as sg
import FACE01GRAPHICS128 as fg
# configファイル読み込み
conf=configparser.ConfigParser()
conf.read('config_FACE01GRAPHICS128.ini', 'utf-8')
similar_percentage= float(conf.get('DEFAULT','similar_percentage'))
jitters= int(conf.get('DEFAULT','jitters'))
priset_face_images_jitters= int(conf.get('DEFAULT','priset_face_images_jitters'))
upsampling= int(conf.get('DEFAULT','upsampling'))
mode= conf.get('DEFAULT','mode')
frame_skip= int(conf.get('DEFAULT','frame_skip'))
movie= conf.get('DEFAULT','movie')
rectangle= conf.getboolean('DEFAULT','rectangle')
target_rectangle= conf.getboolean('DEFAULT','target_rectangle')
show_video= conf.getboolean('DEFAULT','show_video')
frequency_crop_image= int(conf.get('DEFAULT','frequency_crop_image'))
set_area= conf.get('DEFAULT','set_area')
print_property= conf.getboolean('DEFAULT','print_property')
calculate_time= conf.getboolean('DEFAULT','calculate_time')
SET_WIDTH= int(conf.get('DEFAULT','SET_WIDTH'))
default_face_image_draw= conf.getboolean('DEFAULT', 'default_face_image_draw')
show_overlay= conf.getboolean('DEFAULT', 'show_overlay')
show_percentage= conf.getboolean('DEFAULT', 'show_percentage')
crop_face_image= conf.getboolean('DEFAULT', 'crop_face_image')
show_name= conf.getboolean('DEFAULT', 'show_name')
multiple_faces= conf.getboolean('DEFAULT', 'multiple_faces')
bottom_area= conf.getboolean('DEFAULT', 'bottom_area')
kaoninshoDir, priset_face_imagesDir=fg.home()
known_face_encodings, known_face_names=fg.load_priset_image(
kaoninshoDir,
priset_face_imagesDir,
jitters=priset_face_images_jitters,
)
xs=fg.face_attestation(
kaoninshoDir,
known_face_encodings,
known_face_names,
similar_percentage=similar_percentage,
jitters=jitters,
upsampling=upsampling,
mode=mode,
model='small',
frame_skip=frame_skip,
movie=movie,
rectangle=rectangle,
target_rectangle=target_rectangle,
show_video=show_video,
frequency_crop_image=frequency_crop_image,
set_area=set_area,
print_property=print_property,
calculate_time=calculate_time,
SET_WIDTH=SET_WIDTH,
default_face_image_draw=default_face_image_draw,
show_overlay=show_overlay,
show_percentage=show_percentage,
crop_face_image=crop_face_image,
show_name=show_name,
multiple_faces=multiple_faces,
bottom_area=bottom_area
)
layout = [
[sg.Image(filename='', key='cam1', pad=(0,0))],
[sg.Button('終了', key='terminate', pad=(0,10))]
]
window = sg.Window(
'window1', layout, alpha_channel=1, margins=(0, 0),
no_titlebar=True, grab_anywhere=True,
location=(350,130), modal=True
)
def multi(x):
name, pict, date, img, location, percentage_and_symbol = x['name'], x['pict'], x['date'], x['img'], x['location'], x['percentage_and_symbol']
if not name==None:
print(name, percentage_and_symbol, location, date)
return img
pool = ThreadPoolExecutor()
for array_x in xs:
for x in array_x:
if x=={}:
continue
result = pool.submit(multi, x)
event, _ = window.read(timeout=1)
if not result.result() is None:
imgbytes=cv2.imencode(".png", result.result())[1].tobytes()
window["cam1"].update(data=imgbytes)
if event=='terminate':
break
else:
continue
break
window.close()
print('終了します')
顔の登録方法
priset_fase_imagesフォルダに’PNG’形式のファイルを配置して下さい。ファイル名は以下の形式に従って下さい。
名前_default.png
同一人物について2つ以上の顔を登録する場合には以下の形式に従って下さい。同一人物について登録数に上限はありません。マスクをはめた顔に対応させる場合はマスクをはめた顔もここに登録して下さい。
名前_1.png, 名前_2.png

顔は正面を向いた画像にして下さい。斜めを向いていたりうつむいた顔は避けて下さい。
極端に濃い化粧は精度を悪化させます。また眉毛が隠れるような長い前髪は避けて下さい。
可能な限り顔認証を行うカメラと登録を行うカメラを同一にして下さい。スマートフォンやコンパクトカメラの使用は精度を悪化させます。
高速化
GPU使用
良いパフォーマンスを出すにはGPUアクセラレーション(NVidiaのCUDAライブラリ経由)が必要です。またdlibをコンパイルする際にCUDAサポートを有効にする必要あります。
load_priset_image()メソッド
ver. 1.2.4からload_priset_image()メソッドにおけるmode選択が自動になりました。特に理由がない限り’hog’を指定して下さい。
jitters値指定は可能であれば大きめの値を設定して下さい。(100) データベースを構築する最初の1回目のみ時間がかかります。
face_attestation()メソッド
特に理由のない限りupsampling値を大きく設定しないで下さい。通常値: 0
GPU利用時においては’hog’よりも’cnn’の方が処理速度が高くより正確です。
複数同時認証では人数と処理時間に相関があります。多くの場合自動で調節されますが、より細かく調整したい場合はオプション変数から変更を加えてください。
以上です。最後までお読み頂きありがとうございました。