sample_face_ae¶
このガイドでは、K230 の sample_face_ae アプリケーションを CMake out-of-tree ビルドで構築する方法を説明します。このサンプルは顔検出モデル (MobileRetinaface) を使用して検出した顔領域を ISP の AE (Auto Exposure) ROI に反映し、顔に最適化された露出制御を実現するデモアプリケーションです。
前提条件¶
- K230 SDK がビルド済みであること(ツールチェーン展開済み、MPP ライブラリコンパイル済み)
- SDK がリポジトリルートの
k230_sdk/に配置されていること - 顔検出用の kmodel ファイル(
mobile_retinaface.kmodel) - ホスト OS: x86_64 Linux
- CMake 3.16 以降
SDK のビルド
K230 SDK のビルド手順については SDK ビルド を参照してください。
概要¶
sample_face_ae は K230 SDK の顔検出サンプル (sample_face_ae) をベースにした、AI 推論と ISP AE ROI 制御を組み合わせたアプリケーションです。以下を実演します:
- VICAP API によるカメラセンサーの設定(2チャネル: 表示用 YUV420 + AI推論用 RGB888P)
- NNCASE ランタイムによる kmodel の読み込みと AI2D 前処理
- MobileRetinaface モデルによる顔検出(バウンディングボックス + ランドマーク)
- 検出した顔領域の ISP AE ROI への反映(面積比重み付け)
- VO ディスプレイへのリアルタイムプレビューと顔枠描画
ソースファイル¶
| ファイル | 説明 |
|---|---|
main.cc |
メインアプリケーション — VB/VICAP/VO 初期化、AI 推論ループ、クリーンアップ |
model.h / model.cc |
Model 抽象基底クラス — kmodel ロードと推論パイプライン |
mobile_retinaface.h / mobile_retinaface.cc |
MobileRetinaface クラス — 顔検出モデル(AI2D 前処理、アンカーデコード、NMS) |
face_ae_roi.h / face_ae_roi.cc |
FaceAeRoi クラス — 顔座標を ISP AE ROI に反映 |
util.h / util.cc |
ユーティリティ型(box_t、face_coordinate)とヘルパー |
anchors_320.cc |
320x320 入力用の事前計算済みアンカーボックス |
vo_test_case.h |
VO レイヤーヘルパー型(layer_info)の宣言 |
処理フロー¶
アプリケーションは以下のデータフローに沿って動作します:
センサー (OV5647)
│
├─ CHN0 (1920x1080 YUV420) ──→ VO レイヤー ──→ HDMI ディスプレイ
│ ↑
│ 顔枠描画 (kd_mpi_vo_draw_frame)
│
└─ CHN1 (1280x720 RGB888P) ──→ AI 推論
│
┌─────┴─────┐
│ AI2D 前処理 │
│ (リサイズ+パッド) │
└─────┬─────┘
│
┌─────┴─────┐
│ KPU 推論 │
│ (MobileRetinaface) │
└─────┬─────┘
│
┌─────┴─────┐
│ 後処理 │
│ (デコード+NMS) │
└─────┬─────┘
│
┌─────┴─────┐
│ AE ROI 更新 │
│ (FaceAeRoi) │
└─────┬─────┘
│
↓
ISP AE エンジン
クラスリファレンス¶
Model — 抽象基底クラス¶
Source: model.h L13–L39 / model.cc
kmodel のロードと推論パイプラインを管理する抽象基底クラス。サブクラスは Preprocess() と Postprocess() を実装します。
| メソッド | 説明 |
|---|---|
Model(model_name, kmodel_file) |
kmodel ファイルを読み込み、入力テンソルを作成 |
Run(vaddr, paddr) |
Preprocess → KpuRun → Postprocess の推論パイプラインを実行 |
Preprocess(vaddr, paddr) |
純粋仮想 — 入力データの前処理 |
KpuRun() |
kmodel を KPU で実行 |
Postprocess() |
純粋仮想 — 推論結果の後処理 |
InputTensor(idx) / OutputTensor(idx) |
入出力テンソルへのアクセス |
InputShape(idx) / OutputShape(idx) |
入出力形状の取得 |
メンバ変数:
| 変数 | 説明 |
|---|---|
ai2d_builder_ |
AI2D 前処理パイプラインビルダー |
ai2d_in_tensor_ / ai2d_out_tensor_ |
AI2D 入出力テンソル |
interp_ |
NNCASE ランタイムインタプリタ |
MobileRetinaface — 顔検出モデル¶
Source: mobile_retinaface.h L13–L48 / mobile_retinaface.cc
Model を継承し、MobileRetinaface 顔検出モデルの前処理・後処理を実装します。
| メソッド | 説明 |
|---|---|
MobileRetinaface(kmodel_file, channel, height, width) |
AI2D 前処理パイプラインを構築(リサイズ + パディング) |
GetResult() |
検出結果(バウンディングボックス + ランドマーク)を返す |
Preprocess(vaddr, paddr) |
VICAP フレームから AI2D テンソルを作成し、前処理を実行 |
Postprocess() |
9 個の出力テンソルをデコードし、NMS でフィルタリング |
後処理の流れ:
- Confidence デコード (
DealConfOpt) — 3 スケールの信頼度を softmax で処理し、閾値 (obj_threshold_= 0.6) 以上のオブジェクトを選択 - Location デコード (
DealLocOpt) — 選択されたオブジェクトの位置情報をアンカーボックスを使ってデコード - Landmark デコード (
DealLandmsOpt) — 5 点の顔ランドマークをデコード - NMS — IoU 閾値 (
nms_threshold_= 0.5) で重複ボックスを除去 - 座標変換 — モデル座標からカメラ入力座標に変換
FaceAeRoi — AE ROI 制御¶
Source: face_ae_roi.h L9–L21 / face_ae_roi.cc
検出された顔座標を ISP AE ROI ウィンドウに変換し、顔領域に最適化された自動露出制御を実現します。
| メソッド | 説明 |
|---|---|
FaceAeRoi(dev, model_w, model_h, sensor_w, sensor_h) |
ISP デバイスとモデル/センサー解像度を設定 |
SetEnable(enable) |
ISP AE ROI 機能の有効/無効を切り替え (kd_mpi_isp_ae_roi_set_enable) |
Update(boxes) |
顔バウンディングボックスを AE ROI ウィンドウに変換して設定 |
Update() の処理:
- 顔座標をモデル解像度からセンサー解像度にスケーリング
- 最大 8 個の ROI ウィンドウを設定
- 各 ROI の重みを面積比で算出(大きい顔 = 大きい重み)
kd_mpi_isp_ae_set_roi()で ISP に反映
ビルド手順¶
1. 設定¶
cmake -B build/sample_face_ae -S apps/sample_face_ae \
-DCMAKE_TOOLCHAIN_FILE="$(pwd)/cmake/toolchain-k230-rtsmart.cmake"
2. ビルド¶
3. 確認¶
期待される出力:
sample_face_ae: ELF 64-bit LSB executable, UCB RISC-V, RVC, double-float ABI, version 1 (SYSV), statically linked, ...
CMakeLists.txt の詳細¶
apps/sample_face_ae/CMakeLists.txt は以下を処理します:
- MPP インクルードパス:
mpp/include/、mpp/include/comm/、mpp/include/ioctl/、mpp/userapps/api/のヘッダ - NNCASE インクルードパス:
nncase/include/、nncase/include/nncase/runtime/、rvvlib/include/のヘッダ - MPP 静的ライブラリ: 全 MPP ライブラリを
--start-group/--end-groupで循環依存を解決してリンク - NNCASE ライブラリ:
Nncase.Runtime.Native、nncase.rt_modules.k230、functional_k230、rvv - C++20:
target_compile_featuresで C++20 を要求
コマンドライン引数¶
| 引数 | 説明 |
|---|---|
<kmodel> |
顔検出用 kmodel ファイルのパス(例: /sharefs/mobile_retinaface.kmodel) |
<roi_enable> |
AE ROI の有効化: 1 = 有効、0 = 無効 |
K230 への転送・実行¶
CMake の deploy / run ターゲットで転送・実行をワンコマンドで行えます(詳細は CMake ターゲット を参照):
cmake --build build/sample_face_ae --target deploy # ビルド + SCP 転送
cmake --build build/sample_face_ae --target run # シリアル経由で実行 (Ctrl+C で終了)
手動で転送・実行する場合¶
SCP + minicom による手動操作
SCP で転送¶
scp build/sample_face_ae/sample_face_ae root@<K230_IP_ADDRESS>:/sharefs/sample_face_ae/
scp mobile_retinaface.kmodel root@<K230_IP_ADDRESS>:/sharefs/sample_face_ae/
K230 bigcore (msh) で実行¶
K230 のシリアルコンソール (ACM1) で実行します:
AE ROI を無効にして実行する場合:
シリアル接続¶
- Bigcore (RT-Smart msh):
/dev/ttyACM1、115200 bps
CMake ターゲット¶
設定¶
cmake -B build/sample_face_ae -S apps/sample_face_ae \
-DCMAKE_TOOLCHAIN_FILE="$(pwd)/cmake/toolchain-k230-rtsmart.cmake"
ターゲット一覧¶
| ターゲット | コマンド | 説明 |
|---|---|---|
| (デフォルト) | cmake --build build/sample_face_ae |
C++ バイナリのビルド |
deploy |
cmake --build build/sample_face_ae --target deploy |
ビルド + K230 への SCP 転送 |
run |
cmake --build build/sample_face_ae --target run |
シリアル経由で K230 実行 (Ctrl+C で終了) |
deploy¶
バイナリのビルドと K230 への SCP 転送を一括実行します:
転送されるファイル:
| ローカル | K230 上のパス |
|---|---|
build/sample_face_ae/sample_face_ae |
/sharefs/sample_face_ae/sample_face_ae |
apps/face_detect/scripts/output/dump/mobile_retinaface.kmodel |
/sharefs/sample_face_ae/mobile_retinaface.kmodel |
run¶
シリアルポート経由で K230 bigcore (msh) にコマンドを送信し、出力をリアルタイム表示します:
- キーボード入力はそのまま K230 に転送されます(
q+ Enter でアプリ終了) - Ctrl+C でシリアル接続を切断
K230 接続設定¶
CMake キャッシュ変数で接続先をカスタマイズできます:
| 変数 | デフォルト | 説明 |
|---|---|---|
K230_IP |
(空 = 自動検出) | littlecore の IP アドレス |
K230_USER |
root |
SSH ユーザー |
K230_SERIAL |
/dev/ttyACM1 |
bigcore シリアルポート (run 用) |
K230_SERIAL_LC |
/dev/ttyACM0 |
littlecore シリアル (IP 自動検出用) |
K230_BAUD |
115200 |
ボーレート |