Face01_Graphics 1.1.6 の呼び出し方について解説します

この解説ページは「Face01_Graphics 1.1.2 の呼び出し方について解説します」をベースに、バージョン 1.1.6 に対応するように書き換えました。

Face01_Graphics におけるバージョン 1.1.6 について引数の説明をいたします。

# coding: utf-8

print('Start test_script')


import face01_116 as f


kaoninshoDir, pictures_of_people_i_knowDir = f.home()


known_face_encodings, known_face_names = f.load_priset_image(
	kaoninshoDir,
	pictures_of_people_i_knowDir, 
	jitters=5, 
	upsampling=0, 
	mode='cnn', 
	model='large'
)


xs = f.face_attestation( 
	kaoninshoDir, 
	known_face_encodings, 
	known_face_names, 
	tolerance=1.0, 
	jitters=0,
	upsampling=1,
	mode='cnn', 
	model='large',
	frame_skip=15,
	movie='test.mp4',
	rectangle='true',
	show_video='true',
	frequency_crop_image=1
)

for x in xs:
	(name, pict, date, img, location, percentage) = (x['name'], x['pict'], x['date'], x['img'], x['location'], x['percentage'])
	# ~ print({(name,pict)})
	# json 方式の出力
	# ~ print({
		# ~ "name": name,
		# ~ "percentage": percentage,
		# ~ "pict": pict,
		# ~ "date": date,
		# ~ "location": {
			# ~ "top": location[0],
			# ~ "right": location[1],
			# ~ "bottom": location[2],
			# ~ "left": location[3]
		# ~ }
	# ~ })
	print(name, percentage)

今までの

  • Face01_HOG
  • Face01_CNN
  • Face01_USB_HOG
  • Face01_USB_CNN

は全て統合され単一の Face01_Graphics となります。
すなわち HOG 形式か CNN 形式か、あるいは動画入力元が Web カメラか test.mp4 からかを引数から選べるようになりました。

コメントにもあるように、それぞれの関数に与える引数を自由に変えられるようになりました。これによって呼び出す側に自由度を与えますが、反対に顔認証のアルゴリズムや各々の変数の働きが分かっていないと期待しない動作になってしまいます。
ですので内部があまりよく理解できていない場合は「変数を指定しない」というのも一つの手です。デフォルトの動作として変数を与えなくても内部でよろしくやってくれるようになっています。ただしマスクをしたまま顔認証する場合はきちんと働きを知っておく必要があります。
参考文献として「顔認証、マスクをつけたらどうなるの?」を最初にお読みになってください。
では一つづつ変数を確認していきましょう。

各変数の働き

jitters

dlib を git clone した場所、私の場合なら $HOME/dlib/python_examples/ ディレクトリの face_jitter.py ファイルを参照してください。そこには以下のように記述してあります。
It takes an input image and disturbs the colors as well as applies random translations, rotations, and scaling.
「入力画像を受け取り、色を乱し、ランダムな移動、回転、スケーリングを適用します。」
jitters の値を大きくするほどランダムな変換の平均値をとるようになります。
しかしながら大きな値をとることによって入力画像が不確かなものになっていくこと、処理時間が長くなることが懸念されます。
通常は 5 〜 10 あたりが良いように感じます。

upsampling

How many times to upsample the image looking for faces. Higher numbers find smaller faces.
「顔を探して画像をアップサンプリングする回数。 数値が大きいほど顔が小さくなります。」
具体的には upsampling が 0 の時 80×80 ピクセル、1 の時に 40×40 ピクセルの範囲で顔を探索します。Face01 では 0 か 1 の数値をとります。
処理時間とトレードオフになります。
下の例では 80x80px で良好な結果を出します。ですので upsampling=0 にするのが良いでしょう。

mode

CNN 形式または HOG 形式のどちらかを選びます。
CNN: Convolutional Neural Network
HOG: Histogram of Oriented Gradients
速度は HOG が速く CNN で同等の速度を出そうとすれば NVIDIA Titan X GPU が必要になります。
( $HOME/dlib/python_examples/dnn_mmod_face_detection_ex.cpp 参照
実際には RTX 2070 SUPER などが妥当だと思います)
GPU が使えない状況下にあっては HOG 形式を使うほうが現実的でしょう。
マスクをした顔の場合は CNN 形式が良好な結果を出力します。

