Amazon Rekognitionで顔にぼかしを自動で入れる

Amazon Rekognitionを用いて顔の位置を判別してぼかしを入れるスクリプトを書いてみようと思います!!

Pythonも使用します。

流れ

Pythonも使うのでスクリプトがごちゃごちゃしちゃうので大まかな流れを書き出していきます

  1. Amazon Rekognitionを用いて画像を解析する

  1. 顔の位置がBoundingBoxという値で出力されるのでその部分だけ抜き出す

  1. 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つのプログラムで済むしすっきりするのでこの方法は要検討です…