Initial commit: project setup with CMake

This commit is contained in:
HP 2026-06-04 19:32:20 +08:00
commit 8a69fa01c9
11 changed files with 541 additions and 0 deletions

44
.gitignore vendored Normal file
View File

@ -0,0 +1,44 @@
# Build directories
build/
build-*/
cmake-build-*/
out/
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
# CMake
CMakeCache.txt
CMakeFiles/
cmake_install.cmake
Makefile
compile_commands.json
CTestTestfile.cmake
# Compiled binaries
*.exe
*.out
*.app
*.dll
*.so
*.a
*.lib
# OS files
.DS_Store
Thumbs.db
# Runtime data (large files / generated content)
data/faces/*
data/images/*
data/results/*
data/database/*
!data/*/.gitkeep
# Models (large binary files, if needed use Git LFS)
models/*/*
!models/*/.gitkeep

0
CMakeLists.txt Normal file
View File

0
README.md Normal file
View File

View File

@ -0,0 +1,497 @@
# 课前拍照打卡系统实现规划
## 1. 系统目标
本系统基于 IMX6ULL_ALPHA 板端单机运行,优先拆分为两个相对独立的功能:
1. 大图人头数统计功能:对一张课堂大图进行检测,统计图片中出现的人数或人头数。
2. 单张人脸匹配功能:对单个清晰人脸进行识别匹配,判断该人脸是否属于已注册人员。
当前阶段不直接实现“课堂大图中所有人脸逐一识别”的完整流程,而是先完成两个基础能力:
- 证明板端能够完成轻量目标检测。
- 证明板端能够完成单人脸特征提取和数据库匹配。
- 为后续合并成完整课前拍照打卡流程做准备。
## 2. 技术路线
### 2.1 推荐技术栈
- 操作系统Linux运行在 IMX6ULL_ALPHA 开发板。
- 图像采集V4L2 摄像头接口。
- 图像处理OpenCV。
- 模型推理ncnn 或 TFLite Micro/TFLite。
- 数据存储SQLite。
- 配置文件JSON 或 INI。
- 日志:本地文本日志。
### 2.2 模型选择建议
大图人头数统计可以选择:
- YOLOv5n/YOLOv8n 的轻量化人头检测模型。
- YOLO-Fastest 人头检测模型。
- NanoDet 或其他轻量目标检测模型。
- 如果只做人脸计数,也可以使用 YuNet 等轻量人脸检测模型。
单张人脸匹配可以选择:
- MobileFaceNet。
- SFace。
- 其他轻量 ArcFace 结构模型。
模型需要尽量转换为适合 ARM CPU 推理的格式:
- ncnn`.param` + `.bin`
- TFLite`.tflite`
## 3. 功能拆分
## 3.1 大图人头数统计功能
### 3.1.1 功能目标
输入一张课堂大图,系统检测图中所有人头或人脸位置,输出人数统计结果,并保存检测信息。
### 3.1.2 需要实现的功能
1. 摄像头拍照
- 从 USB 摄像头或 DVP 摄像头采集一帧图片。
- 保存原始图片到本地。
- 支持从本地图片文件读取,方便调试。
2. 图片预处理
- 调整图片尺寸。
- 格式转换,如 BGR/RGB。
- 归一化处理。
- 根据模型输入要求进行 padding 或 resize。
3. 人头检测推理
- 加载轻量检测模型。
- 对课堂大图执行推理。
- 输出候选框、置信度、类别。
4. 后处理
- 解析模型输出。
- 执行 NMS 去重。
- 过滤低置信度目标。
- 统计最终人头数量。
5. 结果保存
- 保存检测框坐标。
- 保存统计人数。
- 保存检测时间。
- 保存带框的结果图片。
- 将结果写入 SQLite 数据库。
6. 结果显示
- 在终端输出统计结果。
- 后续可扩展到 LCD 或 Web 页面展示。
### 3.1.3 输出结果示例
```json
{
"image_path": "data/images/session_001.jpg",
"result_image_path": "data/results/session_001_detected.jpg",
"head_count": 36,
"detections": [
{
"x": 120,
"y": 85,
"w": 32,
"h": 36,
"score": 0.91
}
],
"created_at": "2026-06-04 09:00:00"
}
```
## 3.2 单张人脸匹配功能
### 3.2.1 功能目标
输入一张单人脸图片,系统提取人脸特征,与本地数据库中的注册人脸特征进行匹配,输出识别结果。
### 3.2.2 需要实现的功能
1. 人员注册
- 输入学生姓名、学号、班级等信息。
- 采集或导入单张人脸图片。
- 检测图片中的人脸。
- 裁剪并对齐人脸。
- 提取人脸特征向量。
- 保存人员信息和特征向量到 SQLite。
2. 单张人脸检测
- 从图片中检测单个人脸。
- 如果检测到多张人脸,默认选择最大或最清晰的人脸。
- 如果未检测到人脸,返回失败信息。
3. 人脸对齐
- 根据眼睛、鼻尖、嘴角等关键点进行对齐。
- 输出统一尺寸的人脸图,例如 `112x112`
4. 特征提取
- 加载轻量人脸识别模型。
- 输出固定长度特征向量。
- 对特征向量进行归一化。
5. 特征匹配
- 从 SQLite 读取已注册人员特征。
- 使用余弦相似度或欧氏距离进行比较。
- 找到最高分人员。
- 根据阈值判断是否识别成功。
6. 识别记录保存
- 保存识别图片路径。
- 保存匹配到的学生 ID。
- 保存相似度分数。
- 保存识别状态。
- 保存识别时间。
### 3.2.3 输出结果示例
```json
{
"input_image": "data/images/face_test_001.jpg",
"matched": true,
"student_id": "20240001",
"name": "张三",
"score": 0.82,
"threshold": 0.75,
"created_at": "2026-06-04 09:05:00"
}
```
## 4. 建议目录结构
```text
attendance-system/
├── README.md
├── SYSTEM_IMPLEMENTATION_PLAN.md
├── CMakeLists.txt
├── config/
│ ├── app_config.json
│ ├── camera_config.json
│ └── model_config.json
├── models/
│ ├── head_detect/
│ │ ├── head_detect.param
│ │ └── head_detect.bin
│ └── face_recognition/
│ ├── face_detect.param
│ ├── face_detect.bin
│ ├── face_feature.param
│ └── face_feature.bin
├── data/
│ ├── images/
│ ├── faces/
│ ├── results/
│ └── database/
│ └── attendance.db
├── include/
│ ├── app/
│ │ ├── app_context.h
│ │ └── app_config.h
│ ├── camera/
│ │ └── camera_capture.h
│ ├── common/
│ │ ├── image_utils.h
│ │ ├── logger.h
│ │ └── time_utils.h
│ ├── database/
│ │ ├── attendance_db.h
│ │ └── face_repository.h
│ ├── head_count/
│ │ ├── head_counter.h
│ │ ├── head_detector.h
│ │ └── detect_postprocess.h
│ └── face_match/
│ ├── face_detector.h
│ ├── face_aligner.h
│ ├── face_feature_extractor.h
│ └── face_matcher.h
├── src/
│ ├── main.cpp
│ ├── app/
│ │ ├── app_context.cpp
│ │ └── app_config.cpp
│ ├── camera/
│ │ └── camera_capture.cpp
│ ├── common/
│ │ ├── image_utils.cpp
│ │ ├── logger.cpp
│ │ └── time_utils.cpp
│ ├── database/
│ │ ├── attendance_db.cpp
│ │ └── face_repository.cpp
│ ├── head_count/
│ │ ├── head_counter.cpp
│ │ ├── head_detector.cpp
│ │ └── detect_postprocess.cpp
│ └── face_match/
│ ├── face_detector.cpp
│ ├── face_aligner.cpp
│ ├── face_feature_extractor.cpp
│ └── face_matcher.cpp
├── tools/
│ ├── register_face.cpp
│ ├── test_head_count.cpp
│ ├── test_face_match.cpp
│ └── init_database.cpp
├── scripts/
│ ├── build_arm.sh
│ ├── build_pc.sh
│ └── convert_model.md
├── tests/
│ ├── test_head_postprocess.cpp
│ └── test_face_similarity.cpp
└── docs/
├── database_design.md
├── model_deployment.md
└── board_deployment.md
```
## 5. 主要文件功能说明
### 5.1 根目录文件
| 文件 | 功能 |
| --- | --- |
| `README.md` | 项目说明、编译方式、运行方式 |
| `SYSTEM_IMPLEMENTATION_PLAN.md` | 当前系统实现规划 |
| `CMakeLists.txt` | C++ 工程编译配置 |
### 5.2 配置目录
| 文件 | 功能 |
| --- | --- |
| `config/app_config.json` | 系统运行参数,如日志级别、数据目录、是否保存结果图 |
| `config/camera_config.json` | 摄像头设备号、分辨率、帧率、图片格式 |
| `config/model_config.json` | 模型路径、输入尺寸、置信度阈值、匹配阈值 |
### 5.3 模型目录
| 文件或目录 | 功能 |
| --- | --- |
| `models/head_detect/` | 大图人头检测模型 |
| `models/face_recognition/face_detect.*` | 单张人脸检测模型 |
| `models/face_recognition/face_feature.*` | 人脸特征提取模型 |
### 5.4 数据目录
| 目录或文件 | 功能 |
| --- | --- |
| `data/images/` | 原始拍照图片和测试图片 |
| `data/faces/` | 注册时裁剪后的人脸图片 |
| `data/results/` | 检测后带框图片、识别结果图片 |
| `data/database/attendance.db` | SQLite 数据库文件 |
### 5.5 摄像头模块
| 文件 | 功能 |
| --- | --- |
| `include/camera/camera_capture.h` | 摄像头采集接口定义 |
| `src/camera/camera_capture.cpp` | V4L2 或 OpenCV 摄像头采集实现 |
### 5.6 大图人头数统计模块
| 文件 | 功能 |
| --- | --- |
| `include/head_count/head_detector.h` | 人头检测模型接口定义 |
| `src/head_count/head_detector.cpp` | 加载模型并执行人头检测 |
| `include/head_count/detect_postprocess.h` | 检测后处理接口定义 |
| `src/head_count/detect_postprocess.cpp` | 解码模型输出、NMS、置信度过滤 |
| `include/head_count/head_counter.h` | 人头统计主流程接口 |
| `src/head_count/head_counter.cpp` | 调用预处理、检测、后处理并输出人数 |
### 5.7 单张人脸匹配模块
| 文件 | 功能 |
| --- | --- |
| `include/face_match/face_detector.h` | 人脸检测接口定义 |
| `src/face_match/face_detector.cpp` | 检测输入图片中的人脸 |
| `include/face_match/face_aligner.h` | 人脸对齐接口定义 |
| `src/face_match/face_aligner.cpp` | 根据关键点裁剪并对齐人脸 |
| `include/face_match/face_feature_extractor.h` | 人脸特征提取接口定义 |
| `src/face_match/face_feature_extractor.cpp` | 调用模型生成人脸特征向量 |
| `include/face_match/face_matcher.h` | 人脸匹配接口定义 |
| `src/face_match/face_matcher.cpp` | 计算相似度并返回最佳匹配人员 |
### 5.8 数据库模块
| 文件 | 功能 |
| --- | --- |
| `include/database/attendance_db.h` | 数据库初始化、连接、通用操作接口 |
| `src/database/attendance_db.cpp` | SQLite 数据库操作实现 |
| `include/database/face_repository.h` | 人员信息和人脸特征数据访问接口 |
| `src/database/face_repository.cpp` | 注册人员、读取特征、保存识别记录 |
### 5.9 公共工具模块
| 文件 | 功能 |
| --- | --- |
| `include/common/image_utils.h` | 图片读取、保存、缩放、画框等工具函数 |
| `src/common/image_utils.cpp` | 图片工具函数实现 |
| `include/common/logger.h` | 日志接口定义 |
| `src/common/logger.cpp` | 日志输出实现 |
| `include/common/time_utils.h` | 时间格式化接口 |
| `src/common/time_utils.cpp` | 时间工具实现 |
### 5.10 工具程序
| 文件 | 功能 |
| --- | --- |
| `tools/init_database.cpp` | 初始化 SQLite 表结构 |
| `tools/register_face.cpp` | 注册学生人脸信息 |
| `tools/test_head_count.cpp` | 输入大图,测试人头统计功能 |
| `tools/test_face_match.cpp` | 输入单人脸图,测试人脸匹配功能 |
## 6. 数据库初步设计
### 6.1 students 表
保存学生基础信息。
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `id` | INTEGER | 主键 |
| `student_no` | TEXT | 学号 |
| `name` | TEXT | 姓名 |
| `class_name` | TEXT | 班级 |
| `created_at` | TEXT | 创建时间 |
### 6.2 face_templates 表
保存注册人脸特征。
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `id` | INTEGER | 主键 |
| `student_id` | INTEGER | 对应学生 ID |
| `face_image_path` | TEXT | 注册人脸图片路径 |
| `feature` | BLOB | 人脸特征向量 |
| `feature_dim` | INTEGER | 特征维度 |
| `model_version` | TEXT | 特征模型版本 |
| `created_at` | TEXT | 创建时间 |
### 6.3 head_count_records 表
保存大图人头统计结果。
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `id` | INTEGER | 主键 |
| `image_path` | TEXT | 原图路径 |
| `result_image_path` | TEXT | 带框结果图路径 |
| `head_count` | INTEGER | 统计人数 |
| `detections_json` | TEXT | 检测框 JSON |
| `created_at` | TEXT | 创建时间 |
### 6.4 face_match_records 表
保存单张人脸识别记录。
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `id` | INTEGER | 主键 |
| `input_image_path` | TEXT | 输入图片路径 |
| `matched_student_id` | INTEGER | 匹配学生 ID未匹配时为空 |
| `score` | REAL | 相似度分数 |
| `threshold` | REAL | 使用的匹配阈值 |
| `status` | TEXT | `matched`、`unknown`、`failed` |
| `created_at` | TEXT | 创建时间 |
## 7. 主程序运行模式
主程序可以先设计为命令行方式,方便调试和答辩展示。
### 7.1 大图人头统计
```bash
./attendance_app --mode head_count --image data/images/classroom.jpg
```
输出:
```text
head count: 36
result image: data/results/classroom_detected.jpg
```
### 7.2 注册人脸
```bash
./register_face --student-no 20240001 --name zhangsan --class-name class01 --image data/faces/zhangsan.jpg
```
输出:
```text
register success: 20240001 zhangsan
```
### 7.3 单张人脸匹配
```bash
./attendance_app --mode face_match --image data/images/test_face.jpg
```
输出:
```text
matched: true
student_no: 20240001
name: zhangsan
score: 0.82
```
## 8. 实施顺序
建议按以下顺序实现:
1. 搭建 CMake 工程目录。
2. 实现图片读取、保存、画框等基础工具。
3. 实现 SQLite 数据库初始化。
4. 在 PC 上跑通大图人头统计模型。
5. 在 PC 上跑通单张人脸匹配模型。
6. 将模型转换为 ncnn 或 TFLite 格式。
7. 交叉编译 OpenCV、SQLite、ncnn/TFLite 到 IMX6ULL。
8. 将程序部署到 IMX6ULL_ALPHA 板端。
9. 测试摄像头拍照。
10. 测试板端人头统计速度和准确率。
11. 测试板端单张人脸匹配速度和准确率。
12. 根据实际性能调整模型大小、输入分辨率和阈值。
## 9. 当前阶段验收标准
### 9.1 大图人头统计
- 能读取一张课堂大图。
- 能检测出主要人头或人脸位置。
- 能输出人数统计值。
- 能保存带检测框的结果图片。
- 能把统计结果写入 SQLite。
### 9.2 单张人脸匹配
- 能注册至少 5 名学生的人脸。
- 能对单张清晰人脸进行匹配。
- 能输出姓名、学号、相似度。
- 能识别未知人员。
- 能把识别记录写入 SQLite。
## 10. 后续扩展方向
完成两个基础功能后,可以继续扩展为完整课前拍照打卡系统:
1. 将大图中的每个人脸裁剪出来。
2. 对每个人脸分别执行特征提取。
3. 与数据库中所有学生特征进行匹配。
4. 对同一学生的多个匹配结果进行去重。
5. 生成一次课堂考勤记录。
6. 添加 LCD 显示界面或 Web 管理页面。
7. 添加人工复核功能,修正误识别和漏识别结果。

0
data/database/.gitkeep Normal file
View File

0
data/faces/.gitkeep Normal file
View File

0
data/images/.gitkeep Normal file
View File

0
data/results/.gitkeep Normal file
View File

View File

View File

0
src/main.cpp Normal file
View File