model

small: 5-point landmark model
large: 68-point landmark model
となります。
マスクをはめたまま顔認証するときにも large を選んでください。正確性が増します。
どうしても顔の探索率が悪いときにのみ small を指定してください。

tolerance

0.6 を基準としてトレーニングしてあります。これより大きければ他人と判断されます。
アジア人の場合、0.45〜0.55 くらいに設定しましょう。それ以上の distance ( 顔データ間の距離 ) は足切りされます。
以下の動画は Face01_Imager 様に作られたものですが、しきい値 ( torelance ) に関しては共通の知識になりますのでご覧になってみてください。

frame_skip

フレームドロップの割合です。入力が 30fps の場合 frame_skip=2 では 15fps となります。処理するコンピュータの性能によってさばけるフレーム数は異なります。また mode に cnn を選んだ時などマシンに負荷がかかって処理が遅くなってしまう場合この引数を使ってフレームを手動でドロップします。
一般に mode では CNN 形式よりも HOG 形式のほうが負荷が軽く、model では large より small の方が負荷が軽くなります。

movie

動画入力元を test.mp4 と USB カメラの 2 種類から選ぶ事が出来ます。test.mp4 は 同一ディレクトリに配置してください。

  • movie=’test.mp4′
  • movie=’usb’

のいずれかを選びます。デフォルト値は ‘test.mp4’ 。

rectangle

顔周囲に枠を描画するかどうかを指定します。

  • rectangle=’true’
    外枠を描画する
  • rectangle=’false’
    外枠を描画しない
  • デフォルト値
    true
rectangle='true' 外枠描画
rectangle=’true’ 外枠描画
rectangle='false' 外枠を描画しない
rectangle=’false’ 外枠を描画しない

show_video

openCV 由来の GUI 表示をするかしないかを選べます。
独自に GUI を作りその中に顔認証済み動画を埋め込みたいときなどに使います。下図では簡単な例として matplotlab を用いて関数の返り値から GUI ウィンドウを開いています。

frequency_crop_image

これまで(バージョン 1.1.3 )は 1 フレームごとに output として顔をクロップした顔画像ファイルを出力していましたが、これだと io 速度が律速ポイントとなってしまいます。
バージョン 1.1.4 からは n 枚のフレームごとに 1 つの顔画像ファイルを出力することが指定できます。これにより Face01 の速度を向上させることが出来ます。

mode と model の使い分け

まず各関数がどのような働きをしているか簡単に説明します。

load_priset_image() 関数

pictures_of_people_i_know ディレクトリに登録されている顔画像ファイルを 128D 顔識別子にエンコードする際に用いられます。
マスクの有り無しも含めて通常は
mode: ‘hog’
model: ‘large’
pictures_of_people_i_know フォルダにぼやっとした顔やマスクをはめた顔を登録するした場合 HOG モードでは読み込めない事があり、この様なときはプログラム内部でその部分だけ CNN モードで顔探索処理を行います。

face_attestation() 関数

load_priset_image() 関数で 128D 顔識別子でエンコードされたデータと比較するためにここでも 128D エンコードを行います。
先と同じようにマスクの有り無しに関わらず
mode: ‘cnn’
model: ‘large’

を指定してください。ただし mode の項で触れたとおり顔認識の精度の高い cnn を選択する場合は速度とトレードオフになることに注意してください。十分な性能の NVIDIA 製 GPU を搭載していれば速度的には問題になりませんがサーバで使用する場合など CPU のみと制約がある場合もあります。そういった場合で更にマスクの有り無しで考慮する場合には
model: ‘cnn’
mode: ‘large’

にしてフレームドロップなどで対処します。
チェックされる画像の照明の当たり具合や焦点ボケが発生している場合、cnn 形式でないと顔を認識できない場合がありますので注意してください。現場で用いる場合、なるべくしっかりと顔が映るようにすると hog で通用する場合も多いですので「実際の使われる環境」にも留意しましょう。

デフォルト値

マスクをした状態を CPU のみで処理を行うこと前提の引数値になっています。

load_priset_image() 関数の場合

