AI Kit を使った Hailo Raspberry Pi 5 Examples を読み解く
この記事について
この記事は、Raspberry Pi 5 + AI Kit の導入に関する話題をまとめています。
AI Kitとは、Rapsberry Pi 5に高速・低消費電力なAI処理機能を追加するキットです。
初回はRaspberry Pi財団が公開するソフトウェアを用いてAI Kitを動作させるところまでを説明しました。
第2回はHailoRT Python packageを使用して推論を実行する方法を紹介しました。
第3回はHailo社の公開ソフトウェア、Hailo Raspberry Pi 5 ExamplesをインストールしてTAPPASを使用しました。
第4回はHailo Raspberry Pi 5 Examplesを読み解いて、一部改造をしていきます。
今回の内容にはHailo社のアカウントの作成は必要ありません。
誰が書いているのか
株式会社アラヤのエッジAI チームの林です。
普段は、エッジAIシステムの開発などを行っています!
アラヤのエッジAIチームでは、アラヤの"人類の未来を圧倒的に面白く!"するというビジョンを達成するために、"すべてのモノにAIを乗せる"というミッションに取り組んでいます。
Hailo Raspberry Pi 5 Examples (Basic Pipelines)
TAPPASをインストールし、PythonからTAPPASを実行してコールバック関数で推論結果を受け取るサンプルです。
インストール
初回のセットアップの済んだ所から開始してください。
第3回のインストールがお済の方はこの節は飛ばして、サンプルコマンド(姿勢推定)実行に進んでください。
インストールはBasic Pipelines Installation Guideに従います。
git clone https://github.com/hailo-ai/hailo-rpi5-examples.git
cd hailo-rpi5-examples
source setup_env.sh
pip install -r requirements.txt
./download_resources.sh
./compile_postprocess.sh
インストールは上記コマンドの実行で完了です。
今後は実行のたびに、source setup_env.sh
を実行する必要があります。
サンプルコマンド(姿勢推定)実行
引数なしで実行
Pose Estimation Exampleの実行例です
python basic_pipelines/pose_estimation.py
コールバック内で生成されたconfidence
と目の座標がコンソールに出力されています。
上の例では入力は動画ファイルですが、カメラを指定することも可能です。
(RPi camera は Still in Betaですが…)
--input INPUT, -i INPUT
Input source. Can be a file, USB or RPi camera (CSI camera module). For RPi camera use '-i rpi' (Still in Beta). Defaults to example
video resources/detection0.mp4
簡単に解説
pose_estimation.py
を実行すると、1フレームを処理する毎に下に引用したpose_estimation.py
に記述されたユーザ定義のコールバック関数app_callback
が呼び出されます。
コールバック関数では、引数で与えられたinfo
から、30, 49, 50行目により検出したオブジェクトの情報detections
が得られます。
56行目からのループでは検出したオブジェクト毎に
ラベルがperson
であれば右目と左目の位置を取得(63, 65, 68行目)して画像内の座標に変換(69, 70行目)します。
37行目で1フレーム毎にフレーム番号をコンソール出力して、61行目で検出したオブジェクト毎にconfidence
を、71行目で目の座標をコンソールに出力します。
use-frameを指定して実行
次のオプションを指定すると、コールバック関数内でフレームを使用します。
--use-frame, -u Use frame from the callback function
次のコマンドを実行します。
python basic_pipelines/pose_estimation.py -u
コールバック内で生成されたUser Frame
ウィンドウが表示されるようになりました。
簡単に解説
use-frame
オプションを指定するとuser_data.use_frame
がTrueとなります。
コールバック関数内の46行目でフレーム画像を取得して、73行目で目の位置に点を描きます。
78行目でUser Frame
ウィンドウを表示します。
コールバック関数
pose_estimation.py
に記述されたユーザ定義のコールバック関数app_callback
を引用します。
23 # -----------------------------------------------------------------------------------------------
24 # User-defined callback function
25 # -----------------------------------------------------------------------------------------------
26
27 # This is the callback function that will be called when data is available from the pipeline
28 def app_callback(pad, info, user_data):
29 # Get the GstBuffer from the probe info
30 buffer = info.get_buffer()
31 # Check if the buffer is valid
32 if buffer is None:
33 return Gst.PadProbeReturn.OK
34
35 # Using the user_data to count the number of frames
36 user_data.increment()
37 string_to_print = f"Frame count: {user_data.get_count()}\n"
38
39 # Get the caps from the pad
40 format, width, height = get_caps_from_pad(pad)
41
42 # If the user_data.use_frame is set to True, we can get the video frame from the buffer
43 frame = None
44 if user_data.use_frame and format is not None and width is not None and height is not None:
45 # Get video frame
46 frame = get_numpy_from_buffer(buffer, format, width, height)
47
48 # Get the detections from the buffer
49 roi = hailo.get_roi_from_buffer(buffer)
50 detections = roi.get_objects_typed(hailo.HAILO_DETECTION)
51
52 # Get the keypoints
53 keypoints = get_keypoints()
54
55 # Parse the detections
56 for detection in detections:
57 label = detection.get_label()
58 bbox = detection.get_bbox()
59 confidence = detection.get_confidence()
60 if label == "person":
61 string_to_print += (f"Detection: {label} {confidence:.2f}\n")
62 # Pose estimation landmarks from detection (if available)
63 landmarks = detection.get_objects_typed(hailo.HAILO_LANDMARKS)
64 if len(landmarks) != 0:
65 points = landmarks[0].get_points()
66 for eye in ['left_eye', 'right_eye']:
67 keypoint_index = keypoints[eye]
68 point = points[keypoint_index]
69 x = int((point.x() * bbox.width() + bbox.xmin()) * width)
70 y = int((point.y() * bbox.height() + bbox.ymin()) * height)
71 string_to_print += f"{eye}: x: {x:.2f} y: {y:.2f}\n"
72 if user_data.use_frame:
73 cv2.circle(frame, (x, y), 5, (0, 255, 0), -1)
74
75 if user_data.use_frame:
76 # Convert the frame to BGR
77 frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
78 user_data.set_frame(frame)
79
80 print(string_to_print)
81 return Gst.PadProbeReturn.OK
コールバック関数を改造
コールバック関数を改造して、User Frame
ウィンドウに両ひざ下を線で結んだ画像を表示します。
前記に引用した、pose_estimation.py
に記述されたユーザ定義のコールバック関数の64~73行目を次のように変更します。
変更前の例ではキーポイントIDを文字列('left_eye', 'right_eye')から決定していますが、変更後はキーポイントIDを既知のものとして扱っています。
また、膝のID+2が足首のIDであることも利用しています。
64 if len(landmarks) != 0:
65 points = landmarks[0].get_points()
66 #'left_knee': 13,
67 #'right_knee': 14,
68 #'left_ankle': 15,
69 #'right_ankle': 16,
70 for id in [13,14]:
71 point=[0,0]
72 for i in range(2): #i= 0:knee / 1:ankle
73 point[i] = points[id+i*2]
74 x = int((point[i].x() * bbox.width() + bbox.xmin()) * width)
75 y = int((point[i].y() * bbox.height() + bbox.ymin()) * height)
76 point[i] = (x, y)
77 if user_data.use_frame:
78 cv2.circle(frame, point[0], 5, (0, 255, 0), -1)
79 cv2.circle(frame, point[1], 5, (0, 0, 255), -1)
80 cv2.line(frame, point[0], point[1], (255, 0, 0), 3)
上記の変更をして、次のコマンドを実行します。
python basic_pipelines/pose_estimation.py -u
おまけ
fakevideosinkを使ってUser Frameウィンドウだけが表示されるようにする
Gstreamer
にfakevideosink
を使うことで、もともと表示されていたウィンドウを非表示にしてUser Frame
ウィンドウだけが表示されるようにします。
pose_estimation_pipeline.py
のdisplay_pipeline
定義部分を次のように変更します。
- display_pipeline = DISPLAY_PIPELINE(video_sink=self.video_sink, sync=self.sync, show_fps=self.show_fps)
+ display_pipeline = DISPLAY_PIPELINE(video_sink='fakevideosink', sync=self.sync, show_fps=self.show_fps)
鏡で見ているような左右反転画像を表示する
カメラ入力では、鏡で見ているような左右反転画像を見たい時もありますよね。
Gstreamer
で'videoflip video-direction=horiz
を使うことで、表示画像を左右反転することが出来ます。
pose_estimation_pipeline.py
のpipeline_string
定義部分を次のように変更します。
pipeline_string = (
f'{source_pipeline} '
+ f'videoflip video-direction=horiz ! '
f'{infer_pipeline} ! '
その他
スクリーンショットをとるためにCLIコマンドの grim
コマンドを使いました。
AI Hat+ が発売されました。AI Kitとは違い、Hailo-8とHailo-8Lを選ぶことが出来ます。
まとめ
Raspberry Pi 5 + AI Kit の導入に関する話題をまとめています。
今回はHailo Raspberry Pi 5 Examples
のサンプルを改造して、独自のオーバーレイ画像を生成する方法を試しました。
エッジAIからLLM構築まで気軽にご相談ください!
株式会社アラヤの先端研究支援
株式会社アラヤのエッジAI
SubnetX
Discussion