[Python3][Ubuntu16][Docker] OpenFaceで顔認証してみる

#概要
Python3+Ubuntu16.04でOpenFaceを動かせる環境（Dockerイメージ）を作成して、コンテナ上でOpenFaceの顔認証（2つの顔の距離比較）のサンプルコードを動かしてみる。

## OpenFaceとは

>Carnegie Mellon University.のBrandon Amos氏が作成している、
ディープニューラルネットワークを用いた顔認証に特化したオープンソースになります。
PythonおよびTorch実装であり、CVPR 2015に基づいているとのこと。
下記にアルゴリズムの概要やリリースノートがまとめられております。
https://cmusatyalab.github.io/openface/


>OpenFaceのアルゴリズムですが、
　(1)dlibまたはOpenCVによる事前トレーニングされたモデルで顔を検出
　(2)OpenCVのアフィン変換とdlibのリアルタイムポーズ推定を利用して顔内の目と下唇の位置が同一となるように変換
　(3)ディープニューラルネットワークを用いて128次元のユニット超球上の顔を表現（または埋め込み）を行い、クラスタリング、類似性検出、および分類タスクにより顔認識を行う
とのことです。

※引用　https://elsammit-beginnerblg.hatenablog.com/entry/2020/05/17/192559

# 前提
・PCにDockerがインストールされていること

#手順

## 1. Dockerfileの作成

作業ディレクトリに以下のDockerfileを作成する。

※以下の記事を参考に作成
●OpenFaceをUbuntuで利用
https://elsammit-beginnerblg.hatenablog.com/entry/2020/05/17/192559
●第3回 OpenFaceを動かすまで
https://blog.goo.ne.jp/jsp_job/e/a779b628252e23a4ebcf6c857e748f2f

とりあえず動く環境を目指して作成したので、余分なコマンドが存在するかもしれません。

```docker:Dockerfile
FROM ubuntu:16.04

# aptパッケージの更新
# 必要な apt パッケージのインストール
RUN apt-get update && apt-get upgrade -y && apt-get install -y wget sudo python-setuptools python-pip liblapack-dev libatlas-base-dev gfortran g++ build-essential libgtk2.0-dev libjpeg-dev libtiff5-dev libjasper-dev libopenexr-dev cmake python-dev python-numpy python-tk libtbb-dev libeigen3-dev yasm libfaac-dev libopencore-amrnb-dev libopencore-amrwb-dev libtheora-dev libvorbis-dev libxvidcore-dev libx264-dev libqt4-dev libqt4-opengl-dev sphinx-common texlive-latex-extra libv4l-dev libdc1394-22-dev libavcodec-dev libavformat-dev libswscale-dev default-jdk ant libvtk5-qt4-dev unzip cmake git python-dev python-numpy libboost-dev libboost-python-dev libboost-system-dev
# 必要な pip パッケージのインストール
RUN sudo pip install -U pip && sudo pip install numpy==1.12.0 scipy matplotlib cython scikit-image dlib pandas txaio

# Torchのインストール
WORKDIR /root
RUN git clone https://github.com/torch/distro.git ~/torch --recursive
WORKDIR /root/torch
RUN sudo dpkg --configure -a
RUN bash install-deps
RUN ./install.sh -y
RUN . /root/.bashrc
# thコマンドのPATHを通す 
RUN export PATH=/root/torch/bin:$PATH;
RUN export LD_LIBRARY_PATH=/root/torch/lib:$LD_LIBRARY_PATH;

# Torch用のLUAパッケージをインストール
# luarocksをビルドするのにlua**が必要になるため事前にインストール.
RUN sudo apt-get install lua5.3
RUN sudo apt-get install -y lua5.3-dev

#luarocksをインストール
RUN mkdir luarocks
WORKDIR /root/torch/luarocks
RUN wget https://luarocks.org/releases/luarocks-3.3.1.tar.gz
RUN tar -xf luarocks-3.3.1.tar.gz
WORKDIR /root/torch/luarocks/luarocks-3.3.1
RUN ./configure
RUN make
RUN make install

#LUAパッケージインストール
RUN for NAME in dpnn nn optim optnet csvigo cutorch cunn fblualib torchx tds image nngraph; do sudo /root/torch/install/bin/luarocks install $NAME; done

# OpenFaceのインストール
RUN git clone https://github.com/cmusatyalab/openface ~/openface --recursive
WORKDIR /root/openface
RUN sudo python setup.py install
RUN sudo python3 setup.py install

# 追加で必要なものをインストール
RUN ./models/get-models.sh
RUN ./demos/web/install-deps.sh
RUN sudo pip install -r demos/web/requirements.txt

# python3でOpenFaceを動かすために必要なものをインストール
WORKDIR /root
RUN curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
RUN sudo python3 get-pip.py && python3 -m pip install -U pip
RUN sudo apt-get install -y python3-dev
# OpenCV,dlibのインストール
RUN python3 -m pip install opencv_python dlib
```

```terminal:terminal
usermac:~ user$ ls {作業ディレクトリ}
Dockerfile #作成したDockerfile
```

## 2. Dockerイメージを作成する（docker build）

```terminal:terminal
docker build -t openface_ubuntu16_python3:1.0 {Dockerファイルが置いてある作業ディレクトリの相対or絶対パス}
```

※完了まで少し時間がかかります。

## 3. コンテナを起動する（docker run）

```terminal:terminal
docker run -it -v {作業ディレクトリの絶対パス}:/home/ openface_ubuntu16_python3:1.0 /bin/bash .
```
ホストの作業ディレクトリとコンテナのhomeディレクトリを共有（ボリューム）している。

##### 絶対パスの確認コマンド

```terminal:terminal
usermac:work user$ pwd
/Users/{username}/openface_sample/work
```

## 4. OpenFaceのデモコードを実行する

`~/openface`にOpenFaceのソース、デモコードを置いているので確認。

```docker:container
root@bb9464b46285:~# ls openface/
CONTRIBUTING.md  LICENSE    api-docs         build    data   docs        images      models                        openface          run-tests.sh  tests     util
Dockerfile       README.md  batch-represent  cloc.sh  demos  evaluation  mkdocs.yml  opencv-dlib-torch.Dockerfile  requirements.txt  setup.py      training
```

今回はデモコードのcompare.pyを実行して、2枚の写真に存在する顔が同一人物かどうかを判定する。

```docker:container
root@bb9464b46285:~# python3 openface/demos/compare.py openface/images/examples/lennon-1.jpg openface/images/examples/lennon-2.jpg 
Comparing images/examples/lennon-1.jpg with images/examples/lennon-2.jpg.
  + Squared l2 distance between representations: 0.782  #実行結果
```

`python3 openface/demos/compare.py`の後ろで指定している`openface/images/examples/lennon-1.jpg`と`openface/images/examples/lennon-2.jpg`の部分で比較したい2枚の画像を指定する。
今回はopenface以下に置いてあるサンプル画像を利用した。指定した画像から顔が検出できない場合はエラーとなる。

`0.782`が比較した2つの顔の距離。`0`に近いほど同一人物である可能性が高い。
基準値は、実際に利用する写真で検証して判断する必要がありそう。