known_face_encodings, known_face_names = f.load_priset_image(
	kaoninshoDir,
	pictures_of_people_i_knowDir, 
	jitters=10, 
	upsampling=0, 
	mode='cnn', 
	model='large'
)

80×80 ピクセルでの顔探索、jitters ( ゆらぎ値 ) は 10 、HOG 形式、5-point landmark model となっています。
pictures_of_people_i_know フォルダに登録する顔画像ファイルはマスクあり、200×200 ピクセル。
マスクをはめた顔を想定しています。

face_attestation() 関数の場合

xs = f.face_attestation( 
	kaoninshoDir, 
	known_face_encodings, 
	known_face_names, 
	tolerance=0.5, 
	jitters=0,
	upsampling=1,
	mode='cnn', 
	model='large',
	frame_skip=15,
	movie='test.mp4',			# Web カメラからの入力は movie='usb'
	rectangle='true',
	show_video='true',
	frequency_crop_image=1
)

80×80 ピクセル以上の顔、jitters ( ゆらぎ値 ) は 0 、tolerance ( 許容値(閾値)) は 0.5 、CNN モード、5-point landmark model 、手動でのフレームドロップは 15 ( 元が 30fps の場合 2 fps ) 、動画入力元は test.mp4 となっています。こちらは CPU のみで処理を前提としています。

マスクを考慮しない場合には

こちらも CPU のみで処理することを前提にしています。

load_priset_image() 関数の場合

known_face_encodings, known_face_names = f.load_priset_image(
	kaoninshoDir,
	pictures_of_people_i_knowDir, 
	jitters=10, 
	upsampling=0, 
	mode='hog', 
	model='large'
)

mode を cnn 、 model を large 、upsampling を 0 ( 80×80 ピクセル ) にします。

face_attestation() 関数の場合

def face_attestation(
	kaoninshoDir, 
	known_face_encodings, 
	known_face_names, 
	jitters= 0, 
	tolerance=0.5, 
	mode='hog', 
	model='large', 
	upsampling=0, 
	frame_skip=3, 
	movie='test.mp4', 
	rectangle='true', 
	show_video='true', 
	frequency_crop_image=10
):

こちらも、mode を hog 、 model を large にします。また upsampling は 0 、フレームドロップを 3 にして 1/3 の負荷にしています。

GPU が使える場合には

NVIDIA 製の GPU が使える場合にはまず dlib と face-recognition を CUDA 仕様にしてください。
以下はマスクをはめた状態を想定しています。

load_priset_image() 関数の場合

known_face_encodings, known_face_names = f.load_priset_image(
	kaoninshoDir,
	pictures_of_people_i_knowDir, 
	jitters=10, 
	upsampling=0, 
	mode='cnn', 
	model='large'
)

face_attestation() 関数の場合

xs = f.face_attestation( 
	kaoninshoDir, 
	known_face_encodings, 
	known_face_names, 
	tolerance=0.5, 
	jitters=0,
	upsampling=0,
	mode='cnn', 
	model='large',
	frame_skip=1,
	movie='test.mp4',			# Web カメラからの入力は movie='usb'
	rectangle='true',
	show_video='true',
	frequency_crop_image=10
)

返り値

(name, pict, date, img, location, percentage) = (x['name'], x['pict'], x['date'], x['img'], x['location'], x['percentage'])
  • name
    顔認証処理の結果返される名前。未登録の顔の場合は「Unknown」
  • pict
    出力される顔画像ファイル名
  • date
    顔認証処理された日付時刻
  • img
    numpy 配列で返されるフレーム画像
  • location
    顔が存在する座標
  • percentage
    顔認証処理により何 % の確率でその人物か数値で返す

まとめ

上記リンク先も参照してください。

今回の変更により、現場でマスクあり・なしの状況変化や使用するコンピュータの負荷、テスト使用か Web カメラ入力かに柔軟に対応できるようにいたしました。
反面では変更できる変数や関数の働きを理解しないといけないものになっています。
今までは model や mode などごとに違うアプリケーションとしてご用意させていただいておりましたが、現場で柔軟に変えられたほうが良いだろう…という考えがありました。
もし疑問点・不明な点があればお問い合わせからご連絡いただけると幸いです。

Follow me!