第 8 章:顔認識
この章の目標:顔特徴を登録し、NanoCam に「あなたは誰か」を認識させ、完全な入退室管理ソリューションを構築します。
原理
顔認識 = 顔検出(MSR01+MNP01 二段パイプライン)+ 特徴抽出(FaceRecognition112V1S8 MFN ニューラルネットワーク)+ コサイン類似度比較。
カメラ RGB565 フレーム
→ MSR01 粗検出(320×240, 0.3F 閾値)
→ MNP01 精検出(粗検出の候補枠に基づく, 0.4F 閾値)
→ 10 個の顔キーポイント抽出(両目/鼻先/口角)
→ キーポイントで位置合わせ → 112×112 に顔を切り出し
→ MFN 畳み込みネットワーク → 512 次元特徴ベクトル
→ L2 正規化
→ Flash に登録済みの全 ID ベクトルと順にコサイン距離を計算
→ 最大コサイン類似度 > 閾値(0.55) → マッチ成功 → ID を出力
→ すべての類似度 < 閾値 → 見知らぬ人 → "who?" を出力性能最適化
MFN の特徴抽出と登録済み全 ID との照合は計算量が大きく、毎フレーム実行すると画面がカクつきます。現在の実装はフレームスキップ戦略を採用:顔検出は毎フレーム実行(低コスト)、MFN 認識は 10 フレームごとに 1 回実行(高コスト)、ラベルは前回の認識結果を継続的に重ねて表示します。これにより画面は滑らかに保たれ、ID ラベルもちらつきません。
顔特徴の保存
登録済みの顔特徴(id + 512 次元 embedding)は Flash の fr パーティション(96 KB、最大 47 人分の顔 ID)に永続化されます。電源を切っても失われません。
ハードウェア準備
NanoCam コアボード + ベースボード
USB-C データケーブル(PC に接続して給電+シリアル)
シリアルアシスタント(ボーレート 115200)
手順
8.1 顔認識モードに入る
ai_mode:4デバイスは自動的に再起動して FaceID モードに入り、WS2812 RGB LED (GPIO18 DIN、VDD50 給電) が紫色に点灯します。再起動後、シリアルに次のように表示されるはずです:
I (5526) MFN: fr partition size: 98304 bytes, maxminum 47 IDs can be stored
I (5526) MFN: No face ID in flashNo face ID in flash はまだ誰の顔も登録されていないことを示します。正常です。
8.2 顔の登録
顔をカメラに正対させ(距離 30-50cm、照明が均一)、画面内に顔が 1 つだけであることを確認します。シリアルで送信:
face_erilデバイスが顔を検出すると、自動的に特徴を抽出して Flash に登録します:
I (xxxx) ENROLL: ID 1 is enrolled画面に青い文字 Enroll: ID 1 が重畳表示され、約 0.5 秒後に消えます。
注意:コマンドは
face_eril(enroll の略)であり、face_enrollではありません。fail: unknown commandが表示された場合は、綴りを確認してください。
8.3 顔の識別
登録完了後、認識コマンドを送信:
face_rzシステムは継続認識モードに入ります。現在の顔を Flash に登録済みのすべての ID と照合します:
マッチ成功:シリアルに
Similarity: 0.85, Match ID: 1を出力、画面に緑色のID: 1を継続的に重畳表示見知らぬ人:シリアルに
Similarity: 0.32, Match ID: 0を出力、画面に赤色のwho?を継続的に重畳表示
ラベルは継続表示され消えません。認識モードを終了するには
face_detectを送信し、純粋な検出モードに戻します。
8.4 顔の削除
face_del最後に登録した顔 ID を削除し、シリアルに N IDs left を返し、画面に残りの ID 数を短時間表示します。Flash 内の特徴も同時に削除されます。
8.5 認識モードの終了
face_detect純粋な顔検出モードに戻ります(枠+キーポイントのみ描画、認識はしない)。ID ラベルはクリアされます。
DETECT モードについて: ESP32-S3 では、純粋な顔検出モードのシリアル座標出力は無効化されています(
#if !CONFIG_IDF_TARGET_ESP32S3)。これはシリアルが検出ログで埋め尽くされるのを防ぐためです。認識モード(face_rz)に入って初めてdetection_result座標ログが出力されます。
完全コマンド早見表
| コマンド | 機能 | ラベル動作 | 継続表示 |
|---|---|---|---|
face_eril | 現在検出中の顔を登録 | 青 "Enroll: ID N" | 0.5s 点滅表示 |
face_rz | 継続認識モードに入る | 緑 "ID: N" / 赤 "who?" | ✅ 継続 |
face_del | 最後に登録した ID を削除 | 赤 "N IDs left" | 0.5s 点滅表示 |
face_detect | 認識を終了し純粋な検出に戻る | すべてのラベルをクリア | — |
完全なコマンドはシリアルプロトコルマニュアルを参照。
操作フロー例
ai_mode:4 # 顔認識モードに入る
[デバイス再起動、LED は紫色]
face_eril # 1 人目の顔を登録(田中)
→ ID 1 is enrolled
face_eril # 2 人目の顔を登録(佐藤)
→ ID 2 is enrolled
face_rz # 継続認識を開始
→ 田中がカメラの前に立つ: 画面に "ID: 1" が継続表示
→ 佐藤がカメラの前に立つ: 画面に "ID: 2" が継続表示
→ 見知らぬ人がカメラの前に立つ: 画面に "who?" が継続表示
face_detect # 認識モードを終了
→ ラベルが消え、検出枠のみ描画
face_del # 佐藤 (ID 2) を削除
→ 1 IDs left
face_rz # 再度認識
→ 田中がカメラの前に立つ: "ID: 1"
→ 佐藤がカメラの前に立つ: "who?" (削除済み)顔認識モードはメモリ使用量が大きくなります(MFN モデル + 顔検出の 2 モデル)。Type-C シリアル(UART0)は正常に動作します。シリアルが応答しない場合は、まずボーレートが 115200 か確認してください。
コード
コア認識ロジック
components/modules/ai/who_human_face_recognition.cpp — フレームスキップ認識戦略:
case RECOGNIZE:
{
// フレームスキップ: 検出 10 回につき 1 回 MFN 認識を実行
static int recog_skip = 0;
if (recog_skip <= 0) {
recognize_result = recognizer->recognize(
(uint16_t *)frame->buf,
{(int)frame->height, (int)frame->width, 3},
detect_results.front().keypoint);
recog_skip = 10;
}
recog_skip--;
frame_show_state = SHOW_STATE_RECOGNIZE;
break;
}トラブルシューティング
| 症状 | 考えられる原因 | 解決方法 |
|---|---|---|
No face ID in flash | 正常、まだ登録していない | face_eril を送信して登録 |
認識結果が常に who? | 照度不足/角度のずれ/類似度が閾値未満 | 再登録し、カメラに正対、照明を均一に |
| 登録時に反応がない | 画面内の顔が 1 枚ではない | 顔が 1 つだけであることを確認、距離 30-50cm |
| 認識時に画面がカクつく | 正常、MFN 推論に時間がかかる | フレームスキップで最適化済み、10 フレームごとに 1 回実行 |
| ラベルがちらつく | — | 修正済み、ラベルは継続表示され消えない |
fail: unknown command | コマンドの綴りミス | コマンドを確認:face_eril であり face_enroll ではない |
効果
顔を登録 → 継続認識で ID を表示 → I2C/シリアルで結果を出力 → リレー/サーボを制御。完全な入退室管理ソリューション。
次の章:第 9 章:音声対話

