Dockerを使って、Tensorflow とOpenCVの開発環境を構築しよう

# これはなに？
この記事は、岩手県立大学 Advent Calendar 2018の16日目の記事です。

組み込みエンジニアから、サーバーサイドエンジニアにジョブチェンジしたnyagato_00です。
最近は、医療用の画像(レントゲン写真など)の画像処理に興味があります。
今回は、Tensorflowの環境構築をdockerを使って行う方法をご紹介します。

# なんでDockerを使うのか
開発マシンに、Tensorflowの環境構築をするのは意外と手間がかかったりします。
CPUベースで使う場合は、まだなんとかなる場合がありますが、GPUを使ってDNNをやりだそうとすると、相性問題などに当たることもあります。
また、開発チーム皆で共通の開発環境を構築したいですよね。昨今のIT系企業は、開発環境・テスト環・本番環境などは、共通化されているかと思います。ただ、私の前職ではDocker?なにそれ美味しいの状態でした。環境構築にリソースを割くよりも、実際の開発に注力したいですよね。
そんなときには、Dockerを使って開発環境を整備しましょう。

# Tensorflowを使ってみる
Tensorflowを単純に使う場合では、さほど手間はありません。公式が、Docker Imageを配布してくれています。必要な手順は以下の通り。

1. Dockerのアカウント作成
2. Docker Desktopのインストール
3. Docker Imageを取得し起動する

```bash
# 手元のdockerコンテナを確認します。
$ docker ps
CONTAINER ID  IMAGE  COMMAND  CREATED  STATUS  PORTS  NAMES
# ↑コンテナがないので、何も表示されないですね。
```

docker hubにtensorflowのコンテナが用意されています。
https://hub.docker.com/r/tensorflow/tensorflow/

```bash
# docker hubからコンテナを取得します。
$ docker run -it -p 8888:8888 tensorflow/tensorflow
Unable to find image 'tensorflow/tensorflow:latest' locally
latest: Pulling from tensorflow/tensorflow
18d680d61657: Pull complete 
0addb6fece63: Pull complete 
78e58219b215: Pull complete 
eb6959a66df2: Pull complete 
4263945a5710: Pull complete 
282d99d903f2: Pull complete 
dd620fc3ae28: Pull complete 
aa8e48babf4b: Pull complete 
27c088fb1ccc: Pull complete 
ca88730530b5: Pull complete 
5f530f9c7fc4: Pull complete 
8ea52f77069e: Pull complete 
Digest: sha256:hogehogehoge
Status: Downloaded newer image for tensorflow/tensorflow:latest
[I 13:13:43.336 NotebookApp] Writing notebook server cookie secret to /root/.local/share/jupyter/runtime/notebook_cookie_secret
[I 13:13:43.365 NotebookApp] Serving notebooks from local directory: /notebooks
[I 13:13:43.365 NotebookApp] The Jupyter Notebook is running at:
[I 13:13:43.366 NotebookApp] http://(8460e9915d36 or 127.0.0.1):8888/?token=hogehogehoge
[I 13:13:43.366 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
[C 13:13:43.368 NotebookApp] 
    
    Copy/paste this URL into your browser when you connect for the first time,
    to login with a token:
        http://(8460e9915d36 or 127.0.0.1):8888/?token=hogehogehoge
```
※tokenについてはぼかしています。

下記のローカルホストへアクセスしてみましょう。
http://127.0.0.1:8888/?token=hogehogehoge
すると、jupyterが立ち上がります。ここまでくれば、Tensorflowを使うことが可能です。
<img width="1436" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/50627/9a028ae3-0701-f0e5-2b17-86353d678fc9.png">

# Tensorflow×OpenCV3

Tensorflowが使えるようになったら、OpenCVも使ってみたくなりますよね。
OpenCVを使えば、画像の前処理なんかがやりやすくなります。
`pip install opencv-python`だと、`contrib`系のライブラリがインストールされなかったりなど、追加でインストールするのが手間です。
そんなときは、OpenCVをビルドしてしまいましょう。OpenCVのビルドオプションは結構複雑ですので、今回解説することは割愛させていただいたいと思います。

以下のようなDockefileを作成してみました。
OpenCVのバージョンが3.2.0と少し古いので、最新の4.0.0に変更しても良いかもしれません。

```Dockefile:Dockefile
FROM tensorflow/tensorflow:latest-py3

RUN apt-get update && \
    apt-get install -y --no-install-recommends \
        build-essential \
        cmake \
        pkg-config \
        libjpeg8-dev \
        libtiff5-dev \
        libjasper-dev \
        libpng12-dev \
        libavcodec-dev \
        libavformat-dev \
        libswscale-dev \
        libv4l-dev \
        libxvidcore-dev \
        libx264-dev \
        libgtk-3-dev \
        libatlas-base-dev \
        gfortran \
        python3-dev \
        python3-numpy \
        wget \
        && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

RUN mkdir -p /tmp && \
    cd /tmp && \
    wget -O opencv.zip https://github.com/opencv/opencv/archive/3.2.0.zip && \
    unzip opencv.zip && \
    mkdir opencv-3.2.0/build && \
    cd opencv-3.2.0/build && \
    cmake -D CMAKE_BUILD_TYPE=RELEASE \
        -D CMAKE_INSTALL_PREFIX=/usr/local \
        -D PYTHON3_EXECUTABLE=/usr/bin/python3 \
        -D WITH_CUDA=ON \
        -D CUDA_FAST_MATH=1 \
        -D WITH_CUBLAS=1 \
        -D CMAKE_LIBRARY_PATH=/usr/local/cuda/lib64/stubs \
        .. && \
    make -j$(nproc) && \
    make install && \
    ldconfig && \
    cd /tmp && \
    rm -rf opencv-3.2.0 opencv.zip

RUN pip install numpy
```
※今回は、GPUを使わない設定です。

```bash
# Dockefileを作成したディレクトリに移動
$ cd tensorflow_opencv3_work
# コンテナをビルド（OpenCVのビルドも含むため少し時間がかかります）
$ docker build -t tensor-opencv .
Successfully built 28f644893dfe
Successfully tagged tensor-opencv:latest
# ビルドが終わったら、imagesを確認しておきましょう
$ docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
tensor-opencv           latest              28f644893dfe        30 seconds ago      1.85GB
<none>                  <none>              649fe14a57d2        5 hours ago         1.23GB
<none>                  <none>              821ebfcc47b9        5 hours ago         1.22GB
python                  3.6                 1ec4d11819ad        4 weeks ago         918MB
tensorflow/tensorflow   latest-py3          39bcb324db83        5 weeks ago         1.33GB
tensorflow/tensorflow   latest              2054925f3b43        5 weeks ago         1.34GB
# 今回作成した、tensor-opencvを起動する
$ docker run --rm -it -p 8888:8888 -v $(pwd):/workdir -w /workdir tensor-opencv
```

無事jupyterが立ち上がりました。
OpenCVがインポートできるか確認しておきましょう。インポートできバージョンが確認できたら、ひとまず環境構築は完了です。

<img width="1436" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/50627/db748e86-9134-2a50-f3b3-ad08f2bc10c1.png">


# おつかれさまでした
無事、Dockerを使ってTensorflowとOpenCVの開発環境を構築できましたね。
あとは、バリバリ開発していくだけです！
それは、冬休みにやりましょうかね。今回は、ここまで。おつかれさまでした！