画像処理を
AWS LambdaのPythonで!
JAWS-UG Meetup in AWS Cloud Roadshow 名古屋
ワンダープラネット株式会社
取締役 CTO 村田知常
自己紹介
• 村田 知常(むらた ともつね)

  tomotsune.murata
• ワンダープラネット株式会社 取締役 CTO
• 好きな言語 Swift
• 好きなAWS

   Amazon S3
  ワンダープラネット株式会社
• 2012年9月3日 設立
• iOS/Android向けフルネイティブのソーシャルゲームを出してます
• AWSには大変お世話になってます!
本日、ver.1.1.6を配信!本日、ver.1.1.6を配信!
re:Invent2015で来ました
\(^O^)/
Lambda
+
• サーバーサイドのメイン言語
• MayaのPythonスクリプティング
• ちょっとしたコマンドラインツール
+
早速、試しました!
(-_☆)キラーン
• Pythonで実装
• RSSフィードを定期的に取得

→ 新機能 スケジュール化 の検証
• RSSフィードの解析に「feedpaser」

→ 外部ライブラリの利用
• CloudWatchのLogsに出力

→ printで手抜き
本当に試したかったのは
これではなかった…
S3に画像をアップしたら
Pythonライブラリを使って
画像を加工したい
※ 外部サービスは使わず
ブログアップ日に
間に合わなかった…
画像処理ライブラリ
使おう
とした
Python Imaging Library (PIL)のforkプロジェクト
• ピクセル毎の操作
• マスキングと透明度の制御
• ぼかし、輪郭補正、スムージング、輪郭検出などの画像フィルタ
• シャープ化、明るさ補正、コントラスト補正、色補正などの画像の調整
• 画像へのテキストの追加
• その他いろいろ
Unable to import module 'lambda_function': /
var/task/PIL/_imaging.so: invalid ELF header
普通にMac上で実装したものを
Lambdaで実行すると…
Pillowインストール時に環境に合わせて
一部ライブラリをビルドしている
Mac向けにビルドしたものは
Linux上では動かないよ
$ 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
EC2(Amazon Linux AMI 2015.09)上で構築
必要なライブラリをインストール
作業ディレクトリに移動
$ vim setup.cfg
[install]
install-purelib=$base/lib64/python
$ pip install Pillow -t .
Pillowのドキュメントに
沿ってインストール
ビルドに必要
(gcc無いのね…)
<workdir>
├── PIL
│   ├── BdfFontFile.py
│   :
│   :
├── Pillow-3.0.0.egg-info
│   ├── PKG-INFO
│   :
│   :
├── lambda_function.py ← このファイルを作成し実装
└── setup.cfg
完成するとこんな感じ
Macで作ると
Pillow-3.0.0.dist-info
準備完了
\(^O^)/
EC2(Amazon Linux AMI 2015.09)上で構築
Lambda functionの実装
• inputフォルダにPNG画像をPut
• Lambdaを起動しサムネイルを作成
• サムネイルをoutputフォルダに出力
Lambda functionの実装
オリジナル画像
80x80画像
Lambdaで
画像を加工
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']
print u'Bucket=' + bucket
print u'key=' + 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
Lambda functionの実装
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']
print u'Bucket=' + bucket
print u'key=' + 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
Lambda functionの実装
Bucketから
ファイルを取得
/tmp/下に保存
Lambdaから
/tmp/はアクセス可能
容量は500MB
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']
print u'Bucket=' + bucket
print u'key=' + 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
Lambda functionの実装
80 x 80
サムネイルを作成
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']
print u'Bucket=' + bucket
print u'key=' + 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
Lambda functionの実装
output/に
ファイルをアップロード
時間があったら
デモ
まとめ
• Pillowを使えば色々と凝った画像処理が可能
• ビルドを必要とするライブラリを

AWS Lambdaで使うノウハウを習得
• AWS LambdaをPythonで実装できる!
• これで開発・運用をサポートする

