Amazon Rekognitionを用いて顔の位置を判別してぼかしを入れるスクリプトを書いてみようと思います!!
Pythonも使用します。
流れ
Pythonも使うのでスクリプトがごちゃごちゃしちゃうので大まかな流れを書き出していきます
- Amazon Rekognitionを用いて画像を解析する
↓
- 顔の位置がBoundingBoxという値で出力されるのでその部分だけ抜き出す
↓
- Pillow(Python対応の画像処理ライブラリ)を用いて顔の位置にモザイクをいれる編集をして保存
という流れでモザイクをいれます
準備
今回はAmazon Linux2を使いました
awscliはAmazon Linux 2にもともと入っているのでインストールは割愛します
aws configure
でawscliを使えるようにアクセスキーとシークレットキーの設定をします(こちらも割愛)
スクリプト
sample.jpgという名前のこの画像を使ってモザイクいれていきます!
1. Amazon Rekognitionを用いて画像を解析する
RekognitionではPython、boto3を使うのでインストールします
pip install boto3
AWS S3を介してRekognitionと通信するのでまずはawscliでS3に画像をアップロードします
aws s3 cp sample.jpg s3://{バケット名}
新しいバケットを使用したい場合はこのコマンドでバケット作成できます
aws s3 mb s3://{バケット名}
画像をアップできたらRekognitionで解析します
reko.py(Python)
import boto3 import json if __name__ == "__main__": photo='sample.jpg' bucket='{バケット名}' client=boto3.client('rekognition') response = client.detect_faces(Image={'S3Object':{'Bucket':bucket,'Name':photo}},Attributes=['ALL']) print('Detected faces for ' + photo) for faceDetail in response['FaceDetails']: print(json.dumps(faceDetail, indent=4, sort_keys=True))
reko.pyを実行すると
{ "AgeRange": { "High": 38, "Low": 23 }, "Beard": { "Confidence": 98.78243255615234, "Value": false }, "BoundingBox": { "Height": 0.11876832693815231, "Left": 0.4677734375, "Top": 0.47214075922966003, "Width": 0.0791015625 }, "Confidence": 99.98953247070312, "Emotions": [ { "Confidence": 79.13528442382812, "Type": "HAPPY" }, { "Confidence": 3.9083898067474365, "Type": "SURPRISED" }, { "Confidence": 2.7034223079681396, "Type": "SAD" } ], . . .
このように解析結果が出力されます
結果をreko.jsonというファイルに保存しておきます。
2. 顔の位置がBoundingBoxという値で出力されるのでその部分だけ抜き出す
顔の位置はBoundingBoxというパラメータで出力されます
BoundingBoxは画像全体との比率で出力されます
また左上を原点としているので左上が(0, 0)、右下が(1, 1)になります
まずはreko.jsonの1行目が不要なので
sed -e '1d' ./reko.json > reko1.json
で1行目を削除して念の為元のファイルは残してreko1.jsonを用います
reko1.jsonの中で必要なのはBoundingBoxの値だけなのでBoundingBoxだけ抜き出します
jq '.BoundingBox[]' reko1.json > BoundingBox.txt
jqコマンドを使いました。jsonファイルだと使いづらいのでtxtファイルに書き込みました
3. Pillow(Python対応の画像処理ライブラリ)を用いて顔の位置にモザイクをいれる編集をして保存
いよいよ画像にモザイクをいれていきます
PillowというPythonの画像処理ライブラリを使うのでまずはインストールします
pip install pillow
BoundingBoxの値は比率なのでそれぞれに画像全体のサイズをかけ合わせて顔の位置の座標を出し、その位置を指定して顔の部分だけにモザイクをいれるという流れでプログラムを書いていこうと思います
pillow.py
from PIL import Image, ImageFilter, ImageDraw im = Image.open('./sample.jpg') #編集する画像を読み込む iw = im.width #画像の幅 ih = im.height #画像の高さ f = open('BoundingBox.txt', 'r') #BoundingBox.txtを読み込む a = [] a = f.readlines() #BoundingBox.txtを1行ずつ読み込んで配列に値をいれる f.close() #BoundingBox.txtをクローズ width = [] top = [] left = [] height = [] #aにはheight→left→top→widthの順に値が入っているのでheightならheightなどそれぞれの配列にいれる for i, value in enumerate(a): if i % 4 == 0: height.append((float)(a[i])*ih) #まだ比率だからihをかけ合わせた値を配列にいれる continue elif i % 4 == 1: left.append((float)(a[i])*iw) continue elif i % 4 == 2: top.append((float)(a[i])*ih) continue else : width.append((float)(a[i])*iw) continue num = len(width) for j in range(num): #1人ずつ読み込む x1 = left[j] #左上のx座標 y1 = top[j] #左上のy座標 x2 = x1 + width[j] #右下のx座標 y2 = y1 + height[j] #右下のy座標 imcopy = im.copy() #もとの画像のコピーをとる imcut = imcopy.crop((x1, y1, x2, y2)) #顔の部分を切り取り gimg = imcut.resize([x // 8 for x in imcut.size]).resize(imcut.size) #顔の部分にモザイク処理 im.paste(gimg, (int(x1), int(y1))) #もとの画像にモザイクをかけた画像をペースト im.save('./mosaic-sample.jpg', quality=95) #編集した画像をmosaic-sample.jpgとして保存
pillow.pyを実行し、できたmosaic-sample.jpgは
モザイクかかりました!
aws s3 cp mosaic-sample.jpg s3://{バケット名}
でS3にアップして完成です!!
まとめると
ややこしかったのでシェルスクリプトにまとめると
#!/bin/bash pip install boto3 aws s3 cp sample.jpg s3://{バケット名} python reko.py > reko.json sed -e '1d' ./reko.json > reko1.json jq '.BoundingBox[]' reko1.json > BoundingBox.txt pip install pillow python pillow.py aws s3 cp mosaic-sample.jpg s3://{バケット名}
最後に
S3やシェルスクリプトを使わずにローカルから画像読み込んでPythonだけで書いたら1つのプログラムで済むしすっきりするのでこの方法は要検討です…