読者です 読者をやめる 読者になる 読者になる

kivantium活動日記

プログラムを使っていろいろやります

顔認識を失敗させる技術を失敗させるハッカソンに参加した

去年の8月に、国立情報学研究所(NII)が顔認識ができなくなるメガネを開発したという記事が話題になりました。
nlab.itmedia.co.jp

それに対して


とコメントしたところミクミンPさんから
という反応があり、今日実際にハッカソンが行われました。
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カメラでのデモを行った感触では十分な数のプライバシーバイザーを装着した人物のデータさえあればプライバシーバイザーがあっても全く問題なく顔検出できるであろうという結論になりました。
f:id:kivantium:20160327165250p:plain:w600

この時点での学習結果はここからダウンロードできます(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だろうか?)を動かそうとしたが完成には至らなかった

まとめ