Dockerを使ったRaspberry Piでの顔認識アプリケーションの実装

この記事では、**Docker**を使って**Raspberry Pi**で顔認識アプリケーションのソフトウェア開発を簡略化する方法を紹介しています。

*本ブログは英語版からの翻訳です。オリジナルは[こちら](https://www.alibabacloud.com/blog/implementing-facial-recognition-applications-with-raspberry-pi-and-docker_593800)からご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。*

顔認証技術は、すでに多くの実世界のアプリケーションをサポートしています。今日は、Dockerコンテナを使ってRaspberry Pi上に顔認識アプリケーションを素早く作成する方法を紹介します。

今回は、顔認識機能がdlib(Deep Metric Learning)でサポートされているオープンソースのフレームワークageitgey/face_recognitionを使ってみました。Labeled Faces in the Wildのベンチマークテストによると、dlibの精度は99.38%となっています。Face_recognitionアプリケーションの開発は非常に簡単です。Raspberry Piに対応した顔認識アプリケーションを、Pythonコマンドをいくつか使うだけで作成することができます。

Raspberry Pi 2+プラットフォームの顔認識インストールのガイドはこちらにあります：[gist.github.com/ageitgey/1ac8dbe8572f3f533df6269dab35df65](https://gist.github.com/ageitgey/1ac8dbe8572f3f533df6269dab35df65)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/be8ea02f-3abc-754c-b164-50e55f883583.png)

Raspberry Piは、その洗練されたソフトウェアエコシステムと幅広いI/Oインターフェースでソフトウェア開発者に愛されている開発コンソールです。しかし、Raspberry Pi上でアプリケーション開発を深く学ぶことは困難です。

1、アプリケーション開発を勉強するためには、Raspberry Pi の弱いコンパイラアプリを使って多くのパッケージをダウンロードしてコンパイルしなければなりません。これは時間がかかり、それを成功させるためには多くの忍耐が必要になります。
2、オープンソースの深層学習フレームワークには、異なるライブラリや依存関係を持つものが多数存在しており、それらは互いに競合する可能性があります。例えば、Python 2.7 を必要とするものもあれば、Python 3.x に依存しているものもあります。 virtualenv を使って Python 環境を分離することはできますが、これではシステムレベルの依存関係の競合を解決することはできません。長くて時間のかかるビルドプロセスでは、依存関係はコンパイルの失敗や多くのフラストレーションにつながる可能性があります。
3、別のコンソールに同じアプリケーションをデプロイするには、すべてのプロセスを繰り返さなければなりません。

次の記事では、Dockerコンテナを使ってアプリケーションイメージを作成し、パッケージ化していきます。これにより、Dockerfileが提供するレイヤリング機能をフルに活用しながら、依存パッケージの調整を便利に行いながら、アプリケーションのビルドと実行を一括して行うことができるようになります。このようにして、開発とデプロイのプロセスは非常に効率的になります。

#Raspberry Pi上での顔認識アプリケーションのデプロイ

Raspberry PiとDockerのおかげで、顔認証開発環境のインストールとデプロイは楽勝です。
まず、Raspberry Pi 3に最新版のRaspbianをインストールする必要があります。

以下のコマンドを実行して、Docker Engineコミュニティの最新版をインストールします。

```
# Install Docker
curl -sSL https://get.docker.com | sh

# Add pi to Docker group
sudo usermod pi -aG docker

# config cgroup for Docker
echo Adding " cgroup_enable=cpuset cgroup_enable=memory" to /boot/cmdline.txt
sudo cp /boot/cmdline.txt /boot/cmdline_backup.txt
# if you encounter problems, try changing cgroup_memory=1 to cgroup_enable=memory.
orig="$(head -n1 /boot/cmdline.txt) cgroup_enable=cpuset cgroup_memory=1"
echo $orig | sudo tee /boot/cmdline.txt

sudo reboot
```

Raspberry Cameraをインストールします。カメラモジュール2を使用していますが、青い線がイーサネットインターフェイスの方向を示しています。`raspi-config`コマンドを使ってカメラモジュールを起動します。

コンテナでface_recognitionアプリケーションを開発して実行します。以下のコマンドを使ってコンテナを起動します。これには、face_recognitionの開発環境一式とサンプルアプリケーションが含まれています。具体的な画像の詳細については後述します。

```
docker run -it \
    --name face_recognition \
    --device /dev/vchiq \
      registry.cn-hangzhou.aliyuncs.com/denverdino/face_recognition \
      bash
```

ここでは、コンテナにカメラデバイス`/dev/vchiq`をマウントするのがポイントなので、コンテナ内のアプリケーションを使って写真や動画を撮影します。`docker cp`コマンドを使ってコンテナ内のファイル（写真など）をコピーしたり、コンテナ内のnanoなどのコマンドを使ってコードを編集したりすることができます。

#顔認識アプリケーションを分析する

`examples/facerec_on_raspberry_pi.py`を参考に、顔認証アプリを以下のように修正してみました。

```
# This is a demo of running face recognition on a Raspberry Pi.
# This program will print out the names of anyone it recognizes to the console.

# To run this, you need a Raspberry Pi 2 (or greater) with face_recognition and
# the picamera[array] module installed.
# You can follow these installation instructions to get your RPi set up:
# https://gist.github.com/ageitgey/1ac8dbe8572f3f533df6269dab35df65

import face_recognition
import picamera
import numpy as np

known_face_encodings = []
names = []

def load_face_encoding(name, file_name):
    image = face_recognition.load_image_file(file_name)
    face_encoding = face_recognition.face_encodings(image)[0]
    known_face_encodings.append(face_encoding)
    names.append(name)

# Get a reference to the Raspberry Pi camera.
# If this fails, make sure you have a camera connected to the RPi and that you
# enabled your camera in raspi-config and rebooted first.
camera = picamera.PiCamera()
camera.resolution = (320, 240)
output = np.empty((240, 320, 3), dtype=np.uint8)

# Load a sample picture and learn how to recognize it.
print("Loading known face image(s)")
load_face_encoding("Yi Li", "yili.jpg")
load_face_encoding("Zhang Kai", "zhangkai.jpg")
load_face_encoding("Che Yang", "cheyang.jpg")

# Initialize some variables
face_locations = []
face_encodings = []

while True:
    print("Capturing image.")
    # Grab a single frame of video from the RPi camera as a numpy array
    camera.capture(output, format="rgb")

    # Find all the faces and face encodings in the current frame of video
    face_locations = face_recognition.face_locations(output)
    print("Found {} faces in image.".format(len(face_locations)))
    face_encodings = face_recognition.face_encodings(output, face_locations)

    # Loop over each face found in the frame to see if it's someone we know.
    for face_encoding in face_encodings:
        # See if the face is a match for the known face(s)
        matches = face_recognition.face_distance(known_face_encodings, face_encoding)
        name = "<Unknown Person>"
        
        min_distance = min(matches)
        if min_distance < 0.6:
            i = matches.argmin()
            name = names[i]
            
        
        print("I see someone named {}!".format(name))
```

まず、コードの中で、指定した名前のヘッドショットを読み込むには、以下のメソッドを使用します。自分や友達の写真を顔のライブラリに追加することができます。

```
load_face_encoding("Yi Li", "yili.jpg")
```

その後、カメラで連続撮影を行い、以下の方法で写真の中の顔情報を検出します。

```
face_locations = face_recognition.face_locations(output)
...
face_encodings = face_recognition.face_encodings(output, face_locations)
```

次に、カメラで検出した顔情報と既知の顔情報を比較します。そして、その類似度が設定された閾値を超えた場合には、最も一致する名前を返します。これで簡単な顔認識アプリの開発は完了です。簡単でしたね。

```
matches = face_recognition.face_distance(known_face_encodings, face_encoding)
```

操作結果は以下の通りです。

```
# python3 facerec_on_raspberry_pi.py 
Loading known face image(s)
Found 0 faces in image.
Capturing image.
Found 0 faces in image.
Capturing image.
Found 1 faces in image.
I see someone named Yi Li!
...
```

これらの結果は、我々が期待していた通りのものです。しかし、Raspberry Piの処理能力が限られているため、リアルタイムとは程遠い非常に遅いレスポンスとなっています。顔を認識するのに数秒かかります。とはいえ、簡単なシナリオにはまだこのアプリを使うことができます。ぜひ私たちの心を吹き飛ばすようなアプリを自由に開発してください。

顔認識アプリをカスタマイズする必要がある場合は、[https://github.com/denverdino/face_recognition_pi](https://github.com/denverdino/face_recognition_pi?spm=a2c65.11461447.0.0.6d23581dyahWa2) に Dockerfile が公開されているので、自分のニーズに合った完全なアプリを作ることができます。

```
FROM resin/raspberry-pi-python:3
COPY pip.conf /root/.pip/pip.conf
RUN apt-get -y update
RUN apt-get install -y --fix-missing \
    build-essential \
    cmake \
    gfortran \
    git \
    wget \
    curl \
    graphicsmagick \
    libgraphicsmagick1-dev \
    libatlas-dev \
    libavcodec-dev \
    libavformat-dev \
    libboost-all-dev \
    libgtk2.0-dev \
    libjpeg-dev \
    liblapack-dev \
    libswscale-dev \
    pkg-config \
    python3-dev \
    zip \
    && apt-get clean && rm -rf /tmp/* /var/tmp/*
RUN python3 -m ensurepip --upgrade && pip3 install --upgrade picamera[array] dlib

# The rest of this file just runs an example script.

# If you wanted to use this Dockerfile to run your own app instead, maybe you would do this:
# COPY . /root/your_app_or_whatever
# RUN cd /root/your_app_or_whatever && \
#     pip3 install -r requirements.txt
# RUN whatever_command_you_run_to_start_your_app

RUN git clone --single-branch https://github.com/ageitgey/face_recognition.git
RUN cd /face_recognition && \
    pip3 install -r requirements.txt && \
    python3 setup.py install

CMD cd /face_recognition/examples && \
    python3 recognize_faces_in_pictures.py
```

必要であれば、Dockerイメージでアプリケーションをパッケージ化してDockerfilesを追加・修正することもできますが、ここではそれについては記述しません。

最後に、私のRaspberry 3の構成を投稿します。カメラの他に液晶画面を追加し、GPIOドライバを使ってCPUやメモリ、温度などを表示するアプリケーションをプログラムしてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/ef96f66b-5109-1960-8b55-b39eb44978e9.png)

#結論
今日は、Raspberry Pi上で顔認証アプリケーションを実行する方法を学びました。例で使ったコードは [https://github.com/denverdino/face_recognition_pi](https://github.com/denverdino/face_recognition_pi?spm=a2c65.11461447.0.0.6d23581dY7QCIk) にあります。

コンテナ技術は、IoTやエッジコンピューティングなどのシナリオで重要になってきています。この技術を使用することで、スマートデバイスアプリケーションのライフサイクル管理が大幅に簡素化されます。

2017年はコンテナ技術の急速な発展を目の当たりにし、Kubernetes、Containerd/OCI、その他のコンテナ技術標準を中心にエコシステム内でコンセンサスが形成されています。これにより、アプリケーション開発のさらなるイノベーションにつながるでしょう。2018年は、エンタープライズユーザーの生産環境におけるコンテナの幅広い応用だけでなく、あらゆる場所でコンテナ技術に遭遇することになるでしょう。大きな驚きが待っていると思います。
アリババクラウドの製品とソリューションの詳細については、[www.alibabacloud.com](https://www.alibabacloud.com/ja)



*アリババクラウドは日本に２つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
[アリババクラウドジャパン公式ページ](https://www.alibabacloud.com/ja)*