Michaelです。
こんにちは、Michaelです。
今回から、Azure FunctionsとCognitive Servicesを使って画像内の顔を検出する仕組みを作成していきます。
2回目は、Azure FunctionsとCognitive ServicesのFace APIを使い、Blobストレージにアップロードされた画像の顔検出結果を取得する仕組みを作成します。
今回の構成
Blobストレージにアップロードされた画像をトリガーにAzure Functionsを起動します。
Azure Functionsでアップロードされた画像をFace APIに送り、顔の検出結果をJSONとしてBlobストレージに格納します。
※ Cognitive Services Face APIの登録に関しては「Cognitive Services: Face APIの顔検出をPythonで試してみた」を参照ください
バインドの設定
Azure Functionsを起動する「トリガー」と結果をBlobストレージに書き出す「出力」のバインドを設定します。
関数の「統合」から、まず「トリガー」をクリックし「Azure Blob Storage」のバインドを選択します。
「Blob parameter name」に任意の名称、「Path」、「Storage account connection」に監視を行うBlobコンテナーのパスとそのストレージアカウントを設定します。パスパターンとして「{name}.{extention}」を設定しておくことで、他のバインドからパスパターンを参照できるようにしています。
「トリガー」と同様に「出力」バインドも「Azure Blob Storage」を選択し、「Blob parameter name」、「Path」、「Storage account connection」をそれぞれ設定します。
「Path」にはアップロードした画像の名称が出力のJSONファイル名に反映されるよう、「{name}_result.json」を設定しています。
Pythonスクリプト
スクリプトは以下のように作成しました。
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 53 54 55 56 57 58 59 60 61 62 |
# coding: utf-8 # 01‐ライブラリのインポート import os import json import requests import imghdr def main(): input_img_path = os.environ["triggerImage"] result_path = os.environ["resultJson"] # 02‐Face API未対応フォーマット判定 print("Checking input image format") img_format = imghdr.what(input_img_path) if img_format not in ["jpeg", "png", "bmp", "gif"]: status = {"status": "error"} if img_format == None: status["message"] = "Input file is not image." else: status["message"] = "Unsupported image format." print(status) with open(result_path, "w") as f: json.dump(status, f, indent=4) return # 03‐Face APIで顔検出 print("Detecting faces") face_api_location = "westus" face_api_key = "{Face APIキー}" url = "https://{location}.api.cognitive.microsoft.com/face/v1.0/{function}".format(location=face_api_location, function="detect") headers = { "Content-Type": "application/octet-stream", "Ocp-Apim-Subscription-Key": face_api_key } params = { "returnFaceId": True, "returnFaceLandmarks": False, "returnFaceAttributes": "age,gender,smile,emotion" } res = requests.request("POST", url, headers=headers, params=params, data=open(input_img_path, "rb")) detect_data = res.json() # 04‐顔検出結果をJSONで出力 print("Output detect result as JSON.") with open(result_path, "w") as f: json.dump(detect_data, f, indent=4) if __name__ == "__main__": main() |
スクリプトの説明
スクリプトの内容は以下の通りです。
01‐ライブラリのインポート
処理に必要なライブラリを指定してインポートします。
Face APIに対するリクエストを実行するため、外部ライブラリ「requests」を使用しています。
※ 「requests」については
前回の手順で予めインストールしておきます。
02‐Face API未対応フォーマット判定
トリガーとしてアップロードされたファイルがFace APIの対応フォーマット(JPEG、PNG、BMP、GIF)に該当するか判定します。
Azure Functionsでは、os.environ[“トリガーバインド名”]に格納されたパスにアップロードデータのコピーがあるため、標準ライブラリ「imghdr」を使用して画像フォーマットを判定し、対応フォーマットのみを選別します。
03‐Face APIで顔検出
Face APIにリクエストをして、画像内の顔を検出します。
Azure FunctionsのPython関数では、アップロードされたBlobのパスを取得できないため、JSON形式でのリクエストができませんが、Face APIはバイナリ形式のリクエストにも対応しているため、os.environ[“トリガーバインド名”]のパスにあるアップロードデータのコピーで直接リクエストし、顔の検出を行います。
04‐顔検出結果をJSONで出力
Face APIで出力された結果をそのままJSON形式で出力します。
os.environ[“出力バインド名”]のパスに出力したいデータを保存するとBlobストレージに格納されます。
実行結果
テストとして、JPEG画像を「face-01.jpg」としてBlobストレージにアップロードしてみます。
Azure Functionsのログを見ると、アップロードされた4秒後に関数が開始され、順次ログを出力しながら約10秒で関数が完了しました。
Blobストレージを見ると、関数が完了した同時刻に「face-01_result.json」の名称でJSONファイルが出力されていました。バインドで設定したパスパターンが出力ファイル名に反映されていることがわかりました。
出力されたJSONの内容は以下になります。Face APIの出力がそのままBlobストレージに出力できていました。
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 |
[ { "faceId": "4d551839-3ddf-4fdd-95f9-a9fc8ed2bf09", "faceRectangle": { "top": 154, "left": 118, "width": 199, "height": 199 }, "faceAttributes": { "smile": 1.0, "gender": "male", "age": 23.5, "emotion": { "anger": 0.0, "contempt": 0.0, "disgust": 0.0, "fear": 0.0, "happiness": 1.0, "neutral": 0.0, "sadness": 0.0, "surprise": 0.0 } } } ] |
続いて、画像ではないJSONデータ「face-02.json」をBlobストレージにアップロードしてみます。
スクリプトでフォーマット判定を行っているため、Azure Functionsのログを見ると正常に処理が中断されていることがわかりました。
まとめ
Azure FunctionsのPython関数は、C#やJavaScriptのようにバインドのパスパターンをスクリプトで参照できないため、入出力の方法にひと工夫が必要になりますが、今回のようにパスパターンに大きな変更がなければ簡単に設定して処理を組むことができました。
次回は、今回の処理にOpenCVを使いして、検出した顔の情報を画像に描画してみます。