こんにちは!
開発部の武内です。
エコモットアドベントカレンダーの10日目を担当します。
弊社では ミルモット や ジオスコープ をはじめとした、
画像・動画を扱うソリューションを展開しています。
今年、経済産業省・総務省・IoT推進コンソーシアムにより
カメラ画像利活用ガイドブックver1.0 が策定され、
それに追従するように札幌市などの自治体でも
防犯カメラに関するガイドライン が策定されるなど、
カメラで撮影された個人情報に対する意識・気運が高まっています。
そういった流れに対して、
エンジニアとしてはやはり技術で解決したい!ということで、
今回はAWSを利用して、画像内の個人情報の一つである顔を検出しモザイクをかける仕組みを作ってみました。
構成
Serverlessかつシンプルな構成にしました。
- Amazon S3 (モザイク処理前/処理後の画像を保存する)
- AWS Lambda + Python 2.7 + OpenCV 3.2 (モザイク処理を行う)
実装
OpenCVのビルド
まずはOpenCVをPythonで使用するためにソースコードからビルドを行います。
これにはCMakeや関連ライブラリを揃える必要があり少し面倒なところなのですが、
Python OpenCV module for AWS Lambda というビルドスクリプトを見つけたのでこちらを使用します。
ビルド環境としてEC2インスタンスを作成します。
今回は以下を作成しました。
- Amazon Linux (ami-da9e2cbc)
- t2.nano
作成したインスタンスにSSHしビルドを行います。
1 2 3 4 5 6 |
# Python OpenCV module for AWS Lambdaをダウンロード [ec2-user@ ~]$ wget https://github.com/aeddi/aws-lambda-python-opencv/archive/master.zip [ec2-user@ ~]$ unzip master.zip # ビルド [ec2-user@ ~]$ cd aws-lambda-python-opencv-master && ./build.sh |
t2.nanoだと30分ほどでビルドが完了しました。
モザイク処理コード
ビルドが完了するとlambda-packageディレクトリが作成されているので、
その中にモザイク処理コードを配置してLambda用にデプロイパッケージ化(zip)します。
また、顔検出には カスケード型分類器 を使用するので、
正面顔検出用の学習データをダウンロードします。
1 2 3 4 |
[ec2-user@ ~]$ cd ~/aws-lambda-python-opencv-master/lambda-package # カスケード型分類器で使用する正面顔検出用学習データをダウンロード [ec2-user@ lambda-package]$ wget https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_frontalface_default.xml |
モザイク処理コードは以下のように実装しました。
1 2 |
[ec2-user@ lambda-package]$ vim lambda_function.py |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# -*- coding: utf-8 -*- # lambda_function.py from __future__ import print_function import os import re import urllib import boto3 import cv2 s3 = boto3.client('s3') # 正面顔検出用学習データを読み込み cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') def lambda_handler(event, context): # S3のファイル情報を取得/設定 bucket = event['Records'][0]['s3']['bucket']['name'] key = urllib.unquote_plus(event['Records'][0]['s3']['object']['key'].encode('utf8')) tmp = u'/tmp/' + os.path.basename(key) output = re.sub(r'^input-data/', u'output-data/', key) try: # 処理前の画像を読み込み s3.download_file(Bucket = bucket, Key = key, Filename = tmp) before = cv2.imread(tmp) after = cv2.imread(tmp) # グレースケールに変換 gray = cv2.cvtColor(before, cv2.COLOR_RGB2GRAY) # カスケード型分類器で顔を検出 face = cascade.detectMultiScale(gray, 1.3, 5) if 0 < len(face): for (x, y, w, h) in face: # 顔を切り取りモザイク処理 cut_img = before[y:y+h, x:x+w] cut_face = cut_img.shape[:2][::-1] cut_img = cv2.resize(cut_img, (cut_face[0] / 10, cut_face[0] / 10)) cut_img = cv2.resize(cut_img, cut_face, interpolation = cv2.INTER_NEAREST) # モザイク処理した部分を重ねる after[y:y+h, x:x+w] = cut_img # 処理後の画像を保存 cv2.imwrite(tmp, after) s3.upload_file(Filename=tmp, Bucket=bucket, Key=output) os.remove(tmp) return except Exception as e: print(e) raise e |
デプロイパッケージ化します。
1 2 |
[ec2-user@ lambda-package]$ zip -r ../lambda-package.zip * |
画像保存用S3バケットの作成
face-mozaicというバケットを作成し、
配下にinput-dataとoutput-dataというフォルダを作成しました。
input-dataに画像をアップロードするとoutput-dataにモザイク処理された画像が作成されるようにします。
モザイク処理Lambda関数の作成
face-mozaicという関数を作成します。
ランタイムはPython 2.7を選択し、
ロールはS3へのアクセス権限があるものを設定します。
関数が作成されたらトリガーとしてS3を追加します。
トリガー設定で対象のバケットとしてface-mozaicを、プレフィックスとしてinput-dataを設定します。
一応サフィックスにjpgを指定し、jpgファイルにしかトリガーが反応しないようにしました。
先ほど作成したデプロイパッケージをアップロードします。
動作確認
では動かしてみます。
テストデータとして Pexels の写真を使用しました。
(Creative Commons Zero (CC0) license)
input-dataに画像をアップロードします。
少し待つとモザイク処理された画像がoutput-dataに作成されます。
結果を見てみましょう。
↓↓↓
顔にモザイクがかかりました!
複数人の場合でも同様にモザイクがかかります。
↓↓↓
横顔や動物の場合
正面顔検出用の学習データを使っていますので、
このままでは人間の横顔や動物の顔は検出できません。
それらにも学習データが公開されているので試してみましょう。
横顔には haarcascade_profileface.xml を使用します。
↓↓↓
横顔が検出できました。
猫の正面顔用の学習データも試してみました。
haarcascade_frontalcatface.xml を使用します。
↓↓↓
こちらはあまり精度が高くなかったので、
パラメータ調整などが必要かもしれませんね。
おわりに
いかがでしたでしょうか?
個人情報の切り分けや破棄は、人力では骨の折れる作業です。
画像認識も進歩していますので、どんどんシステム化していきたいですね。
皆さまの快適な開発生活の一助になれば幸いです。