読者です 読者をやめる 読者になる 読者になる

WonderPlanet DEVELOPER BLOG

ワンダープラネットの開発者ブログです。モバイルゲーム開発情報を発信。

画像処理ライブラリ「Pillow」をAWS Lambdaで使ってみる

AWS Python

今回のエンジニアブログを担当する村田です。

前回は、Pythonを使ったAWS Lambdaでスケジュール化を試しました。
今回は、画像処理ライブラリである「Pillow」をAWS Lambdaで使いたいと思います。

Pillowとは?

Python Imaging Library (PIL)のforkプロジェクトで、

  • ピクセル毎の操作
  • マスキングと透明度の制御
  • ぼかし、輪郭補正、スムージング、輪郭検出などの画像フィルタ
  • シャープ化、明るさ補正、コントラスト補正、色補正などの画像の調整
  • 画像へのテキストの追加
  • その他いろいろ

といった様々な画像処理が可能なライブラリです。

実は前回使おうとしたのですが、このPillowというライブラリ、
インストール時に環境に合わせてビルドをするため、普通にMac上で環境を構築すると実行時にエラーが発生します。

Unable to import module 'lambda_function': /var/task/PIL/_imaging.so: invalid ELF header  

AWS LambdaはEC2上で動いているようなものなので、今回はEC2(Amazon Linux AMI 2015.09)上で構築していきます。

環境構築

Amazon Linuxで構築したEC2に接続します。

まず、Pillowをビルドするのに必要なものをインストールします。

$ sudo yum install python-devel  
$ sudo yum install libtiff-devel libjpeg-devel libzip-devel freetype-devel \  
  lcms2-devel libwebp-devel tcl-devel tk-devel  
$ sudo yum install gcc  

準備が整いましたら、AWS Lambda を実装する作業ディレクトリに移動し、setup.cfgを編集します。
Amazon Linuxに合わせた設定ですので、環境に合った内容を記載してください。

[install]  
install-purelib=$base/lib64/python  

AWS LambdaにPillowをインストールします。

$ pip install Pillow -t .  

インストールに成功すると、以下のようなディレクトリ構成になります。

<workdir>  
├── PIL  
│   ├── BdfFontFile.py  
│    :  
│    :  
├── Pillow-3.1.0.egg-info  
│   ├── PKG-INFO  
│    :  
│    :  
├── lambda_function.py  
└── setup.cfg  

では、lambda_function.pyを編集して、実装しましょう。

実装

今回の実装内容は以下の通りです。

  1. inputフォルダにPNG画像をPut
  2. Lambdaが起動しPutした画像からサムネイルを作成
  3. サムネイルをoutputフォルダに出力

2と3が、今回作成するLambdaが担当する処理です。

S3のBucket内は、以下のようにフォルダを作成します。

<Bucket>  
├── input  
└── output  

実装内容です。

from PIL import Image  
import boto3  
import os  
import re  
  
s3 = boto3.client('s3')  
  
def lambda_handler(event, context):  
    bucket = event['Records'][0]['s3']['bucket']['name']  
    key = event['Records'][0]['s3']['object']['key']  
    tmp = u'/tmp/' + os.path.basename(key)  
    output = re.sub(r'^input/', u'output/', key)  
    try:  
        s3.download_file(Bucket=bucket, Key=key, Filename=tmp)  
        img = Image.open(tmp, 'r')  
        img.thumbnail((80, 80), Image.ANTIALIAS)  
        img.save(tmp, 'PNG')  
        s3.upload_file(Filename=tmp, Bucket=bucket, Key=output)  
        return  
    except Exception as e:  
        print(e)  
        raise e  

11行目で、/tmp/へのパスを生成しておりますが、今回のプログラムでは、S3上にアップされたPNG画像を /tmp/ 配下に一旦ダウンロード(14行目)します。
Lambdaから/tmp/へのアクセスが可能で、/tmp/の容量は 500MB となっております。

16行目で 80x80 のサムネイルを作成します。
18行目で 作成したサムネイルを output フォルダにアップします。

今回は、以下のようにevent sourcesを設定することで、inputにPutしたpng拡張子にしか反応しないようにしました。
BucketSetting

まとめ

Pillowが扱えるということで、複雑な画像処理がAWS Lambda上で実現できるようになりました。
Pillowに限らずビルドを必要とするライブラリをAWS Lambda上で扱えるというのは、Pythonで実装するAWS Lambdaの可能性がより広がります。

ますますPythonで実装するAWS Lambdaが好きになりました。