chakokuのブログ(rev4)

テック・コミック・DTM・・・ごくまれにチャリ

Rekognitionのサンプルを動かして理解→Node-REDから呼び出せるようにしたい

背景:プログラミングセミナーのテキストを作る必要あり
課題:AWSが提供するRekognitionを使って、「顔認証してみよう」的な教材とする。生徒様にはRPI + NodeREDを使ってもらう
取り組み:Rekognitionが分かっていないので、AWSが提供するサンプルコードを使って、動かして理解する。教材としてはNode-REDのノードとしたいので、JSによる呼び出しを理解すべし。
結論:Python + boto3の組み合わせでは detect_faces のサンプルを動かすことができた (年齢、性別、笑っているか等、画像から推定して返却される)

詳細:
AWSがJS/Pythonのサンプルコードを提供しているのでそれを動かしてみる。おおよその流れは以下

  1. 画像をS3に配置
  2. Rekognition APIを呼び出す
  3. JSON形式で返却される。内容を見やすくして利用者に返却

まずはテストをしてみる
RPiにカメラを取り付けて以下のコマンドで撮影する

libcamera-jpeg -o test4.jpg -t 3000 --width 640 --height 480

Amazon Rekognitionはシステム理解のためのデモが提供されているので、上記コマンドで撮影した自分の顔をアップロードしてみる。解析された結果が以下。
男性で推定年齢が52-60歳となっている。若く見られているが大体合っている。

やってみて分かったのは、モニタ無しにカメラ撮影するのが難しい。UIとしてはプレビュー手段が必須である。あと、実際にやってみると面白い、多分、セミナーでやった場合、推定年齢の所でウケるだろう。プログラミングのお題としては、、Node-REDでカメラ撮影して、撮影した画像データをAPIAWSに送信する、返ってきた結果(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を使ってPythonAPI呼び出し関数を作って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で動かしてみる

情報も揃ってやるべきことは明快なのに、(いつもと同じく)逃避している。一旦作り始めると、動かない→調べる→動く→嬉しい→コードを書く→動かないに戻るのループが回り出して、いつまでもコーディングを続けるのだけど、、最初の一サイクルが回らない。一回転させるスタータがない・・


AWS service endpoints - AWS General Reference