はじめに
このコラムではRadxa社のシングルボードコンピュータROCK 5 Model BでエッジAIアクセラレーターHailo-8を動作させ、 Hailo社が提供しているアプリケーションサンプルを改造してHDMI入力に対してリアルタイム物体検出処理を紹介します。
以前の小型デバイスでここまでできる:ファンレスで動くエッジAIアクセラレーターによる姿勢推定(YOLOv8-pose)ではサンプルコードを動かして静止画への処理を行う例を紹介しました。
今回はROCK 5 Model BのHDMI入力を利用して、動画のリアルタイム処理を行い画面に表示してみようと思います。
HDMI入力を利用することで動画サイトやDVDプレーヤーなど様々なコンテンツに対してHailo-8の高性能を実感していただけると思います。次の動画は当社の紹介動画を入力した例です。
評価や検証の一例として、ぜひお試しください。
準備
以前の記事を参照して、ROCK 5 Model BとHailo-8の環境設定を行ってください。今回は動画処理を行いますので、「HDMI出力ができる機器(PC、ビデオカメラ)」と 「Mini HDMI - HDMIケーブル」が必要になります。
物体検出サンプルコードの実行
object_detectionのビルド
ではさっそく進めていきましょう。Hailo社が公開しているアプリケーションサンプルのhailo-appsを利用していきます。
ROCK 5 Model Bのターミナルを起動したら、適当なディレクトリへ移動します。次のコマンドを実行してください($はコマンドプロンプトです。入力しません)。
$ git clone https://github.com/hailo-ai/hailo-apps.git
# 記事を執筆した時点のバージョンと合わせます
$ cd hailo-apps
$ git checkout 095deb51bd
物体検出のサンプルをベースに処理を追加していきます。まずはサンプルをそのまま動かしてみましょう。
ディレクトリを移動してビルドします。
# 物体検出サンプルへ移動
$ cd hailo_apps/cpp/object_detection
# 依存するライブラリをインストール
$ sudo apt update
$ sudo apt install -y libopencv-dev python3-opencv libboost-all-dev
# ビルド
$ cmake -S . -B build
$ cmake --build build -j
ビルドが完了するとbuild/object_detectionが生成されます。
モデルのダウンロード
では、プログラムを実行してみましょう。引数に'--list-nets'を指定して実行すると対応するモデルの一覧が表示されます。
$ ./build/object_detection --list-nets
No --net was provided.
Fetching networks list... please wait
Supported networks for object_detection:
- yolov10b | arch=[hailo8,hailo8l,hailo10h] | src=model_zoo | hefs=[yolov10b.hef] | desc=YOLOv10b
- yolov10n | arch=[hailo8,hailo8l,hailo10h] | src=model_zoo | hefs=[yolov10n.hef] | desc=YOLOv10n
- yolov10s | arch=[hailo8,hailo8l,hailo10h] | src=model_zoo | hefs=[yolov10s.hef] | desc=YOLOv10s
- yolov10x | arch=[hailo8,hailo8l,hailo10h] | src=model_zoo | hefs=[yolov10x.hef] | desc=YOLOv10x
- yolov11l | arch=[hailo8,hailo8l,hailo10h] | src=model_zoo | hefs=[yolov11l.hef] | desc=YOLOv11l
- yolov11m | arch=[hailo8,hailo8l,hailo10h] | src=model_zoo | hefs=[yolov11m.hef] | desc=YOLOv11m
- yolov11n | arch=[hailo8,hailo8l,hailo10h] | src=model_zoo | hefs=[yolov11n.hef] | desc=YOLOv11n
- yolov11s | arch=[hailo8,hailo8l,hailo10h] | src=model_zoo | hefs=[yolov11s.hef] | desc=YOLOv11s
- yolov11x | arch=[hailo8,hailo8l,hailo10h] | src=model_zoo | hefs=[yolov11x.hef] | desc=YOLOv11x
- yolov5m | arch=[hailo8,hailo8l,hailo10h] | src=model_zoo | hefs=[yolov5m.hef ] | desc=YOLOv5m
- yolov5s | arch=[hailo8,hailo8l,hailo10h] | src=model_zoo | hefs=[yolov5s.hef ] | desc=YOLOv5s
- yolov6n | arch=[hailo8,hailo8l,hailo10h] | src=model_zoo | hefs=[yolov6n.hef ] | desc=YOLOv6n
- yolov7 | arch=[hailo8,hailo8l,hailo10h] | src=model_zoo | hefs=[yolov7.hef ] | desc=YOLOv7
- yolov7x | arch=[hailo8,hailo8l,hailo10h] | src=model_zoo | hefs=[yolov7x.hef ] | desc=YOLOv7x
- yolov8l | arch=[hailo8,hailo8l,hailo10h] | src=model_zoo | hefs=[yolov8l.hef ] | desc=YOLOv8l
- yolov8m | arch=[hailo8,hailo8l,hailo10h] | src=model_zoo | hefs=[yolov8m.hef ] | desc=YOLOv8m
- yolov8n | arch=[hailo8,hailo8l,hailo10h] | src=model_zoo | hefs=[yolov8n.hef ] | desc=YOLOv8n
- yolov8s | arch=[hailo8,hailo8l,hailo10h] | src=model_zoo | hefs=[yolov8s.hef ] | desc=YOLOv8s
- yolov8x | arch=[hailo8,hailo8l,hailo10h] | src=model_zoo | hefs=[yolov8x.hef ] | desc=YOLOv8x
- yolov9c | arch=[hailo8,hailo8l,hailo10h] | src=model_zoo | hefs=[yolov9c.hef ] | desc=YOLOv9c
Hailo社が公開しているModel Explorer Visionではモデルの精度、処理速度を一覧で見ることができます。またHailo-8向けにコンパイルされたモデルデータをダウンロードすることもできます。
今回は精度とFPSのバランスが良いYOLOv8mを利用します。Model Explorerからダウンロードしても良いですが、hailo-appsに用意されているスクリプトを使ってみましょう。このスクリプトは--list-netsで表示されたモデル名を指定してダウンロードできるので便利です。
次のコマンドで現在のディレクトリにyolov8m.hefが保存されます。
# hailo-apps/hailo_apps/cpp/object_detectionから実行します
$ ../../config/get_hef.sh get --app object_detection --net yolov8m --hw-arch hailo8 --dest .
hailortcliを利用すると、モデル単体のFPS、レイテンシ、消費電力を簡単に計測することができます。次のコマンドを実行してみましょう。
$ hailortcli benchmark yolov8m.hef
Starting Measurements...
Measuring FPS in HW-only mode
Network yolov8m/yolov8m: 100% | 794 | FPS: 52.91 | ETA: 00:00:00
Measuring FPS (and Power on supported platforms) in streaming mode
[HailoRT] [warning] Using the overcurrent protection dvm for power measurement will disable the overcurrent protection.
If only taking one measurement, the protection will resume automatically.
If doing continuous measurement, to enable overcurrent protection again you have to stop the power measurement on this dvm.
Network yolov8m/yolov8m: 100% | 794 | FPS: 52.82 | ETA: 00:00:00
Measuring HW Latency
Network yolov8m/yolov8m: 100% | 494 | HW Latency: 15.77 ms | ETA: 00:00:00
=======
Summary
=======
FPS (hw_only) = 52.9069
(streaming) = 52.8196
Latency (hw) = 15.77 ms
Device 0000:01:00.0:
Power in streaming mode (average) = 2.81216 W
(max) = 2.87292 W
このモデルは最大52FPS、レイテンシが15.8ms、消費電力が2.8Wであることがわかります。
※ 上記数値は本検証環境での参考値です。
またモデルと同様にテスト用のデータも用意されており、簡単にダウンロードすることができます。以下のコマンドで現在のディレクトリにfull_mov_slow.mp4が保存されます。
# hailo-apps/hailo_apps/cpp/object_detectionから実行します
$ ../../config/get_input.sh list --app object_detection
images:
name="bus" | description="Bus with walking people"
name="dog_bicycle" | description="dog and a bicycle outdoor"
name="zidane" | description="Zidane and Carlo Ancelotti Italian football manager"
videos:
name="cars" | description="drive in the city"
$ ../../config/get_input.sh get --app object_detection --i cars --target-dir .
object_detectionの実行
ここまでの手順でモデルとデータが手に入ったので実行してみます。
$ ./build/object_detection --net yolov8m.hef --input full_mov_slow.mp4
画像のようにYOLOv8mで物体検出した結果が動画で表示されます。遠くの信号や車もリアルタイムに検出できており、Hailo-8の処理性能がおわかりいただけると思います。
HDMI入力に対する物体検出処理
HDMI入力機能の確認
ROCK 5 Model B にはHDMI入力用のインターフェースが用意されており対応するOSイメージではV4L2(VideoをLinuxで扱うためにLinux Kernelに実装されているuser space API)デバイスとして画像入力を行うことが出来ます。この機能を使ってHDMI入力した動画に対して物体検出をしてみたいと思います。
※ 本記事の検証は 1920x1080 / 30p フォーマットを前提としています。
※ 解像度やフレームレートが異なる場合はパイプラインの修正が必要です。
HDMI入力は下の図の赤い丸で囲った端子を利用します。Mini HDMI - HDMIケーブルを用意してPCやビデオカメラと接続してください。
接続したら次のコマンドでキャプチャ画面が表示されるかを確認します。
# メディアプレーヤをインストール
$ sudo apt update
$ sudo apt install -y ffmpeg
$ ffplay -f v4l2 -input_format nv12 -video_size 1920x1080 /dev/video0
もしも、うまくいかない場合は出力機器側の解像度を1920x1080/30pに固定して試してみてください。また、出力機器によっては色味が変わる場合があります。出力側のフォーマットを変更するなどしてみてください。
object_detectionへ機能を追加
HDMI入力のためにOpenCVからGStreamerを利用します。サンプルコードでは入力としてファイルとUSBカメラのみを想定した処理となっているため、OpenCVでGStreamerを読み込む機能を追加していきます。
GStreamerはオープンソースのマルチメディアフレームワークです。非常に多機能なライブラリで機能の詳細な解説はこの記事の範囲を超えるため省略します。ネットにはさまざまな解説ドキュメントがありますので参照してみてください。
object_detection.cppをエディタで開き、main()より前で次の関数を定義してください。この関数は対応する画像フォーマットをHDMI入力デバイスに問い合わせ、最初にマッチしたものをオープンするようにしています。
/**
* HDMI入力のためにGStreamerパイプラインを初期化します
*/
static InputType get_hdmi_input(const std::string &input_path,
cv::VideoCapture &capture,
double &org_height,
double &org_width,
size_t &frame_count,
size_t batch_size,
const std::string &camera_resolution)
{
InputType input_type;
input_type.is_video = true;
// 入力は/dev/video0に固定
if (input_path != "/dev/video0")
{
throw std::runtime_error("Unsupported input device: " + input_path + ". If you use --rock5b-hdmi-in, set --input to /dev/video0 ");
}
// GStreamerパイプライン(デバイスのサポートフォーマットを自動検出)
// 複数のフォーマットを試す(NV12, YUY2, UYVY, MJPEGなど)
std::vector<std::pair<std::string, std::string>> format_candidates = {
{"video/x-raw,format=NV12", "NV12"}, // NV12フォーマット
{"video/x-raw,format=YUY2", "YUY2"}, // YUY2フォーマット
{"video/x-raw,format=UYVY", "UYVY"}, // UYVYフォーマット
{"video/x-raw", "auto-detect"} // フォーマット指定なし(自動検出)
};
// 色変換マトリクスの設定
// GStreamerのmatrix-coefficients: 0=Identity, 1=BT.709, 2=BT.601, 3=BT.
// matrix_param = ""の場合は自動判別
// HDで標準的なBT.709を設定しておきます
std::string matrix_param = ",matrix-coefficients=1";
bool opened = false;
std::string successful_format;
for (const auto &[format, format_name] : format_candidates)
{
// 各試行の前にcaptureをリセット
capture.release();
std::ostringstream pipeline;
// その他のフォーマット
pipeline << "v4l2src device=/dev/video0 io-mode=mmap ! "
<< format << " ! "
<< "videoscale ! video/x-raw,width=1920,height=1080" << matrix_param << " ! "
<< "videoconvert ! video/x-raw,format=BGR ! "
<< "appsink drop=true sync=false max-buffers=2";
capture.open(pipeline.str(), cv::CAP_GSTREAMER);
if (capture.isOpened())
{
opened = true;
successful_format = format_name;
break;
}
}
if (!opened)
{
throw std::runtime_error("Unable to open HDMI input via GStreamer: " + input_path +
" (tried multiple formats: NV12, YUY2, UYVY, MJPEG, auto-detect)");
}
// 成功したフォーマットを表示(警告が表示されても正常に動作していることを示す)
std::cout << "-I- HDMI input opened successfully using format: " << successful_format << std::endl;
// HDMI入力の解像度は固定(1920x1080)
org_width = 1920;
org_height = 1080;
frame_count = 0; // カメラと同様にフレーム数は不明
return input_type;
}
次にmain()に以下の内容を追加、削除してください。
- post_parse_args(APP_NAME, args, argc, argv);
- HailoInfer model(args.net, args.batch_size);
- input_type = determine_input_type(args.input,
- std::ref(capture),
- std::ref(org_height),
- std::ref(org_width),
- std::ref(frame_count),
- std::ref(args.batch_size),
- std::ref(args.camera_resolution));
+ // --rock5b-hdmi-inオプションが指定された場合は/dev/video0からのキャプチャ設定を行う
+ if (has_flag(argc, argv, "--rock5b-hdmi-in"))
+ {
+ // HDMI入力時はpost_parse_args(), determine_input_type()を利用しません。
+ input_type = get_hdmi_input(args.input,
+ std::ref(capture),
+ std::ref(org_height),
+ std::ref(org_width),
+ std::ref(frame_count),
+ std::ref(args.batch_size),
+ std::ref(args.camera_resolution));
+ }
+ else
+ {
+ // 通常の処理(ファイル、USBカメラなど)
+ post_parse_args(APP_NAME, args, argc, argv);
+ input_type = determine_input_type(args.input,
+ std::ref(capture),
+ std::ref(org_height),
+ std::ref(org_width),
+ std::ref(frame_count),
+ std::ref(args.batch_size),
+ std::ref(args.camera_resolution));
+ }
+ HailoInfer model(args.net, args.batch_size);
ビルドと実行
まず、GStreamerのツールと関連ライブラリをインストールします。
$ sudo apt install -y gstreamer1.0-tools libgstreamer1.0-0 gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav
次に修正したコードをビルドしてください。
# hailo-apps/hailo_apps/cpp/object_detectionから実行します
$ cmake --build build -j
PCやビデオカメラをHDMI入力端子に接続します。ではプログラムを実行しましょう。
$ ./build/object_detection --rock5b-hdmi-in --net yolov8m.hef --input /dev/video0
※ --rock5b-hdmi-in は本記事用に追加した独自オプションのため、--help には表示されません。
PCから当社のYouTube動画を入力してみました。いかがでしょうか?
入力した動画はこちら
Hailo-8による物体検出処理を含めて実測で20FPS程度の速度となりました。
このプログラムで物体検出処理を外してHDMI画像のみを表示させた場合でもフレームレートに変化は見られなかったことから、OpenCV経由の取り込み処理がボトルネックになっている可能性が高いと考えられます。より高速な処理を行いたい場合はOpenCVを介さずにGStreamerのAPIを直接利用する構成をご検討ください。
まとめ
今回の記事ではHailo社が提供しているアプリケーションサンプルを改造してHDMI入力に対してリアルタイム物体検出処理を行ってみました。
ネット上のいろいろな動画コンテンツに対してHailo-8でのリアルタイム処理を適用することができるので手軽に評価やアプリケーション開発にご利用いただけると思います。
また、今回紹介した方法は他のサンプルにも適用することができますのでぜひお手元で試してみてください。
ネクスティエレクトロニクス開発部では今回紹介したHailo-8の他にも生成AIに適したHailo-10Hの技術開発・サポートを行っています。またNXP社のi.MX8, i.MX95とHailo-8, Hailo-10Hを組み合わせた動作事例の紹介やサポートなど、お客様の用途に合わせたいろいろな製品やソリューションをご提案できますので、ぜひお気軽にお問い合わせください。







