サーバレスで画像のモザイク処理を作ってみた①
こんにちは、保険システム部の宮内です。
AWSの画像分析サービスであるAmazon Rekognitionを利用して顔にモザイクをかける、という紹介ページはいくつかありますが、サーバ(EC2)を利用しているものがほとんどです。
今回はEC2に頼らず、サーバレスで顔のモザイク処理を作ってみたいと思います。
今回は実装の下準備まで説明し、モザイク処理の実装内容は次回説明します。
Lambdaでライブラリを利用する方法
今回はモザイク処理の実装のため、Pythonの画像編集ライブラリであるPillow(PIL)をLambdaで利用します。
しかしLambdaでは、Pillowのようなライブラリを標準で利用することができません。実際、インポートしようとするとエラーが発生します。

Pillowのようなライブラリを利用するには、次の2つの対応方法があります。
1.Lambdaの実行ファイル(Lambda関数)と必要なライブラリでZipファイルを作成し、Lambdaにアップロード(Lambda関数を作成)する
2.必要なライブラリでZipファイルを作成し、Lambda Layerにアップロードする
今回は2つ目の方法で実装しますが、まずはLambda Layerについて簡単に説明します。
Lambda Layerとは
Lambda Layerはre:Invent 2018で発表された機能で、ライブラリをレイヤーに設定することにより、複数のLambdaで共有して利用できる仕組みになります。

Lambdaでライブラリを使いたい場合、Lambda Layerが登場するまでは、Lambda関数と使用するライブラリをまとめてLambdaを作成する必要がありましたが(左図)、Lambda Layerを利用することでライブラリを複数のLambdaで共有して利用できるようになります(右図)。
Lambda Layerを利用するためにZipファイルを用意する必要がありますが、Zipファイル作成では注意すべきことが2つあります。
【注意点1】Zipファイルを作成するサーバのOS
LambdaのOSは「Amazon Linux」、または「Amazon Linux2」が使用されています。
使用するプログラム言語やバージョンによって使用するOSも変わりますが、「Zipファイルを作成するサーバのOS」は「コードを実行するLambdaのOS」に合わせる必要があります。
次の表は、LambdaにおけるPythonの実行環境の一覧です。

注意点を踏まえると、
- Python3.7はAmazon Linuxで実行されるため、OSがAmazon LinuxのサーバでZipファイルを作成
- Python3.8はAmazon Linux2で実行されるため、OSがAmazon Linux2のサーバでZipファイルを作成
といった考慮が必要になる訳です。
その他のプログラム言語と対応するOSについては、以下の公式ドキュメントをご覧下さい。
https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html
【注意点2】Zipファイルのフォルダ構成
Lambda Layerに設定したモジュールは、
from PIL import Image
といったように、パスを特別に設定すること無く、自然にインポートして利用したいですよね。
この場合、Zipファイルを固める際のフォルダ構成に注意する必要があります。
前提として、PythonにおけるLambda Layerでは以下の2つの仕様があります。
- Lambda LayerにアップロードしたZipファイルは /opt 配下に展開される
- /opt 配下の特定のパスは、あらかじめライブラリ検索用のパスとして設定されている
ライブラリ検索用の「特定のパス」について、システムパス(sys.path)を確認するプログラムコードをLambdaで実行してみましょう。
import sys
def lambda_handler(event, context):
# sys.pathを確認
return {
'sys.path' : sys.path
}
実行すると、以下のような結果となります。

この中で /opt 配下のパスとして設定されているのは
- /opt/python
- /opt/python/lib/python3.8/site-packages
の2つなので、Zipファイルを固める際には、以下のフォルダ構成にすると自然にインポートできます。
- python
└(Lambda Layerに設定したいライブラリ群) - python
└ lib
└ python3.8
└ site-packages
└(Lambda Layerに設定したいライブラリ群)
2つ目はフォルダの階層が多く複雑なので、今回は1つ目のフォルダ構成でZipファイルを作成します。
Zipファイルの作成
Zipファイル作成のため、ここではEC2を利用します。
(モザイク処理でEC2は使わないですが、準備ではEC2が必要です…)
EC2インスタンスの作成
EC2インスタンス構築時の注意点をまとめます。
Amazon Machine Image(AMI)、及びインスタンスタイプは無料利用枠の対象のものでOKです。
今回はZipファイル作成が目的なので、高いスペックは必要ありません。


最後にキーペアの選択を求められますが、SSHクライアントソフト(Tera Term、WinSCP等)を利用してZipファイルを取得する場合は、ここで設定するキー(pemファイル)が必要となります。
(今回は、SSHクライアントソフトを使用しない方法でEC2へアクセスします)

注意点は以上です。
その他、セキュリティ設定等は必要に応じて設定頂いて構いません。
SSH接続してコマンド実行
次に、作成したEC2インスタンスにSSH接続してZipファイルを作成します。
今回はEC2 Instance Connectを利用して接続します。
EC2 Instance ConnectはブラウザベースのSSHクライアントで、AWSマネジメントコンソールから利用できます。
EC2のインスタンス一覧から先ほど作成したインスタンスを選択し、右上の「接続」をクリックします。

EC2インスタンスの接続方法が表示されますので、EC2 Instance Connectを選択して接続します。

接続すると、SSHクライアントの画面がブラウザ上で開きます。

