一、项目概述

facecheck 是一个嵌入式人脸识别打卡系统,由客户端(ARM 开发板)和服务端(WSL/Linux PC)组成:

  • 客户端:运行在嵌入式板子上,通过摄像头采集人脸 → 识别身份 → 上报打卡数据到服务器
  • 服务端:接收 TCP 打卡请求 → 自动判断迟到/早退 → 存入 SQLite 数据库

二、项目结构

1
2
3
4
5
6
7
8
9
10
11
facecheck/
├── common/
│ └── protocol.h # 通信协议定义(C/S 共用)
├── server/
│ └── server.cpp # 服务端(TCP + SQLite)
├── client/
│ └── client.cpp # 客户端(人脸识别 + 打卡)
├── database/
│ └── schema.sql # 数据库建表 & 常用查询
├── Makefile
└── README.md

三、通信协议设计

3.1 帧格式

1
2
3
4
5
6
┌────────┬────────┬────────┬───────────┬────────┐
│ 帧头 │ 类型 │ 长度 │ 数据区 │ 帧尾 │
│ 2 Byte │ 1 Byte│ 2 Byte │ N Byte │ 2 Byte │
├────────┼────────┼────────┼───────────┼────────┤
│0x5AA5 │ TYPE │ N │ payload │0xA55A │
└────────┴────────┴────────┴───────────┴────────┘

3.2 打卡记录数据结构

1
2
3
4
5
6
7
typedef struct {
char name[32]; // 识别到的姓名
time_t timestamp; // Unix 时间戳
uint8_t type; // 0=上班 1=下班
uint8_t status; // 0=正常 1=迟到 2=早退
float confidence; // 人脸识别置信度 (0~1)
} checkin_record_t;

3.3 消息类型

类型码 含义 方向
0x01 打卡签到 客户端 → 服务端
0x02 服务端回复 服务端 → 客户端
0x03 查询考勤记录 客户端 → 服务端
0x05 心跳保活 双向

3.4 完整通信流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
客户端                              服务端
│ │
├─── TCP 三次握手 ──────────────────┤
│ │
├── [0x01] 打卡请求 ───────────────→│
│ name="张三" │
│ timestamp=xxx │ ① 验证帧头/帧尾
│ type=0 (上班) │ ② 解析打卡数据
│ confidence=0.92 │ ③ 判断迟到/早退
│ │ ④ 写入 SQLite
├←─ [0x02] 回复 ────────────────────┤
│ code=0 (成功) │
│ msg="张三 打卡成功!" │
│ │
├── [0x05] 心跳 ─────── 每30秒 ───→│
├←─ [0x05] alive ──────────────────┤

四、服务端设计

4.1 多线程模型

1
2
3
4
5
while (running) {
SOCKET client_fd = accept(...);
// 每个客户端独立线程处理
std::thread(handle_client, client_fd, ip).detach();
}

4.2 迟到/早退判定

1
2
3
4
5
6
7
8
9
10
11
uint8_t check_status(time_t now, uint8_t type) {
if (type == TYPE_WORK_ON) {
// 9:00 之后 → 迟到
if (hour > 9 || (hour == 9 && min > 0))
return 1;
} else {
// 17:00 之前 → 早退
if (hour < 17) return 2;
}
return 0; // 正常
}

4.3 SQLite 存储

1
2
3
4
5
6
7
8
CREATE TABLE checkin (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
timestamp INTEGER NOT NULL,
type INTEGER NOT NULL, -- 0=上班 1=下班
status INTEGER DEFAULT 0, -- 0=正常 1=迟到 2=早退
confidence REAL -- 置信度
);

五、客户端设计

5.1 主流程

1
2
3
4
5
6
7
8
9
10
11
12
main()

├─ connect_server() // 连接 TCP 服务器

└─ while(1)
├─ show_menu() // 1=上班 2=下班
├─ detect_face() // 人脸检测 & 识别
│ ├─ 返回 name
│ └─ 返回 confidence
├─ 构造 checkin_record
└─ send_checkin() // 上报到服务器
└─ 接收 reply 并显示

5.2 人脸识别接口(可替换)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int detect_face(char *name_out, float *confidence) {
/*
* 当前为模拟桩代码,替换为实际算法:
*
* 方案A: OpenCV Haar Cascade
* cv::CascadeClassifier face_cascade;
* face_cascade.load("haarcascade_frontalface.xml");
* cv::Mat gray; cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY);
* face_cascade.detectMultiScale(gray, faces);
*
* 方案B: dlib DNN
* dlib::frontal_face_detector detector;
* auto faces = detector(frame);
*
* 方案C: 云 API(百度/腾讯)
* POST 图片 base64 → 返回识别结果
*
* 方案D: K210 硬件模块
* UART 通信,发送命令 → 接收识别结果
*/
}

六、编译与部署

服务端(WSL/Linux PC)

1
2
3
cd facecheck
make server
build/server 8888

客户端

1
2
3
4
5
6
7
# 本机测试
make client
build/facecheck_client

# 交叉编译 → ARM 嵌入式板
make client CROSS=1
# 将 build/facecheck_client 拷到开发板

七、运行效果

服务端启动

1
2
3
4
5
6
7
8
9
10
11
╔══════════════════════════════════╗
║ facecheck 打卡服务器 ║
║ 端口: 8888 ║
║ 数据库: facecheck.db ║
║ Ctrl+C 退出 ║
╚══════════════════════════════════╝
[DB] 数据库初始化完成
[连接] 客户端 192.168.1.200 已连接
[打卡] 张三 | 2026-06-22 09:05 | 上班 | 置信度: 0.92 | 状态: 1(迟到)
[打卡] 李四 | 2026-06-22 08:55 | 上班 | 置信度: 0.95 | 状态: 0(正常)
[打卡] 王五 | 2026-06-22 17:30 | 下班 | 置信度: 0.88 | 状态: 0(正常)

客户端操作

1
2
3
4
5
6
7
8
9
10
11
12
13
╔══════════════════════════════════╗
║ 人脸识别打卡系统 ║
╠══════════════════════════════════╣
║ 1. 上班打卡 ║
║ 2. 下班打卡 ║
║ 0. 退出 ║
╚══════════════════════════════════╝
请选择: 1

[人脸检测] 请正对摄像头...
[识别成功] 张三 置信度: 92.50%
[打卡] 张三 上班...
[服务器回复] 张三 打卡成功!

八、SQL 数据分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-- 今日所有打卡记录
SELECT name,
datetime(timestamp, 'unixepoch', 'localtime') as time,
CASE type WHEN 0 THEN '上班' ELSE '下班' END as type,
CASE status WHEN 0 THEN '正常' WHEN 1 THEN '迟到' WHEN 2 THEN '早退' END
FROM checkin
WHERE date(timestamp, 'unixepoch') = date('now')
ORDER BY timestamp DESC;

-- 本月迟到统计
SELECT name, COUNT(*) as late_times
FROM checkin
WHERE type = 0 AND status = 1
AND strftime('%Y-%m', timestamp, 'unixepoch') = strftime('%Y-%m', 'now')
GROUP BY name
ORDER BY late_times DESC;

九、后续扩展

方向 说明
人脸录入系统 注册新用户时录入人脸特征向量
Web 管理后台 Django/Flask 搭建考勤管理页面
手机推送 打卡后微信通知直属领导
RFID 双因子 人脸 + 工卡双重验证
实时大屏 会议室大屏显示今日到岗人数

项目地址e:/facecheck/

技术栈:C/C++ · TCP Socket · SQLite3 · 人脸检测 · ARM 交叉编译