初始化项目文档
This commit is contained in:
+288
@@ -0,0 +1,288 @@
|
||||
# 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 程序依赖 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, ...]
|
||||
```
|
||||
|
||||
程序只解析安全的浮点数组文本,不执行任意表达式。
|
||||
|
||||
当前同步映射不会把 `recordftr.txt` 中的 `ID:1` 改成学号;真实学号保存在 `/sd/face_mapping.txt`,识别发送给 STM32 前再转换。
|
||||
|
||||
## 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` 中的原始 `ID:<face_id>` 不变。
|
||||
4. 识别成功后先取原始 `face_id`,再通过 `face_mapping.txt` 转成真实学号发送给 STM32。
|
||||
5. 未绑定学号的人脸按 `UNKNOWN` 处理,不参与签到。
|
||||
|
||||
## 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/<face_id>` | 上传 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 管理端设置映射。
|
||||
Reference in New Issue
Block a user