# K210 识别端文档 ## 1. K210 在系统中做什么 K210 负责“看见人脸并判断是谁”。它不直接决定能不能签到,最终签到判断由 STM32 完成。 K210 的职责包括: 1. 初始化摄像头和 LCD。 2. 加载人脸检测、关键点检测、特征提取三个 KPU 模型。 3. 从 SD 卡读取已经录入的人脸特征。 4. 实时检测画面中的人脸。 5. 将识别结果通过 UART1 发给 STM32。 6. 通过按键添加或删除本地人脸。 7. 保存新增人脸照片到 SD 卡。 8. 通过 K210 侧 ESP8266 上传照片到服务端。 9. 从服务端同步人脸 ID 到学号的映射。 10. 从服务端同步待删除任务,并删除本地特征。 ## 2. 相关文件 | 文件 | 作用 | | --- | --- | | `k210/main.py` | K210 主程序,包含识别、添加、删除、同步、上传照片 | | `k210/view_attendance.py` | 辅助脚本,用于查看旧版本地记录文件 | K210 程序依赖 SD 卡上的模型文件: ```text /sd/FaceDetection.smodel /sd/FaceLandmarkDetection.smodel /sd/FeatureExtraction.smodel ``` 如果模型文件不存在或路径错误,程序会在加载 KPU 模型时报错。 ## 3. 代码中的主要配置 位置:`k210/main.py` | 配置 | 当前值 | 说明 | | --- | --- | --- | | `WIFI_SSID` | `yzfh` | K210 侧 ESP8266 要连接的 WiFi | | `WIFI_PASSWORD` | `yzfhroot` | WiFi 密码 | | `SERVER_IP` | `27.106.113.205` | 服务端 IP | | `SERVER_PORT` | `8082` | 服务端端口 | | `API_TOKEN` | `atk_nKfVWLhMjL0RGSfRll3R_sdJS6IrIjuV` | 服务端鉴权 Token | | `SYNC_CHECK_INTERVAL_MS` | `50000` | 每 50 秒检查一次服务端同步请求 | | `NETWORK_FRAME_INTERVAL` | `300` | 每 300 帧处理一次网络任务 | | `LOCAL_FACE_PHOTO_DIR` | `/sd/face_photos` | 本地照片缓存目录 | | `CAMERA_HMIRROR` | `1` | 水平镜像 | | `CAMERA_VFLIP` | `1` | 垂直翻转 | ## 4. 硬件连接 | 功能 | K210 引脚 | 说明 | | --- | --- | --- | | 发给 STM32 | 24 | UART1 TX | | 收 STM32 | 25 | UART1 RX | | 发给 ESP8266 | 34 | UART2 TX | | 收 ESP8266 | 35 | UART2 RX | | 蓝/绿/红 LED | 12 / 13 / 14 | 状态提示 | | 按键 | 16 | 添加、删除、删除全部 | UART 参数: ```text 115200, 8 data bits, no parity, 1 stop bit ``` ## 5. SD 卡文件 | 文件或目录 | 作用 | | --- | --- | | `/sd/recordftr.txt` | 人脸特征库,每行一个人脸 | | `/sd/face_mapping.txt` | face_id 到学号的本地映射 | | `/sd/sync_version.txt` | K210 已同步到的服务端版本号 | | `/sd/face_photos/` | 新增人脸时保存的本地照片 | | `/sd/FaceDetection.smodel` | 人脸检测模型 | | `/sd/FaceLandmarkDetection.smodel` | 人脸关键点模型 | | `/sd/FeatureExtraction.smodel` | 人脸特征提取模型 | `recordftr.txt` 的一行大致是: ```text ID:1#[0.0123, -0.0456, ...] ``` 或同步映射后: ```text 20240001#[0.0123, -0.0456, ...] ``` 代码中已经不再用 `eval` 解析特征,而是只解析安全的浮点数组文本。 ## 6. 启动流程 K210 启动后主要执行: 1. 设置堆内存到 1MB。 2. 初始化 UART1 和 UART2。 3. 初始化 K210 侧 ESP8266,尝试连接 WiFi。 4. 加载本地映射 `/sd/face_mapping.txt`。 5. 加载本地同步版本 `/sd/sync_version.txt`。 6. 加载三个 KPU 模型。 7. 初始化 LCD 和摄像头。 8. 初始化按键中断。 9. 加载本地人脸特征库 `/sd/recordftr.txt`。 10. 扫描本地照片目录,把未上传照片加入队列。 11. 如果 WiFi 可用,执行一次统一同步。 12. 进入主循环。 ## 7. 人脸识别流程 每一帧画面大致按下面处理: 1. 摄像头采集图像。 2. `task_fd` 做人脸检测。 3. `task_ld` 做关键点定位。 4. 根据关键点做仿射变换,把人脸对齐到 128x128。 5. `task_fe` 提取人脸特征。 6. 与 `peoples` 中的本地特征逐个比对。 7. 如果最高分大于 `85`,认为识别成功。 8. 如果识别成功,LCD 画绿色框;陌生人画红色框。 9. 每隔 `SEND_INTERVAL_MS = 1000` 毫秒,向 STM32 发送一次状态变化。 发给 STM32 的格式: ```text ID:<学号或face_id>,NAME:<显示名>,CONF:<置信度> ``` 示例: ```text ID:20240001,NAME:20240001,CONF:0.95 ``` 如果陌生人: ```text UNKNOWN ``` ## 8. 按键操作 | 操作 | 程序状态 | 作用 | | --- | --- | --- | | 短按 | 正常识别界面 | 进入添加人脸模式 | | 长按约 2 秒 | 正常识别界面 | 进入删除人脸模式 | | 超长按约 5 秒 | 正常识别界面 | 进入删除全部人脸模式 | | 添加模式中短按 | 检测到陌生人脸时 | 确认添加 | | 添加模式中长按 | 添加模式 | 退出添加模式 | | 删除模式中短按 | 删除模式 | 切换候选项 | | 删除模式中长按 | 删除模式 | 确认删除当前项 | ## 9. 添加人脸流程 1. 正常识别界面短按按键。 2. LCD 显示 `Add Face Mode`。 3. 摄像头检测到陌生人脸后显示 `Ready`。 4. 再短按确认添加。 5. K210 分配一个未使用的 `face_id`,例如 `1`。 6. 特征写入 `/sd/recordftr.txt`,名称为 `ID:1`。 7. 当前画面压缩为 JPEG。 8. JPEG 保存到 `/sd/face_photos/1.jpg`。 9. `1` 加入照片上传队列。 10. 后续网络任务会上传到服务端。 服务端接收接口: ```text POST /api/v1/faces/photos/1 ``` ## 10. 人脸映射同步 新增人脸后,K210 只知道它是 `ID:1`,不知道真实学号。管理员需要在 Qt 管理端把 `1` 映射成学号: ```json { "mappings": { "1": "20240001" } } ``` K210 同步后会: 1. 拉取服务端 `face_mappings`。 2. 修改本地 `face_mapping.txt`。 3. 修改 `recordftr.txt` 中对应人脸的名称。 4. 后续发送给 STM32 的 ID 就会变成真实学号。 ## 11. 照片上传队列 K210 不会在识别每一帧时都做网络请求,因为网络请求会阻塞画面。它采用“分时网络任务”: 1. 新照片先保存到 SD 卡。 2. 只把 face_id 放入 `photo_upload_queue`。 3. 每隔一定帧数,主循环处理一个网络任务。 4. 如果上传失败,重新放回队列。 这样可以减少卡顿,并且即使网络临时不可用,照片也不会丢,因为原始 JPEG 还在 SD 卡。 ## 12. 服务端同步 K210 主要使用统一同步接口: ```text GET /api/v1/sync/state?client=k210&last_version=<本地版本> ``` 如果有变化,服务端返回 K210 需要的数据: ```json { "version": 5, "changed": true, "state": { "face_mappings": { "1": "20240001" }, "pending_delete": ["1"], "delete_tasks": [ { "task_id": "delete-1", "face_id": "1" } ] } } ``` K210 会先处理删除任务,再应用映射。删除成功后发送 ACK: ```json { "client": "k210", "version": 5, "deleted": ["1"], "task_ids": ["delete-1"] } ``` 如果 ACK 失败,K210 不会推进本地版本号,下一次还会重试。 ## 13. 删除人脸 K210 本地删除有两种来源: ### 13.1 K210 按键本地删除 这只会删除 K210 本地 `recordftr.txt` 和本地照片,不会自动删除服务端记录。适合现场维护。 ### 13.2 Qt 管理端远程删除 Qt 删除会在服务端创建待删除任务。K210 同步后删除本地人脸,并向服务端确认。适合后台统一管理。 ## 14. K210 常用接口 | 方法 | 路径 | 用途 | | --- | --- | --- | | `POST` | `/api/v1/faces/photos/` | 上传 JPEG 照片 | | `GET` | `/api/v1/faces/photos` | 查询服务端已有照片 | | `GET` | `/api/v1/faces/mappings` | 拉取人脸 ID 到学号映射 | | `GET` | `/api/v1/faces/pending-delete` | 拉取待删除列表 | | `POST` | `/api/v1/faces/delete-ack` | 旧式删除确认 | | `GET` | `/api/v1/sync/state?client=k210&last_version=N` | 推荐统一同步 | | `POST` | `/api/v1/sync/ack` | 推荐统一同步确认 | | `GET` | `/api/v1/sync/request` | 查询 Qt/服务端是否请求同步 | | `POST` | `/api/v1/sync/request/ack` | 确认收到同步请求 | ## 15. 常见问题 | 现象 | 可能原因 | 处理 | | --- | --- | --- | | 模型加载失败 | SD 卡缺少 `.smodel` 文件 | 把三个模型放到 `/sd/` 根目录 | | WiFi 连接失败 | SSID/密码错误、ESP8266 未启动、波特率不匹配 | 看串口日志,代码会尝试多个波特率 | | 添加人脸失败 | 没检测到陌生人脸、SD 卡不可写、照片保存失败 | 检查光照、SD 卡和日志 | | Qt 看不到照片 | 上传队列未完成、服务端地址不一致、Token 错误 | 看 K210 `[PHOTO]`、`[NET]`、`[ESP]` 日志 | | 删除后仍识别 | K210 尚未同步或 ACK 失败 | 等待同步,检查 `/api/v1/sync/state` | | 发给 STM32 的还是 `ID:1` | 映射没有保存或 K210 未同步 | Qt 保存映射后触发同步 | ## 16. 修改配置时要注意 1. K210 的服务端 IP、端口、Token 必须和服务端一致。 2. K210 的 WiFi 配置和 STM32 可以相同,也可以不同,但都要能访问服务端。 3. K210 侧照片上传使用自己的 ESP8266,不依赖 STM32 的 ESP8266。 4. K210 本地 SD 卡数据很重要,删除或格式化 SD 卡会丢失本地人脸特征。 5. 如果重新录入人脸,原 face_id 可能变化,需要重新在 Qt 管理端设置映射。