OpenFace(顔照合) について調査中

[OpenFace について調査中](https://qiita.com/nonbiri15/items/d9be1bd4baeaa2e8ab61)からOpenFace (顔照合)の記事を独立させました。


### 記事を執筆する動機：
　現在、深層学習に基づく顔検出・顔照合の技術が、飛躍的に進展しています。
　１．顔技術のユーザーが適切な判断をできるようにしたい。
　２．顔技術のユーザーが技術水準を理解していることで、市販品を導入する際のヒントとしたい。 


OpenFaceと名乗っている複数のプロジェクトがあるようです。ここでは、顔照合をする方のライブラリを示します。

github **[OpenFace Free and open source face recognition with deep neural networks.](https://cmusatyalab.github.io/openface/)**

CVPR 2015 paper [FaceNet: A Unified Embedding for Face Recognition and Clustering](https://www.cv-foundation.org/openaccess/content_cvpr_2015/app/1A_089.pdf) に対応する実装であるという。

![Screenshot from 2018-07-25 01-48-36.png](https://qiita-image-store.s3.amazonaws.com/0/83761/57750a19-5f81-19f2-bb0f-fe993bb3362b.png)

これは上記の論文中の顔画像です。このような難易度の高い画像での顔照合をするようになっているのです。


LFWデータ・セットでの検出精度の評価結果もある。

Accuracy on the LFW Benchmark
https://cmusatyalab.github.io/openface/models-and-accuracies/


ROCカーブで主張していることは、EigenFaceよりも、OpenBR v 1.1.0 よりもOpenFaceの方が本人の照合の性能がよいことです。
（ROCカーブの横軸は、他人を本人と間違える率。縦軸は、本人を本人と判定する率です。そのため、他人を本人と間違える率が小さく、本人を本人と判定する率が大きいこと、ROCカーブの左上にプロットされることがよい照合の結果です。)



![ROCカーブ](https://raw.githubusercontent.com/cmusatyalab/openface/master/evaluation/lfw.nn4.small2.v1/roc.png)



[OpenFace: A general-purpose face recognition
library with mobile applications](https://www.cs.cmu.edu/~satya/docdir/CMU-CS-16-118.pdf)

[openface.AlignDlib class](https://openface-api.readthedocs.io/en/latest/openface.html?highlight=au#openface-aligndlib-class)


Dockerを使ってインストールするのが、インスール時にライブラリのバージョンのバッティングの問題を生じないのでお薦めです。

[Setup with Docker](https://cmusatyalab.github.io/openface/setup/) に書いてある内容を引用しつつ、少し補足します。

git submoduleは外部の git リポジトリを、自分の git リポジトリのサブディレクトリとして登録し、特定の commit を参照する仕組みです。

```
git submodule init && git submodule update
```

### Automated Docker Build

すばやく開始するには、まずBamos / openfaceから入手可能な、あらかじめ構築された自動Dockerビルドを使用することです。 これは、ローカルでチェックアウトされたOpenFaceのコピーを必要とせず、使用しません。あなたの用意した 画像上で使用するには、ホストとDockerコンテナの間でディレクトリを共有します。


まず、Docker イメージを取得します。

```
docker pull bamos/openface
```

次にそのDockerイメージを起動します。

```
docker run -p 9000:9000 -p 8000:8000 -t -i bamos/openface /bin/bash
```

ここからDocker環境の中になります。


```
cd /root/openface
```


次のスクリプトは、２つの画像を比較するものです。

```
./demos/compare.py images/examples/{lennon*,clapton*}

Comparing images/examples/lennon-1.jpg with images/examples/lennon-2.jpg.
  + Squared l2 distance between representations: 0.763
Comparing images/examples/lennon-1.jpg with images/examples/clapton-1.jpg.
  + Squared l2 distance between representations: 1.132
Comparing images/examples/lennon-1.jpg with images/examples/clapton-2.jpg.
  + Squared l2 distance between representations: 1.145
Comparing images/examples/lennon-2.jpg with images/examples/clapton-1.jpg.
  + Squared l2 distance between representations: 1.447
Comparing images/examples/lennon-2.jpg with images/examples/clapton-2.jpg.
  + Squared l2 distance between representations: 1.521
Comparing images/examples/clapton-1.jpg with images/examples/clapton-2.jpg.
  + Squared l2 distance between representations: 0.318
```


次のスクリプトは、２つ目の引数で与えられた画像の顔が誰であるのかを推測するものです。
学習済みの内容は１つめのpickleされたファイルの中に記載されています。

./demos/classifier.py infer models/openface/celeb-classifier.nn4.small2.v1.pkl ./images/examples/carell.jpg

=== ./images/examples/carell.jpg ===
/root/.local/lib/python2.7/site-packages/sklearn/preprocessing/label.py:166: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.
  if diff:
Predict SteveCarell with 0.97 confidence.

[Steve Carell](https://en.wikipedia.org/wiki/Steve_Carell)という人物についてはwikipediaに記載があります。どうやらそのページにある画像が./images/examples/carell.jpg のようです。

最後のstart-servers.shはローカルPCに接続されたカメラを使って、
Youtube [OpenFace Web Demo [Oct 2015]](https://www.youtube.com/watch?v=LZJOTRkjZA4)
にある内容を実現するものです。

./demos/web/start-servers.sh
```


Youtube [OpenFace Web Demo [Oct 2015]](https://www.youtube.com/watch?v=LZJOTRkjZA4)
にある動画は、その動作例です。


サーバーが立ち上がったときに、webブラウザからアクセスする。

Dockerを使っていないときには以下のアドレスにアクセス
https://localhost:8000

Dockerを使っているときには、
https://<docker-ip>:8000
にアクセスする。

このdocker-ip の値を知るためには、
- コンテナIDを知る。
    - Docker 環境内で`cat /etc/hostname` をして値を表示させる。
- コンテナIDを元に対応するdocker-ip を求める。
    - docker環境の外で`docker inspect -f "{{.NetworkSettings.IPAddress}}" fb5d7a508ffd
` を実行する。
そうすると、次のようなIPアドレスが返ってくる。
172.17.0.2
これがdocker-ipだ。


次に、この値を使ってブラウザで以下のIPアドレスにアクセスする。
https://<docker-ip>:8000
　

ブラウザによっては以下のメッセージを出して、次に進めない。
「安全な接続ではありません」
そのときは、次のようにすることでアクセスできます。

>エラーを許容できるウェブサイトであれば、そのサイトに訪れるために、その証明書が既定 で信頼されていないことを無視して例外を追加できます:

>    エラーの警告ページで、エラー内容 ボタンをクリックします。
    例外を追加... ボタンをクリックします。セキュリティ例外の追加 ダイアログが表示されます。
    ウェブサイトの問題について書かれた文章をよく読み、信頼されない証明書を調べるため、表示... ボタンをクリックしてください。
    そのサイトが信頼できる場合は、セキュリティ例外を承認 ボタンをクリックします。 


そうすると、更に、ローカルPCにUSBカメラにアクセス許可を求めてくるので、許可をする。
以下のように、トラブルが記載されている。
今、私が四苦八苦している状況と似ている。
https://github.com/cmusatyalab/openface/issues/327

カメラの画像を表示すべき部分が、真っ黒の画像が表示されている。
Servers: Connected to Local
と表示されてきている。


- Ubuntu でのインストール手順 と　顔の比較をするサンプルの実行 [OpenCVとdlibとOpenFaceでの顔検出と知見まとめ](http://vaaaaaanquish.hatenablog.com/entry/2016/06/28/004811)


> サンプルは「顔の場所を検出してcropして学習済みネットワークで特徴量化しそのベクトルのL2距離を比較する」というもの。
本家は「"OpenCV or dlib"」と言っているが、この推奨サンプルではcv2の画像読み込みでロードして顔検出精度が高いdlibで顔検出しているので「dlibもOpenCVも結局どっちも要るじゃねえか！」となる。

- 解説 [Deep Neural Networkによる顔認識フレームワーク『OpenFace』 ](https://blog.negativemind.com/2016/04/14/openface/)

- Ubuntu でのインストール手順 [第3回 OpenFaceを動かすまで](http://blog.goo.ne.jp/jsp_job/e/a779b628252e23a4ebcf6c857e748f2f)


### **インストール手順を示すYoutube動画**

Youtube [OpenFace face recognition API Installation prerequisites pip packages Setup 1](https://www.youtube.com/watch?v=hN4lULtjzzE)

Youtube [OpenFace face recognition API Installation prerequisites OpenCV Setup 2](https://www.youtube.com/watch?v=mXfQTBclLqE)
Youtube [OpenFace face recognition API Installation prerequisites dlib Setup 3](https://www.youtube.com/watch?v=YNBD6rNJIRw)
Youtube [OpenFace face recognition API Installation prerequisites Torch Setup 4](https://www.youtube.com/watch?v=J6AlkeC4ET8)

### demoのYoutube動画
Youtube OpenFace の顔照合のデモ[OpenFace Web Demo [Oct 2015]](https://www.youtube.com/watch?v=LZJOTRkjZA4)


以下の記事は、OpenFaceで検出した顔枠から目の近傍の画像を用いて、カメラを見ている画像とそうでない画像とを区別するものです。

qiita [OpenFace+機械学習で視線検知](https://qiita.com/29Takuya/items/5c95b2a1fa42975305c9)
qiita [Facenetを使った類似顔画像検索のための特徴量抽出](https://qiita.com/zeze/items/09bdd7229713c0a6b090)


---
### Docker環境で/dev/video0のアクセス

Docker環境ではカメラデバイスのアクセスを許可する設定をしないと、上記のエラーがでている可能性が高い。

----
### 付記：OpenBR
OpenBRのサイトを見ると、 "Version 1.1.0　9/29/15"　と書かれており、最近は改良がされていない様子です。


http://openbiometrics.org/

---
### 今後、商用のライブラリはどうなっていくのだろうか？

顔検出だけではなく、顔照合の分野でもオープンソースのライブラリの性能が向上してきている。

#### 商用ライブラリが優位を保ち続けるための前提条件

- 精度がオープンソースの実装を上回り続けること。
- 精度が同程度であれば、検出・照合の実行速度が少なく、最適化されていること。
- 利用するためのライブラリのインタフェースが適切であって、使いやすいこと。
- そのライブラリのサポートをし続けること。
- そのライブラリのうえに、市場の目的にそった多数のアプリケーションを構築し、顧客へのサポートをし続けること。

そういった条件を維持しつづけないと、商用ライブラリが、オープンソースで置き換えられていく可能性がある。

（ちなみに、統計分野でのS言語が、オープンソースのR言語で置き換えられつつある。深層学習のライブラリのサポート状況では、R言語の方が優位にたっている状況らしい。）

今の時点で、市場の優位に立っている商用ライブラリでも、その優位をいつまで保てるかは不明です。

一社が圧倒的な優位をしめて、市場を専有することは健全なことではありません。オープンソースの実装が、精度・処理速度・インターフェスの設計・サポートするプラットフォームなどの点で、最適なものを作り上げていけば、圧倒的な優位による市場独占に立ち向かうことができるかもしれません。

#### 優秀な種類の顔照合の商用ライブラリの特徴

- マスクをしていても顔検出ができるだけではなく、マスクに隠されていない部分から、顔照合ができる。
- サングラスをしていても顔検出ができる。
- メガネの有無やメガネの種類によっても、顔照合の精度が保たれる。
- 顔画像が、メガネ・サングラス・マスクの有無などが判定できる。
- 西洋人・東洋人によらず顔照合の精度が保たれる。

こういった部分への対応は、なかなかオープンソースの顔照合では対応できていません。

固有顔を使った顔照合は、マスクをしている顔をそのまま固有顔に展開すると、めちゃくちゃな展開になります。そのため、顔照合は事実上不能になります。

顔照合で用いる特徴量ベクトルは、顔の平均顔からの差を用いて生成していることが多いものです。そのため、顔照合の学習に用いた平均顔しだいで、顔照合の性能に影響します。たとえて言えば、ある色が何色かを判断する際に、基準となる白色をどこに置くかということです。白色の基準がどこにあるかによって、わずかにピンクぽいのか、わずかに水色っぽいのかが変わってくるようなものです。

西洋人の平均顔から見れば、日本のアイドルグループの若い女性の顔は、どれも似た方向の変化に見えてしまうのです。そのため、西洋人だけで訓練した顔照合のシステムの場合には、日本人の顔照合で精度がでないということが起こりえます。


#### 顔照合技術の健全な利用なために

- 顔照合技術には限界があることを理解すること
- 顔照合技術をあざむく手法が各種存在することから、安易に顔照合技術を信用しないこと。
- 顔照合を乱用する社会は健全なのか。
- 顔照合技術は、ある種の計測技術であり、撮影した画像の品質が重要であることを理解しよう。


#### オープンソースの維持にはコストがかかる。
オープンソースであっても品質を維持・向上させるにはコストがかかる。
C++言語の言語仕様の変更、依存性のあるライブラリのバージョン変更への対応、これらを怠ると、品質が劣化した（degradeした）コードになってしまう。
多くのユーザーがいるオープンソースの場合には、維持してくれている多数の方々の努力によって、破綻や崩壊、品質の劣化を免れている。

あなたにとって重要なライブラリに対しては、あなたも改善に寄与できることを見つけていくことがいいだろう。

利用者の少ない、その分野の専門家が少ないライブラリに対しては、あなたの知見は有意義なはずだ。
今後伸ばしていくことが重要なライブラリに対して、あなたの知見をプルリクエストの形で反映してくださるとうれしい。

商用ライブラリは、オープンソースを使っているときに生じる（かもしれない）様々な面倒をお金を払って肩代わりしてもらっているやり方ともいえる。