基于 reComputer 的视频人脸自动相册构建
基于 Hailo-8 / SCRFD / ArcFace 的端侧人脸相册自动归档项目。

你可以在 GitHub 上查看本项目源代码:https://github.com/doublelf/person_face_sign
一、项目概述
Person Face Sign 是一个在边缘设备(reComputer + Hailo-8 NPU)上离线构建「人脸相册」的项目。它的核心目标是把一段监控/活动视频中所有出现的人脸自动归入各自的「身份相册」,方便事后翻查、统计或归档。
解决的典型问题
- 来访登记 / 访客管理:把若干小时的前台摄像头录像交给脚本,自动生成「今天来了 23 个人,每人 N 张图」的结果。
- 课堂 / 会议签到辅助:把课程录像按人头归档,作为电子点名依据。
- 活动照片自动整理:把多机位、多角度的现场录像合并聚类,自动产出按人分组的相册。
- 视频素材的二次检索:以人找人,而非以时间戳找人。
核心 Pipeline
视频 (data/*.mp4)
│
▼
[VideoSampler] —— 每 1 秒采 1 帧 (1280×720)
│
▼
[YOLOv8n] —— 行人检测 (640×640)
│
▼
[IoUTracker] —— 行人跟踪 + 节流采脸 (可关)
│
▼
[SCRFD-10G] —— 人脸检测 + 5 点 landmarks
│
▼
[FaceAlign 5pt] —— 仿射对齐到 112×112
│
▼
[ArcFace MobileFaceNet] —— 512-d L2-norm embedding
│
▼
[AlbumCluster] —— pHash 优先 / Faiss HNSW 兜底 → 分配 person_id
│
▼
[AlbumStorage] —— 写文件 + 双去重 + 更新 manifest.json
│
▼
[Web Browser :8080] —— 浏览/检索产物二、快速开始
下面是一份端到端的复现流程,按顺序执行即可在 reComputer 上构建出一个可浏览的人脸相册。
2.1 克隆仓库
git clone https://github.com/doublelf/person_face_sign.git
cd person_face_sign2.2 创建虚拟环境
推荐使用 venv(Python 内置,无需额外安装)。
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip2.3 安装 Python 依赖
pip install -r requirements.txt2.4 安装系统级前置依赖
build_album.py 通过 subprocess 调用 ffmpeg / ffprobe 跳帧采帧,需要在系统层安装:
# Debian / Ubuntu (含 reComputer)
sudo apt update
sudo apt install -y ffmpeg
# 验证
ffmpeg -version | head -n 1
ffprobe -version | head -n 12.5 准备 HEF 模型文件
person_face_sign/
└── models/
├── yolov8n.hef # ~4.3 MB
├── scrfd_10g.hef # ~10 MB
└── arcface_mobilefacenet.hef # ~5 MB| 用途 | 模型 | 默认路径(build_album.py 硬编码) | 实际来源 |
|---|---|---|---|
| 行人检测 | YOLOv8n | <项目根>/models/yolov8n.hef | 官方 Docker 镜像内置,容器内路径 /app/model/yolov8n.hef |
| 人脸检测 | SCRFD-10G | <项目根>/models/scrfd_10g.hef | HailoRT deb 包自带(可拷贝到 models/) |
| 人脸嵌入 | ArcFace MobileFaceNet | <项目根>/models/arcface_mobilefacenet.hef | HailoRT deb 包自带(可拷贝到 models/) |
2.5.1 获取 SCRFD + ArcFace(最简单)
SCRFD-10G 与 ArcFace MobileFaceNet 的 HEF 是 Hailo 官方预编译模型,随 hailort deb 包安装到 /usr/local/hailo/resources/models/hailo8/,直接拷贝到本项目 models/ 即可:
sudo apt install hailort
ls /usr/local/hailo/resources/models/hailo8/
# 应当能看到:
# arcface_mobilefacenet.hef
# scrfd_10g.hef
# 以及若干其他官方示例模型
# 拷贝到项目本地 models/ 目录
cp /usr/local/hailo/resources/models/hailo8/scrfd_10g.hef models/
cp /usr/local/hailo/resources/models/hailo8/arcface_mobilefacenet.hef models/
ls -lh models/2.5.2 获取 YOLOv8n
见 https://sensecraft.seeed.cc/ai-lab/en/models/yolov8/hailo-8,YOLOv8n HEF 已打包 ghcr.io/seeed-projects/recomputer-r20-cv/yolov8:latest 内,容器中路径为 /app/model/yolov8n.hef
mkdir -p models
# 1. 拉取官方镜像
docker pull ghcr.io/seeed-projects/recomputer-r20-cv/yolov8:latest
# 2. 用 create 起一个不运行的容器实例(只为了拿到文件)
docker create --name yolov8-temp ghcr.io/seeed-projects/recomputer-r20-cv/yolov8:latest
# 3. 从容器里把 yolov8n.hef 拷到项目 models/ 下
docker cp yolov8-temp:/app/model/yolov8n.hef models/yolov8n.hef
# 4. 清理临时容器
docker rm yolov8-temp
# 5. 验证
ls -lh models/yolov8n.hef2.6 构建人脸相册(核心步骤)
仓库自带一段演示视频 data/tex.mp4(约 11 MB)。运行下面这条命令即可生成相册:
python apps/build_album.py \
--video data/tex.mp4 \
--out data/album \
--no-tracker \
--scrfd-score 0.6 \
--cluster-thresh 0.85 \
--skip-dedup参数含义:
| 参数 | 取值 | 说明 |
|---|---|---|
--video | data/tex.mp4 | 输入视频,可多次指定或用逗号分隔 |
--out | data/album | 相册输出目录 |
--no-tracker | flag | 关闭 IoU tracker,每帧每脸都采(短样本视频推荐) |
--scrfd-score | 0.6 | SCRFD 人脸检测置信度阈值(默认 0.60) |
--cluster-thresh | 0.85 | 宽松聚合:cosine distance 阈值;详见 4.2 节 |
--skip-dedup | flag | 跳过写入时的 pHash / embedding 双去重(仍会保留 pHash 优先的聚类) |
构建完成后,data/album/ 下会出现:
data/album/
├── manifest.json
├── thumbnails/
│ ├── person_0001.jpg
│ ├── person_0002.jpg
│ └── ...
├── person_0001/
│ ├── representative.jpg
│ ├── info.json
│ ├── embeddings.npz
│ └── img_0001_ts_2.00s_score_0.78.jpg
│ └── img_0002_ts_5.00s_score_0.74.jpg
│ └── ...
├── person_0002/
└── ...2.7 启动 Web 相册浏览服务
构建完成后,另开一个终端,启动极简 Web 服务:
python apps/web_browser.py --port 8080浏览器访问 http://<reComputer-IP>:8080/:
- 顶部统计条显示总人数、总图片数、源视频数;
- 主体网格按「每张图 = 1 个人」展示缩略图(缩略图来自
representative.jpg,按图片数降序); - 点击某个人进入详情页,列出该 person 的所有
img_*.jpg; - 点击任意图片弹出全屏查看器。
三、产物解读
3.1 数据目录结构
data/album/
├── manifest.json # 全局统计 + 人员列表(Web UI 的数据源)
├── thumbnails/
│ └── person_<id>.jpg # 缩略图(= representative.jpg 的副本)
└── person_<NNNN>/ # 每个身份一个目录,NNNN 为 4 位 zero-padded id
├── info.json # 单个人元数据:count / first_ts / last_ts / best_score / source_videos
├── embeddings.npz # 该 person 排名前 N 的 embedding(默认 N=5,按 score 排序)
├── representative.jpg # 得分最高的「封面照」,同步写到 thumbnails/
└── img_<NNNN>_ts_<ts>s_score_<score>.jpg # 每张保留的人脸 (112×112 对齐后)文件命名规范示例:
person_0001/img_0001_ts_2.00s_score_0.78.jpg:第 1 张,2.00 秒,SCRFD score = 0.78person_0001/img_0014_ts_18.50s_score_0.82.jpg:第 14 张,18.50 秒
3.2 manifest.json 关键字段
{
"version": "1.0",
"created_at": "2026-09-26T10:23:11",
"updated_at": "2026-09-26T10:24:48",
"total_persons": 6,
"total_images": 142,
"source_videos": ["tex"],
"config": {
"interval_s": 1.0,
"cosine_distance_threshold": 0.85,
"min_face_size": [40, 40],
"min_face_score": 0.6,
"best_n_embeddings": 5,
"phash_max_dist": 4
},
"persons": [
{
"id": 1,
"count": 28,
"first_ts": 2.0,
"last_ts": 82.0,
"best_score": 0.85,
"source_videos": ["tex"],
"thumbnail": "thumbnails/person_0001.jpg"
},
...
]
}字段含义:
| 字段 | 含义 |
|---|---|
total_persons | 已聚类的人员总数(持续 build 时单调递增) |
total_images | 所有人脸图片总数(去重后) |
config | 本次 build 的参数快照(写回相册,便于追溯) |
persons[].count | 该 person 的人脸图数量 |
persons[].first_ts / last_ts | 首次 / 末次出现的时间戳(秒) |
persons[].best_score | 最高 SCRFD 检测分数 |
3.3 Web 界面交互
Web 端基于纯 http.server + 静态 HTML/CSS/JS,无数据库依赖,所有数据都从 manifest.json 与文件系统实时读取。
主要交互路径:
- 首页(
/):拉取/manifest.json,按count降序列出所有 person 的缩略图; - 进入个人详情:点击缩略图 → 后端 glob
person_<id>/img_*.jpg→ 列出所有图; - 大图预览:点击单图 →
<dialog>全屏弹窗; - 刷新:点击顶部
↻重新拉manifest.json。