背景:プログラミングセミナーのテキストを作る必要あり
課題:AWSが提供するRekognitionを使って、「顔認証してみよう」的な教材とする。生徒様にはRPI + NodeREDを使ってもらう
取り組み:Rekognitionが分かっていないので、AWSが提供するサンプルコードを使って、動かして理解する。教材としてはNode-REDのノードとしたいので、JSによる呼び出しを理解すべし。
結論:Python + boto3の組み合わせでは detect_faces のサンプルを動かすことができた (年齢、性別、笑っているか等、画像から推定して返却される)
詳細:
AWSがJS/Pythonのサンプルコードを提供しているのでそれを動かしてみる。おおよその流れは以下
まずはテストをしてみる
RPiにカメラを取り付けて以下のコマンドで撮影する
libcamera-jpeg -o test4.jpg -t 3000 --width 640 --height 480
Amazon Rekognitionはシステム理解のためのデモが提供されているので、上記コマンドで撮影した自分の顔をアップロードしてみる。解析された結果が以下。
男性で推定年齢が52-60歳となっている。若く見られているが大体合っている。
やってみて分かったのは、モニタ無しにカメラ撮影するのが難しい。UIとしてはプレビュー手段が必須である。あと、実際にやってみると面白い、多分、セミナーでやった場合、推定年齢の所でウケるだろう。プログラミングのお題としては、、Node-REDでカメラ撮影して、撮影した画像データをAPIでAWSに送信する、返ってきた結果(JSON)を視覚的に分かるように表示するといった内容になるだろう。
自分のRPiにはGUIもなくnode-redが入っていないので、docker起動版で入れてみる
docker run -it -p 1880:1880 --name mynodered nodered/node-red
ローカルでNode-REDを実行する : Node-RED日本ユーザ会
bullseyeになってからカメラの制御が変わったのが気になっていたが、やはりNode-REDで使えるカメラ用Nodeは未対応なようだ。@airpocket様のレポートでもexecノードでコマンドを呼び出して実装されている。
Node-REDでの画像取得には「node-red-contrib-camerapi」というノードがありますが、Bullseyeではカメラの取り扱いが変わった為使用できません
Zero + Bullseye + Node-RED + CHIRIMEN環境のセットアップ覚書 - Qiita
撮影はexecノードで実行するとして、プレビューは実装したい。Node-REDダッシュボードでもいいけど、初めて使う人にダッシュボードを操作せるのはちょっと敷居が高いので、ノード編集画面でJPGイメージを表示させたい。というわけで、、「node-red-contrib-image-output」というありがたいNodeがあるようで、これを入れてみる。
イメージ表示用ノード(node-red-contrib-image-output)をインストールした。なお、このノード自体はイメージを表示する機能のみを持っており、イメージデータ自体は上流ノードで取得して流す必要がある。当てずっぽなのだが、上流で、ReadFileノードを使って、撮影したJPGデータを読み込んで、バイナリバッファとして下流に流す設定をした。
上流ノードの設定は以下、ReadFileノードで、撮影したデータが置かれているファイルを絶対パスで指定、下流へはバイナリバッファとして流す(他のプルダウンメニュー(バッファのストリーム等)を選ぶとプレビューは行われない)。ご参考にデバッグ出力も付けています。payloadの値がbuffer型になっている。
画像は取得できるとして、、APIの呼び出しはJSによるコードになるだろう。。FunctionノードでJSをゴリゴリと書くか、JSで正しくAPIを呼び出せない場合は、AWS CLIコマンドをインストールして、Execノードでコマンドを実行するか。。あるいは、boto3を使ってPythonでAPI呼び出し関数を作ってExecノードから呼び出すか。。 Execノードにした場合、戻り値の処理が大変なのではないかと推測される。だから、まずはFunctionノードがいいのだろう。
API呼び出しを理解するため、boto3で試作する。
detect_faces - Boto3 1.28.27 documentation
サービスが使えるリージョンはAPになくUSなので、'us-east-1'等を選択する。
サンプルコードを参考に対象修正したコードが以下(Credentialは ~/.aws/credentials において定義)
import boto3 import json REGION = 'us-east-1' ; // BUCKET = <set_bucket_name> ; // e.g. 'rekognition-image-bucket' PHOTO = <set_file_name> ; // e.g. 'face20230817.jpg' PROFILE_NAME = 'default' ; def detect_faces(photo, bucket, region, profile): session = boto3.Session(profile_name=profile, region_name=region) client = session.client('rekognition', region_name=region) response = client.detect_faces(Image={'S3Object':{'Bucket':bucket,'Name':photo}}, Attributes=['ALL']) print('Detected faces for ' + photo) print("-------------------------------------------") for faceDetail in response['FaceDetails']: age_low = faceDetail['AgeRange']['Low'] age_high = faceDetail['AgeRange']['High'] gender = faceDetail['Gender']['Value'] smile = faceDetail['Smile']['Value'] print(f'The detected face is between {age_low} and {age_high} years old') print(f"Gender: {gender}") print(f"Smile: {smile}") print("-------------------------------------------") return len(response['FaceDetails']) def main(): photo = PHOTO bucket = BUCKET region = REGION profile = PROFILE_NAME face_count = detect_faces(photo, bucket, region, profile) print("Faces detected: " + str(face_count)) if __name__ == "__main__": main()
実行結果は以下
$ python3 detect_faces.py Detected faces for face001.jpg ------------------------------------------- The detected face is between 52 and 60 years old Gender: Male Smile: False ------------------------------------------- Faces detected: 1
ということで、、Python+boto3では動いたので、次はnodejsで動かしてみる
■
情報も揃ってやるべきことは明快なのに、(いつもと同じく)逃避している。一旦作り始めると、動かない→調べる→動く→嬉しい→コードを書く→動かないに戻るのループが回り出して、いつまでもコーディングを続けるのだけど、、最初の一サイクルが回らない。一回転させるスタータがない・・