> 身份验证还能这么做?无需昂贵设备,普通摄像头 + 开源代码就能实现——我理想中的“开源代码自由”之首次尝试
图1:人脸识别结果图——姓名+编号
保护隐私需要,加了个卡通眼镜贴纸,哈哈
---
## 一、项目背景
每年各类考试期间,考场身份验证都是个头疼的问题。传统的人工核验效率低、易出错,而商业人脸识别设备动辄上万。
我们培训基地早几年前就请专业人员安装了这么一套人脸识别系统。但是现在有了ai辅助,我也想自己手搓一个:
能不能用普通摄像头 + 开源技术,搭建一套**低成本、高准确率**的人脸识别认证系统?
这就是我这次要完成的尝试。
---
## 二、技术选型
### 为什么不用 face_recognition?
最初考虑了著名的 `face_recognition` 库(基于 dlib),但它有几个问题:
1.**安装复杂** - dlib 需要编译 C++ 扩展,Windows 下各种依赖问题
2.**体积庞大** - 完整安装后超过 500MB
3.**运行较慢** - 实时识别时 FPS 较低
### 最终方案:OpenCV + OpenFace
我最终选择了更轻量的方案:
```
- OpenCV:开源计算机视觉库,人脸检测用 Haar 级联
- OpenFace:Facebook 开源的人脸识别模型,仅 30MB
- PIL:用于中文字符渲染(OpenCV 原生不支持中文)
```
**优势:**
- ✅ 安装简单,`pip install opencv-python pillow` 即可
- ✅ 总占用不到 100MB
- ✅ 实时识别 FPS 可达 15-20
**提示词**
- 告诉OpenClaw你想要的是什么:我想做一个人脸识别系统,你可以在GitHub上找一些开源项目,我们再根据需要调整。
最简单的方法就是这样了,从第一句提示词开始,擦亮你的阿拉丁神灯。
接下来就是根据 助理的反馈+你的持续提问调试修正。这个阶段比拼的是能“耐烦”,因为一开始并不一定能达到你理想的目标,你和你的助理都在学习。
---
## 三、核心实现
### 1. 人脸录入(enroll_lite.py)
录入流程:
```python
# 1. 打开摄像头采集人脸
# 2. 使用 Haar 级联检测人脸位置
# 3. 用 OpenFace 提取 128 维特征向量
# 4. 保存为 .npy 文件
```
**关键代码:**
(这里所有的代码不懂也没关系,我也不是很懂😓)
```python
defget_face_encoding(frame, face_rect):
"""从人脸区域提取特征编码"""
x1, y1, x2, y2 = face_rect
face_roi = frame[y1:y2, x1:x2]
# 缩放到 OpenFace 要求的 96x96
face_roi = cv2.resize(face_roi, (96, 96))
# 转换为 blob 输入神经网络
blob = cv2.dnn.blobFromImage(face_roi, 1/255.0, (96, 96),
(0, 0, 0), swapRB=True, crop=False)
recog_net.setInput(blob)
embedding = recog_net.forward()
return embedding.flatten()
```
**录入建议:**
- 每人拍摄 5-10 张照片
- 覆盖不同角度(正面、左偏、右偏)
- 不同光线条件(室内光、自然光)
---
### 2. 实时识别(run_final.py)
识别流程:
```
摄像头画面 → 人脸检测 → 特征提取 → 特征匹配 → 显示结果
↓
距离 < 阈值 → 绿色框(已录入)
距离 ≥ 阈值 → 红色框(未知)
```
**核心匹配逻辑:**
```python
# 计算待识别人脸与所有已知人脸的距离
distances = [np.linalg.norm(embedding - ke) for ke in known_encodings]
best_idx = np.argmin(distances)
best_dist = distances[best_idx]
# 距离小于阈值则认为是已录入人员
if best_dist < RECOGNITION_THRESHOLD:
name = known_names[best_idx]
color = (0, 255, 0) # 绿色
else:
name = "未知人员"
color = (0, 0, 255) # 红色
```
---
### 3. 解决识别闪烁问题
**问题现象:** 绿色框不停跳动,识别结果不稳定
**原因分析:**
1. 单帧识别容易受光线、角度影响
2. 距离阈值临界时反复横跳
**解决方案:** 时间窗口平滑
```python
# 配置参数
STABLE_COUNT = 2# 连续 2 帧相同才确认
LOST_COUNT = 5# 连续 5 帧丢失才切换状态
# 稳定性跟踪
if rec_name == stable_name:
stable_count += 1
else:
stable_name = rec_name
stable_count = 1
# 达到稳定帧数才更新显示
if stable_count >= STABLE_COUNT:
display_name = rec_name
```
**效果:** 识别结果平滑,不再闪烁
---
## 四、参数调优经验
### 识别阈值(RECOGNITION_THRESHOLD)
| 阈值 | 效果 | 适用场景 |
|----|-------------|--------|
| 1.0 | 严格,误识率低 |高安全场景|
| 1.2 | 平衡 | 一般场景 |
| 1.5 | 宽松,识别率高 | 熟人场景 |
**调试技巧:** 在控制台打印距离值,观察已录入人员的典型距离分布
```python
print(f"识别:{name} - 距离={best_dist:.3f}")
```
### 稳定帧数(STABLE_COUNT)
- 设为 1:响应最快,但容易闪烁
- 设为 2-3:平衡响应和稳定(推荐)
- 设为 5+:非常稳定,但切换有延迟
---
## 五、最终效果
### 识别演示
```
┌─────────────────────────────────┐
│ ┌───────────────┐ │
│ │ 吴佟 | 9680 │ ← 绿色框 │
│ │ (85%) │ 已录入人员 │
│ └───────────────┘ │
│ │
│ ┌───────────────┐ │
│ │ 未知人员 │ ← 红色框 │
│ │ │ 未录入人员 │
│ └───────────────┘ │
└─────────────────────────────────┘
```
### 性能指标
| 指标 | 数值 |
|------|------|
| 人脸检测速度 | ~30ms/帧 |
| 识别速度 | ~50ms/次 |
| 整体 FPS | 15-20 |
| 识别准确率 | >95%(正常光线) |
---
## 六、部署指南
### 环境要求
```
- Python 3.8+
- Windows / Linux / macOS
- 普通 USB 摄像头(640x480 即可)
```
### 安装步骤
```bash
# 1. 克隆项目
gitclone <repo-url>
cdface_auth_system
# 2. 安装依赖
pipinstallopencv-pythonpillownumpy
# 3. 下载模型
pythondownload_models.py
# 4. 录入人脸
pythonenroll_lite.py
# 5. 启动识别
pythonrun_final.py
```
### 目录结构
```
face_auth_system/
├── run_final.py # 主程序(实时识别)
├── enroll_lite.py # 人脸录入
├── database.json # 人员数据库
├── known_faces/ # 人脸特征文件
│ └── 9680.npy
├── openface.nn4.small2.v1.t7 # OpenFace 模型
└── requirements.txt
```
###⚠️ 当前局限与注意事项
- 无活体检测 — 无法区分真人和照片/视频,考场场景存在作弊风险
- 环境依赖 — 光线不足、侧脸、遮挡(口罩/墨镜)会显著降低识别准确率
- 距离敏感 — 最佳识别距离 0.8-1.2 米,过远或过近可能识别失败
- 本地存储 — 人脸特征和数据存储于本地,多设备无法同步,人员需重新录入
- 规模限制 — 适合 100 人以内场景,人员过多时识别速度和精度会下降
适用场景推荐: 小型考场、会议室签到、内部人员验证等低安全风险场景
不适用场景: 高安全门禁、大规模考场、无人值守验证等
---
## 七、后续优化方向
1.**多人同时识别** - 当前只处理最大人脸,可扩展为多人
2.**活体检测** - 防止照片/视频攻击
3.**数据库管理** - 添加删除、更新人员功能
4.**日志记录** - 记录每次识别的时间、人员
5.**Web 界面** - 浏览器远程查看识别状态
---
## 八、完整代码
项目已开源,欢迎 Star & Fork:
```
GitHub: https://github.com/wy170/face-auth-system
```
心心念念的GitHub上的完整项目的个人首秀——开源代码自由的第一步✌
当然,单机版的小程序,去年一年也整了不少,但都比较简单的在本地,欢迎咨询。沉迷于喜爱的事,总是很开心!😀祝愿每位同仁都能找到一生所爱,半生也行……
---
## 结语
这套系统的总成本:
- 💻 硬件:普通 USB 摄像头(¥50-100)
- 📦 软件:全部开源免费
- ⏱️ 开发:3 天工余时间完成核心功能
用开源技术解决实际问题,这就是编程的魅力。
**代码不多,但每一步都经过实践。** 希望这篇文章也能帮到你。
备注:因为等待免费调用额度的每日更新太煎熬,开发过程的最后一天,我终于破费了7.9元巨款采购了阿里云的首月月度会员。但匹配专属API的过程也是一波三折,下一篇再表……
---
*初稿作者:小一同学*
*转载请注明出处*
---
## 附录:核心参数速查
```python
# run_final.py 配置区
WEBCAM_INDEX = 0# 摄像头索引
RECOGNITION_THRESHOLD = 1.5# 识别距离阈值
STABLE_COUNT = 2# 连续确认帧数
LOST_COUNT = 5# 丢失切换帧数
```
**调试口诀:**
- 识别不灵敏 → 调大阈值(1.5 → 1.8)
- 容易误识别 → 调小阈值(1.5 → 1.2)
- 显示闪烁 → 增加稳定帧数(2 → 3)
- 切换太慢 → 减少稳定帧数(2 → 1)