ツール作成が る
ご清聴ありがとうございました

画像処理をAWS LambdaのPythonで!

  • 1.
    画像処理を AWS LambdaのPythonで! JAWS-UG Meetupin AWS Cloud Roadshow 名古屋 ワンダープラネット株式会社 取締役 CTO 村田知常
  • 2.
    自己紹介 • 村田 知常(むらたともつね)
   tomotsune.murata • ワンダープラネット株式会社 取締役 CTO • 好きな言語 Swift • 好きなAWS
    Amazon S3
  • 3.
      ワンダープラネット株式会社 • 2012年9月3日設立 • iOS/Android向けフルネイティブのソーシャルゲームを出してます • AWSには大変お世話になってます! 本日、ver.1.1.6を配信!本日、ver.1.1.6を配信!
  • 4.
  • 5.
  • 6.
  • 7.
  • 9.
    • Pythonで実装 • RSSフィードを定期的に取得
 →新機能 スケジュール化 の検証 • RSSフィードの解析に「feedpaser」
 → 外部ライブラリの利用 • CloudWatchのLogsに出力
 → printで手抜き
  • 10.
  • 11.
  • 12.
  • 13.
    画像処理ライブラリ 使おう とした Python Imaging Library(PIL)のforkプロジェクト • ピクセル毎の操作 • マスキングと透明度の制御 • ぼかし、輪郭補正、スムージング、輪郭検出などの画像フィルタ • シャープ化、明るさ補正、コントラスト補正、色補正などの画像の調整 • 画像へのテキストの追加 • その他いろいろ
  • 14.
    Unable to importmodule 'lambda_function': / var/task/PIL/_imaging.so: invalid ELF header 普通にMac上で実装したものを Lambdaで実行すると… Pillowインストール時に環境に合わせて 一部ライブラリをビルドしている Mac向けにビルドしたものは Linux上では動かないよ
  • 15.
    $ sudo yuminstall 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 EC2(Amazon Linux AMI 2015.09)上で構築 必要なライブラリをインストール 作業ディレクトリに移動 $ vim setup.cfg [install] install-purelib=$base/lib64/python $ pip install Pillow -t . Pillowのドキュメントに 沿ってインストール ビルドに必要 (gcc無いのね…)
  • 16.
    <workdir> ├── PIL │   ├──BdfFontFile.py │   : │   : ├── Pillow-3.0.0.egg-info │   ├── PKG-INFO │   : │   : ├── lambda_function.py ← このファイルを作成し実装 └── setup.cfg 完成するとこんな感じ Macで作ると Pillow-3.0.0.dist-info 準備完了 \(^O^)/ EC2(Amazon Linux AMI 2015.09)上で構築
  • 17.
    Lambda functionの実装 • inputフォルダにPNG画像をPut •Lambdaを起動しサムネイルを作成 • サムネイルをoutputフォルダに出力
  • 18.
  • 19.
    from PIL importImage 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'] print u'Bucket=' + bucket print u'key=' + 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 Lambda functionの実装
  • 20.
    from PIL importImage 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'] print u'Bucket=' + bucket print u'key=' + 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 Lambda functionの実装 Bucketから ファイルを取得 /tmp/下に保存 Lambdaから /tmp/はアクセス可能 容量は500MB
  • 21.
    from PIL importImage 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'] print u'Bucket=' + bucket print u'key=' + 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 Lambda functionの実装 80 x 80 サムネイルを作成
  • 22.
    from PIL importImage 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'] print u'Bucket=' + bucket print u'key=' + 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 Lambda functionの実装 output/に ファイルをアップロード
  • 23.
  • 24.
    まとめ • Pillowを使えば色々と凝った画像処理が可能 • ビルドを必要とするライブラリを
 AWSLambdaで使うノウハウを習得 • AWS LambdaをPythonで実装できる! • これで開発・運用をサポートする
 ツール作成が る
  • 25.