今回は、AWS Lambda上でOpenCVを利用して、画像のサイズを変更する方法について紹介します。
目次
前提条件
開発環境
まず、前提条件として、開発環境はmacbookを利用しています。Python用のOpenCVをpipでインストールしただけでは、mac用のバイナリがインストールされてしまい、Lambda上ではうまく動作しません。
そのため、macにVirtualBoxでAmazon Linuxの仮想マシンを立て、その上で作業しました。
フォルダ構成
次にAWS Lambda用のフォルダ構成についてです。AWS Lambdaでは一つのフォルダ内に全ての必要なファイルをインストールする必要があります。今回は、OpenCVのような外部ライブラリと、自作のコードを分離するため、python_modulesというディレクトリを作成し、その中に外部ライブラリをインストールするようにしました。
+-- lambda_function.py # 自作ファイル | +-- python_modules # 外部モジュール用ディレクトリ | +-- cv2 # 外部モジュール
実現した手順
1.pipを利用してOpenCVをインストールする方法
まず、python_modulesというディレクトリを作成し、次のコマンドでOpenCVをpython_modulesにインストールされるようにします。
# pip3 install opencv-python -t ./python_modules
2.関数の作成
次にlambda_function.pyというファイルを作成し、次のコードをコピペします。
# -*- coding: utf-8 -*- import os, sys, math, boto3, json sys.path.append("./python_modules") import cv2 import numpy as np s3 = boto3.client('s3') def parseArgs(event): try: body = json.loads(event['body']) bucket = body["bucket"] inkey = body["inkey"] outkey = body["outkey"] return bucket, inkey, outkey except Exception as e: raise Exception def downloadImage(bucket, key): try: srcBucket = bucket tmpFile = "/tmp/" + os.path.basename(key) s3.download_file(Bucket=srcBucket, Key=key, Filename=tmpFile) img = cv2.imread(tmpFile) height, width, channels = img.shape return img, height, width except Exception as e: raise Exception def resize(img, size): try: resized = face_cascade.detectMultiScale(img, 1.02, 5) return resized except Exception as e: raise Exception def save(img, bucket, key): try: outFile = "/tmp/" + os.path.basename(key) cv2.imwrite(outFile, img) s3.upload_file(Filename=outFile, Bucket=bucket, Key=key) return True except Exception as e: raise Exception def handler(event, context): # bucket = "image-store" # key = "test/sample.png" # outKey = "test/sample_out.png" try: bucket, key, outKey = parseArgs(event) img, height, width = downloadImage(bucket, key) size = (height/2, width/2) img = resize(img, size) result = save(img, bucket, outKey) print("finished") return { "statusCode": 200, "headers": { "Access-Control-Allow-Origin": "*", "Content-Type": "application/json", }, "body": json.dumps({"status": "ok"}) } except Exception as e: return { "statusCode": 200, "headers": { "Access-Control-Allow-Origin": "*", "Content-Type": "application/json", }, "body": json.dumps({"status": "error", "message": e.args}) }
ここでは、まず、S3に保存された画像ファイルをLambdaの一時ディレクトリにダウンロードし、メモリに読み込みます。(downloadImage関数)
次に、読み込んだイメージの縦と横の長さが元の画像の2分の1になるよう画像をリサイズします。(resize関数)
最後に作成した画像を一時ディレクトリに一旦保存し、S3にアップロードします。(save関数)