去年の8月に、国立情報学研究所(NII)が顔認識ができなくなるメガネを開発したという記事が話題になりました。
nlab.itmedia.co.jp
それに対して
Haar-like, LBP特徴による方法が前提っぽいから、HOG特徴量で輪郭取るこの前の方法なら勝てそう
— 川奈 清 (@kivantium) 2015年8月6日
とコメントしたところミクミンPさんから
@kivantium ポチったので届いたらハッカソンでもやりましょうか
— ミクミンP/Kazuhiro Sasao (@ksasao) 2015年8月6日
という反応があり、今日実際にハッカソンが行われました。
connpass.com
「顔認識を失敗させる技術を失敗させるハッカソン」は、最初に7人の参加者でプライバシーバイザーをつけた場合とつけなかった場合の顔動画を撮影して共有し、あとは各自で黙って作業するという形で行われました。
プライバシーバイザーの有効性の確認
Faces in the WildのOriginal News Photographsからダウンロードしたデータのうち200枚を使って以前の記事(dlibによるHOG特徴量を用いた物体検出器がすごい)の手順に従って学習させました。(900枚ラベリングしたのですが全部使うとdlibが落ちてしまうので200枚だけ使いました。)頭ではなく顔の検出を学習させたかったので、両眉とあごを含むなるべく小さい正方形領域を正例としました。試した範囲ではパラメータC=50に設定するのが最も精度が良かったのでそう設定しています。
評価にはハッカソン参加者の顔を撮影した画像のうち、前を向いているもの(目が2つ写っているかどうかを基準にした)を選んで使いました。その結果、顔が正しく検出できたのはプライバシーバイザーなしの顔データに対して67%(149/222)、プライバシーバイザーを装着した顔データについて27%(29/106)でした。(偽陽性は1%程度でした)
この実験により、HOG特徴量を使って通常の顔画像のみを用いて学習した検出器に対してはプライバシーバイザーが顔検出率を下げる効果を持つことが確認できました。
※ プライバシーバイザーをつけていない状態で67%しか検出できないのは検出率が低いような気もしますが、テストデータには学習データにはない角度(横向きや上向きなど)の顔が多く存在したのでその影響で下がってしまったようです。真正面の顔であれば90%くらいは検出できていました。
※ プライバシーバイザーをつけていても1/4の顔が検出できてしまうのはかなり問題がある気がしますが、NIIはこれでいいのでしょうか……
この時点での学習結果とほぼ同じものをここからダウンロードできます(lfw-detector.svm)
プライバシーバイザーに対抗する
プライバシーバイザーが存在するという事前知識があればプライバシーバイザーをつけた顔画像を訓練データに入れて学習することが当然考えられます。今日撮影したデータのうちランダムに150枚を訓練用に分けて学習データをつくりました。
結果は、プライバシーバイザーなしの顔に対して100%(96/96)、プライバシーバイザーありであっても99%(105/106)の顔を検出できるというものでした。
半日のハッカソンで用意できるデータという限界がある関係でテスト画像が学習データと同じ人物・同じ背景になってしまったのは問題なのですが、Webカメラでのデモを行った感触では十分な数のプライバシーバイザーを装着した人物のデータさえあればプライバシーバイザーがあっても全く問題なく顔検出できるであろうという結論になりました。
この時点での学習結果はここからダウンロードできます(detector.svm)
detector.svmを使ってWebカメラの画像に対して顔検出するプログラムは以下の通りです。
#!/usr/bin/python import os import sys import dlib import cv2 # Webカメラをopen cap = cv2.VideoCapture(0) if not cap.isOpened(): raise Exception, 'failed to open camera' # 顔検出器の読み込み detector = dlib.simple_object_detector("detector.svm") while True: ret, frame = cap.read() img = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB) dets = detector(img) # 顔を枠で囲む for d in dets: cv2.rectangle(frame, (d.left(), d.top()), (d.right(), d.bottom()), (0, 0, 255), 2) cv2.imshow("show", frame) k = cv2.waitKey(1) # ESCを押すと終了 if k == 27: break cap.release() cv2.destroyAllWindows()
です。(参考: Python+OpenCVでカメラキャプチャ - Qiita)
他の参加者について
ハッカソンの終わりにそれぞれの進捗報告会を行いました。他の人の進捗は以下のような感じでした。
- プライバシーバイザーをかけた画像も含むデータセットに対してOpenCVのカスケードをLBP特徴量で学習したところ十分な精度で認識できた
- 検出した顔領域を32x32のグレースケール画像にして、各人の平均顔とのユークリッド距離を取ったところそれなりの精度での個人識別ができるようになった
- OpenCVのデフォルト顔検出器でも若干正答率は下がるものの割と検出できることが分かった
- OpenBRを使った生体認証をしようとしたが動かすところまでは行かなかった
- OpenFaceのDockerを動かしてみたが、顔検出部分はOpenCVをだったため今回のハッカソンの対象ではないことが分かった
- Facial Keypoints Detection | Kaggleで勝った論文(Deep Convolutional Network Cascade for Facial Point Detectionだろうか?)を動かそうとしたが完成には至らなかった
まとめ
[結論] 抵抗は無意味だ #aafacedetect
— ミクミンP/Kazuhiro Sasao (@ksasao) 2016年3月27日