AWS Lambda で OpenCV と Pillow を使う環境を準備する

こちらと同じようなことをやってみたくなったので、開発環境を作りました。
[AWS Lambdaを使ったサムネール作成でNode.jsとPythonを比較してみた](http://qiita.com/tanakatsu1080/items/a41bdbdd79760edb07d5)

Pillowは、EC2でビルドする必要があるそうです。インスタンスを立ち上げても良かったのですが、[Amazon Linux Container Image](http://docs.aws.amazon.com/AmazonECR/latest/userguide/amazon_linux_container_image.html)とDockerを使えばローカルでもできると思いました。

# Pillowのビルド

このあたりを参考にしました。
[画像処理ライブラリ「Pillow」をAWS Lambdaで使ってみる](http://developer.wonderpla.net/entry/blog/engineer/Lambda_Python_Pillow/)
[デプロイパッケージを作成する](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/with-s3-example-deployment-pkg.html#with-s3-example-deployment-pkg-python)

# OpenCVのビルド

こちらを参考にしました。
[AWS LambdaのPythonから利用出来るOpenCV3.0のライブラリを作成する手順](https://gist.github.com/mmitou/2299686a8771495dcd67)

出来上がった cv2.soファイルは、47MBもありました。[Lambda関数デプロイパッケージの制限](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/limits.html)は50MBだそうなので、すでにお腹いっぱいです。OpenCVの使わないモジュールを外して、soファイルをダイエットしました。
[Build specific modules OpenCV](http://stackoverflow.com/questions/25594003/build-specific-modules-opencv)

Dockerfileです。

``` Dockerfile
FROM amazonlinux:latest

RUN yum update -y
RUN yum install python27-devel python27-pip gcc gcc-c++ cmake git zip -y
RUN yum install libjpeg-devel zlib-devel -y
RUN pip install --upgrade pip
RUN pip install virtualenv numpy

ENV HOME /home/lambda-py
RUN mkdir $HOME
WORKDIR $HOME

RUN git clone https://github.com/opencv/opencv.git
WORKDIR $HOME/opencv
WORKDIR $HOME/opencv/build
RUN cmake -D CMAKE_BUILD_TYPE=RELEASE -D BUILD_SHARED_LIBS=NO -D BUILD_opencv_python2=ON -D BUILD_opencv_calib3d=OFF -D BUILD_opencv_objdetect=OFF -D BUILD_opencv_ml=OFF -D BUILD_opencv_features2d=OFF -D BUILD_opencv_stitching=OFF -D BUILD_opencv_videostab=OFF -D BUILD_opencv_flann=OFF -D BUILD_opencv_superres=OFF  -D BUILD_opencv_shape=OFF -D BUILD_opencv_ts=OFF -D BUILD_opencv_video=OFF -D BUILD_opencv_videoio=OFF -D CMAKE_INSTALL_PREFIX=/usr/local ..
RUN make install

WORKDIR $HOME
RUN virtualenv $HOME/venv
```

この設定でビルドすると、OpenCVの多くのモジュールがdisabledになりますが、その分soファイルはぐっと小さくなります。

```bash
<ビルドログから抜粋>
--   OpenCV modules:
--     To be built:                 core imgproc photo imgcodecs highgui python2
--     Disabled:                    calib3d features2d flann ml objdetect shape stitching superres ts video videoio videostab world
--     Disabled by dependency:      -
--     Unavailable:                 cudaarithm cudabgsegm cudacodec cudafeatures2d cudafilters cudaimgproc cudalegacy cudaobjdetect cudaoptflow cudastereo cudawarping cudev java python3 viz


(venv) bash-4.2# ls -l /usr/local/lib/python2.7/dist-packages/      
total 40544
-rwxr-xr-x 1 root root 41510502 Nov 29 03:54 cv2.so
```

# デプロイパッケージを作る

出来上がったコンテナを立ち上げて、Lambdaにデプロイするパッケージ(zipファイル)を作ります。

```bash
bash-4.2# source $HOME/venv/bin/activate
(venv) bash-4.2# pip install Pillow numpy
(venv) bash-4.2# cp /usr/local/lib/python2.7/dist-packages/cv2.so ~/venv/lib/python2.7/site-packages/
(venv) bash-4.2# cd ~/venv/lib/python2.7/site-packages
(venv) bash-4.2# zip -r9 ~/lambda_function.zip *
(venv) bash-4.2# cd ~/venv/lib64/python2.7/site-packages
(venv) bash-4.2# zip -r9 ~/lambda_function.zip *
```

コードはホスト側で編集し、コンテナのsrcフォルダにマウントしたフォルダに入れてあります。

```bash
(venv) bash-4.2# cd ~/src
(venv) bash-4.2# zip ~/lambda_function.zip lambda_test.py 
```

デプロイパッケージが出来ました！

```bash
(venv) bash-4.2# ls -l
total 39736
-rw-r--r--  1 root root 40680005 Nov 29 04:51 lambda_function.zip
drwxr-xr-x 19 root root     4096 Nov 29 03:54 opencv
drwxr-xr-x  4 root root      136 Nov 29 04:50 src
drwxr-xr-x  8 root root     4096 Nov 29 04:39 venv
```

あとは、このzipファイルをホスト側に持ってきて、AWSコンソールやCLIなどでLambdaにデプロイすればいいと思います。
コンテナで作業してもいいと思いますが、その場合は、AWS CLIをインストールする必要があります。