はじめに
AWS Lambda で OpenCV を使用するにはいくつかの方法がある。
- Lambda 関数のデプロイパッケージに OpenCV を含める
- OpenCV 用の Lambda Layers をビルドして使用する
前者の「Lambda 関数のデプロイパッケージに OpenCV を含める」方法の場合は、Lambda のデプロイパッケージサイズの上限 50 MB のうち、そのほとんどが OpenCV のために使用されてしまう。後者の Lambda Layers を使用すると、ライブラリをデプロイパッケージに含める必要がなくなり、パッケージのサイズを小さくすることができる。また、ライブラリを外部化することで、OpenCV のバージョンアップなども行いやすくなると考えられる。
そこで本稿では、AWS Lambda (Python 3.7) 向けに OpenCV 3.4 の Lambda Layers をビルドし、実際にビルドした Layers を使用して OpenCV 3.4 を Lambda で動作させるまでの手順をまとめた。
OpenCV 3.4 Layer の作成
https://qiita.com/hajimen/items/4419ba0182fc6d008896 を参考に Docker を使用したビルドを行なったが、Python 3.7 と OpenCV 3.4.7 の組み合わせでは、先の記事の方法では上手くいかなかった。そこで、以下のような Dockerfile
を作成した。
FROM lambci/lambda:build-python3.7
ENV OPENCV_VERSION 3.4.7
RUN curl -fsSLO https://github.com/opencv/opencv/archive/$OPENCV_VERSION.tar.gz \
&& tar -zxf $OPENCV_VERSION.tar.gz \
&& mv opencv-$OPENCV_VERSION opencv
RUN curl -fsSLO https://github.com/opencv/opencv_contrib/archive/$OPENCV_VERSION.tar.gz \
&& tar -zxf $OPENCV_VERSION.tar.gz \
&& mv opencv_contrib-$OPENCV_VERSION opencv_contrib
RUN yum install -y cmake3
RUN pip install --upgrade pip && pip install numpy
RUN mkdir opencv/build \
&& cd opencv/build \
&& cmake3 \
-DBUILD_SHARED_LIBS=NO \
-DCMAKE_BUILD_TYPE=RELEASE \
-DCMAKE_INSTALL_PREFIX=../../python \
-DOPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules \
-DPYTHON3_EXECUTABLE=/var/lang/bin/python .. \
&& make install
RUN find python/lib -name *.so | xargs -n 1 strip -s
RUN zip -ry9 cv2.zip python/lib
CMD cp cv2.zip /share
同じ要領で docker-compose.yml
も作成。
version: '2'
services:
app:
build:
context: .
volumes:
- .:/share
この 2 個のファイルが存在するディレクトリで以下のコマンドを順に実行すると、カレントディレクトリに cv2.zip
が生成される。
docker-compose build
docker-compose up
生成された cv2.zip
を AWS Lambda マネジメントコンソールから Layers としてアップロードすれば完了。
動作確認
以下の Lambda 関数を作成し、AWS により用意されているレイヤー AWSLambda-Python37-SciPy1x(これに NumPy が含まれている)および上で作成した OpenCV 3.4 のレイヤーを使用するように設定し、実行した。
import numpy as np
import cv2
def lambda_handler(event, context):
print(cv2.__version__)
その結果、以下のようなエラーが発生した。
[ERROR] Runtime.ImportModuleError: Unable to import module 'lambda_function': numpy.core.multiarray failed to import
どうやら NumPy のバージョンが古い場合に発生するエラーらしい。そこで NumPy の Layer も自作することに。
NumPy 1.17 Layer の作成
先ほどと同じ要領で以下の Dockerfile
を作成した。
FROM lambci/lambda:build-python3.7
RUN pip install --upgrade pip && pip install -t python numpy
RUN zip -ry9 numpy.zip python
CMD cp numpy.zip /share
このあとは OpenCV のときと同様の手順を実行すればカレントディレクトリに numpy.zip
が生成されるので、これを AWS Lambda マネジメントコンソールから Layers としてアップロードすれば完了。
動作確認
以下の Lambda 関数を作成し、自作の 2 つのレイヤーを使用するように設定し、実行した。
import numpy as np
import cv2
def lambda_handler(event, context):
print(cv2.__version__)
その結果、以下の出力を得た。
3.4.7
OpenCV のバージョンが出力されていることから、AWS Lambda (Python 3.7) で OpenCV 3.4 が正常に動作したことが確認できた。