技術雑記帳兼日記帳

AWS、Python、Terraformの使い方をコッソリ

python Amazon Rekognition Recognize Celebrities

はじめに

今回は有名人の顔を分析するRecognize Celebritiesを使ってみる。

準備

下記のプログラムを用意する。

  • recognize_celebrities.py
import boto3, sys, json, cv2, math, os, traceback

#recognize_celebritiesで顔の分析結果を返す
def recognize_celebrities(in_image_file):
    client=boto3.client('rekognition')
    #写真を読み出して、Byte変換してdetect_faces送信
    file = open(in_image_file,'rb')
    response = client.recognize_celebrities(Image={'Bytes':file.read()})

    return response

#Bounding Boxを設定して返す
def set_bounding_box(image_file, bounding_box_data):
    #画像の高さと幅を取得
    imgHeight, imgWidth = image_file.shape[:2]

    #位置を算出
    left = math.ceil(bounding_box_data['Left'] * imgWidth)
    top = math.ceil(bounding_box_data['Top'] * imgHeight)
    width = math.ceil(bounding_box_data['Width'] * imgWidth)
    height = math.ceil(bounding_box_data['Height'] * imgHeight)

    image_file = cv2.rectangle(image_file
                            , (left, top)
                            , (width+left, height+top)
                            , (0,255,0)
                            , 2)

    return image_file

#Bounding Boxの左下に名前を設定して返す
def set_celebrity_name(image_file, celebrity_name, boundingBox):
    #画像の高さと幅を取得
    imgHeight, imgWidth = image_file.shape[:2]

    left = math.ceil(boundingBox['Left'] * imgWidth)
    top = math.ceil(boundingBox['Top'] * imgHeight)
    height = math.ceil(boundingBox['Height'] * imgHeight)

    image_file = cv2.putText(image_file
                            , celebrity_name
                            , (left, height+top)
                            , cv2.FONT_HERSHEY_PLAIN
                            , 2
                            , (255, 255, 255)
                            , 2
                            , cv2.LINE_AA)

    return image_file


if __name__ == '__main__':
    if len(sys.argv) != 3:
        exit()
    
    in_file_name = sys.argv[1]
    out_file_name = sys.argv[2]

    try:
        #顔分析
        #jsonが無ければ分析あれば使う
        json_file_name = in_file_name + '.json'
        if (os.path.exists(json_file_name) == True):
            file = open(json_file_name, 'r')
            response = file.read()
            response = json.loads(response)
        else:
            response = recognize_celebrities(in_file_name)
            file = open(json_file_name, 'w')
            file.write(json.dumps(response))

        #分析元の画像を読み込み
        origin_image = cv2.imread(in_file_name)
        after_image = origin_image.copy()
        
        #画像に分析結果の設定
        for celebrity in response['CelebrityFaces']:
            after_image = set_bounding_box(after_image, celebrity['Face']['BoundingBox'])
            after_image = set_celebrity_name(after_image, celebrity['Name'], celebrity['Face']['BoundingBox'])
            
        #結果の出力
        if after_image is not None:
            cv2.imwrite(out_file_name, after_image)


    except Exception as e:
        print(e)
        print(traceback.format_exc())

実行方法

python recognize_celebrities.py 分析したいファイル.jpg 出力したいファイル名.jpg
  • 実行結果 f:id:halhalhal1:20210426211733j:plain

BoundingBoxを設定して、名前を設定してみた。
動作はほぼ共通化していて、流用が簡単にできるのでAmazonAPIが共通的に作られているかがわかった。
やっぱ、似たようなAPIは似たような構造になるんだよな、普通。


まとめ

今までの集大成で一気に書き上げることができた。
text設定とかはもうちょっとうまくメソッド化できそうだなぁ。