HaneCa

独り立ちへ向けた長い道

AWS LambdaでOpenCVで画像処理する方法

投稿日: 2019年1月1日

今回は、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関数)

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください