第 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 特徵擷取與全庫比對運算量較大,每幀都執行會導致畫面卡頓。當前實作採用跳幀策略:人臉偵測每幀執行(成本低),MFN 辨識每 10 幀執行一次(成本高),標籤使用上一次辨識結果持續疊加顯示。這樣畫面保持流暢,ID 標籤不閃爍。
人臉特徵儲存
已註冊的人臉特徵(id + 512 維 embedding)持久化儲存在 Flash 的 fr 分區(96 KB,最多 47 個人臉 ID)。斷電不遺失。
硬體準備
- NanoCam 核心板 + 底板
- USB-C 傳輸線(接電腦供電 + 串列)
- 串列埠助手(波特率 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,光照均勻),確保畫面中只有一張人臉。在串列發送:
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 # 註冊第一個人臉(張三)
→ ID 1 is enrolled
face_eril # 註冊第二個人臉(李四)
→ 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 模型 + 人臉偵測雙模型),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 張 | 確保只有一張臉,距離 30-50cm |
| 辨識時畫面卡頓 | 正常,MFN 推理需要時間 | 已透過跳幀最佳化,每 10 幀執行一次 |
| 標籤閃爍 | — | 已修復,標籤持續顯示不消失 |
fail: unknown command | 指令拼寫錯誤 | 檢查指令:face_eril 不是 face_enroll |
效果
註冊人臉 → 持續辨識顯示 ID → I2C/串列輸出結果 → 控制繼電器/舵機,完整門禁方案。