早速、コマンドを実行していきましょう!
Python3.8のインストール
Amazon Linux2には標準でPython2.7が入っていますが、今回はPython3.8を利用するため、まずはPython3.8をインストールします。Python2.7のアンインストールは不要です。
# Python3.8 をインストール
sudo amazon-linux-extras install python3.8
実行するとインストールの可否の確認があるため、y(YES)を入力します。

これでPython3.8がインストールされます。
バージョンを確認すると、インストールされていることが確認できます。

Pillowのインストール
次にPillowのインストールです。
まずは「python」という名前のディレクトリを作成しましょう。
# フォルダを作成
mkdir python
mkdirは「make directory」の略で、ディレクトリを作成するコマンドです。
次にpipというPythonのライブラリを管理するコマンドを利用し、Pillowをインストールします。
# Pillowのインストール
pip3.8 install Pillow -t python
「-t」のオプションを付ける事で、インストール先のディレクトリを指定できるので、pythonディレクトリを指定しています。

Zipファイル作成
最後にZipファイルの作成です。以下のコマンドを実行しましょう。
# Zipファイルの作成
# 【例】 zip -r (作成するZipファイル名)(圧縮対象のディレクトリ名)
zip -r PIL.zip python
「-r」はZip圧縮の対象をディレクトリとする際に必要なオプションになります。
作成するZipファイル名は好きなように設定頂いてOKです。

Zipファイルの転送
Lambda LayerにZipファイルを設定する方法として、
- PC内に保存したZipファイルをアップロード
- S3に保存したZipファイルをアップロード
の2通りがあります。
今回は2つ目の方法を利用するため、EC2で作成したZipファイルをS3にアップロードしたいと思います。
S3バケットの作成
バケットを作成する際の注意点としては、S3とEC2を連携するので、S3のリージョンはZipファイルの作成で利用したEC2のリージョンと合わせる必要があります。
他の注意点はありません。全てデフォルト値でOKです。

AWS CLIへアカウント情報紐づけ
次にEC2のAWS CLIに対して、IAMユーザのアカウント情報と紐づけを行います。
紐づけで必要になるのが、使用しているIAMユーザのアクセスキーID、シークレットアクセスキーです。
使用しているIAMユーザの認証情報からアクセスキーの作成が可能です。
手元にアクセスキーの情報が無ければ作成し、アクセスキーIDとシークレットアクセスキーを控えておきましょう。

それでは、EC2 Instance ConnectからAWS CLIを利用して、アカウントの紐づけを行います。
AWS CLIはEC2に標準でインストールされています。AWS CLIの設定を行うために、以下のコマンドを実行しましょう。
# AWS CLIの設定を行う
aws configure
実行するとアクセスキーID、シークレットアクセスキー、AWSリージョン、出力形式の入力を求められます。
今回はアクセスキーID、シークレットアクセスキーのみ入力でOKです。リージョン、出力形式は使用しないので、未設定で構いません。

これでアカウントの紐づけは完了です。
確認のため、S3情報を取得してみましょう。
# アカウントに紐づくS3の情報を取得
aws s3 ls
正常に紐づけができていれば、S3のバケット情報を取得できます。
転送先のS3が表示されていることを確認して下さい。(receive-from-ec2 というバケットがファイル転送先です)

EC2からS3へファイル転送
いよいよS3へZipファイルを転送します。以下のコマンドを実行しましょう。
# ファイル転送
# 【例】 aws s3 cp (転送ファイル名) s3://(転送先のS3バケット名)
aws s3 cp ./PIL.zip s3://receive-from-ec2
コマンド実行後、「upload: …」と表示されればアップロード成功です!

S3にファイルがあることも確認できました。

EC2 Instance Connectは「exit」と入力するとSSH接続を切断できます。
また、S3にZipファイルが転送できたら、EC2の役目は終了なので停止しましょう。
(停止し忘れて課金されないように気を付けましょう!)
Lambda Layerの設定
いよいよLambda Layerの設定です。
まずはLambda LayerにZipファイルをアップロードしてレイヤーを作成し、次にLambdaへレイヤーの適用を行います。
レイヤーの作成
マネジメントコンソールからLambdaにアクセスし、レイヤーのページを開きます。
右上にある「レイヤーの作成」をクリックしましょう。

レイヤー設定の画面が開きますので、必要な項目を入力します。

注意すべき点として、AmazonS3のリンクURLには作成したZipファイルのオブジェクトURLを設定しましょう。

レイヤーの設定ページ下部にある「作成」ボタンを押下すると、レイヤーが作成されます。

Lambdaにレイヤー適用
最後に、作成したレイヤーをLambdaへ適用します。
レイヤーを適用するLambdaを開き、レイヤーのタブにある「レイヤーの追加」をクリックします。

追加するレイヤーを選択する画面が開きますので、必要な項目を入力します。
レイヤーはバージョン管理が自動で行われており、変更が行なわれる(Zipファイルを再度アップロードする)と、新しいバージョンで保存されます。新規作成のレイヤーはバージョンが1で設定されます。
右下の「追加」をクリックすると、Lambda Layerの設定が完了します。

インポート再実行
改めて、インポートエラーとなったコードを実行すると…

無事、Pillowのインポートエラーが解消できました!
以上で下準備は完了です。
さいごに
今回はモザイク処理実装の下準備として、EC2を利用したZipファイルの作成、及びS3への転送と、Lambda Layerの設定まで行いました。
次回はモザイク処理の実装について説明したいと思います。
次回のキーワードは「BytesIO」と「BoundingBox」です!