# FaceRegServer **Repository Path**: liuziloong/FaceRegServer ## Basic Information - **Project Name**: FaceRegServer - **Description**: 人脸比对服务(不含识别) 以SeetaFace6为底座,使用mysql、sqlite存储元数据信息,同时使用zvec作为向量数据库,全部使用TraeWork,0手写代码开发的一套人脸识别系统。 - **Primary Language**: Go - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 6 - **Forks**: 0 - **Created**: 2026-07-04 - **Last Updated**: 2026-07-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Facereg — 人脸比对服务 基于 **Golang + SeetaFace6 + Gin** 的高性能人脸比对服务,支持 CPU/GPU 加速,MySQL/SQLite 双数据库,本地/S3 图片存储,嵌入式 [zvec](https://github.com/alibaba/zvec)(阿里巴巴开源进程内向量数据库)HNSW+COSINE 检索引擎。 > 本项目仍处于 早期演进阶段:代码尚未完全稳定, 在后续版本中仍有可能调整。请在生产环境使用前关注 CHANGELOG 并做好兼容性验证。 ## 快速开始(4 步启动) ```bash # 1. 编译 zvec 向量引擎(阿里巴巴嵌入式向量数据库) make build-zvec # 或手动: git clone https://github.com/alibaba/zvec.git 3rd/zvec # cd 3rd/zvec && mkdir build && cd build # cmake .. -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release # cmake --build . --config Release -j$(nproc) # 2. 下载 SeetaFace6 模型文件(详见下方模型下载章节) # 最小集 (15MB): face_detector.csta + face_landmarker_pts5.csta + face_recognizer_light.csta # 放入 models/ 目录 # 3. 启动服务(SQLite 模式,免装数据库,自动建表) go run ./cmd/server # 4. 打开浏览器 http://localhost:8080 ``` > 服务启动时 **自动建表**,无需手动执行任何 SQL。MySQL/SQLite 均支持。 --- ## 模型下载 SeetaFace6 需要本地模型文件(`.csta` 格式),存放在 `models/` 目录下。 ### 最小模型集(512维 MobileFaceNet,推荐) | 文件名 | 大小 | 用途 | 来源 | |--------|------|------|------| | `face_detector.csta` | ~5MB | 人脸检测 | [Part I](https://pan.baidu.com/s/1LlXe2-YsUxQMe-MLzhQ2Aw) 提取码 `ngne` | | `face_landmarker_pts5.csta` | ~5MB | 5点关键点 | Part I | | `face_recognizer_light.csta` | ~5MB | 特征提取(512维, 9ms) | [Part II](https://pan.baidu.com/s/1xjciq-lkzEBOZsTfVYAT9g) 提取码 `t6j0` | ### 完整模型集(按需下载) | 文件名 | 大小 | 用途 | 来源 | |--------|------|------|------| | `face_recognizer.csta` | ~50MB | 通用识别(1024维, 57ms) | Part I | | `quality_lbn.csta` | ~5MB | 质量评估 | Part I | 项目提供了模型检查脚本: - Linux: `bash scripts/download_models.sh` - Windows: `scripts\download_models.bat` --- ## 配置说明 ```yaml # ── 服务 ── server: port: 8080 # 监听端口 mode: "release" # ── 数据库(代码自动建表,无需手动导入 SQL)── database: type: "sqlite" # sqlite | mysql sqlite_path: "./data/facereg.db" host: "127.0.0.1" # MySQL 模式有效 port: 3306 user: "root" password: "123456" database: "facereg" max_open_conns: 100 max_idle_conns: 10 conn_max_lifetime: 3600 # ── 向量存储(阿里巴巴 zvec 嵌入式向量数据库,内置于服务进程中)── zvec: data_dir: "./data/zvec" # 向量索引持久化目录 dimension: 512 # 特征向量维度(需与 SeetaFace6 detect_mode 一致) index_type: "hnsw" # hnsw | ivfflat | diskann(推荐 HNSW) metric_type: "cosine" # cosine | l2 | ip(人脸推荐 cosine) # ── 人脸引擎 ── engine: device: "cpu" # cpu | gpu model_dir: "./models" # SeetaFace6 .csta 模型目录 feature_dim: 512 detect_mode: 0 # 0=MobileFaceNet(512维,9ms), 1=ResNet50(1024维,57ms) pool_size: 4 # 引擎池大小(CPU=核心数, GPU=1~2) detect_threshold: 0.8 compare_threshold: 0.62 # ── 图片存储 ── image_storage: type: "local" # local | s3 local_path: "./data/images" ``` --- ## API 接口 ### 人脸库 | 方法 | 路径 | 说明 | |------|------|------| | `POST` | `/api/v1/groups` | 创建人脸库 | | `GET` | `/api/v1/groups` | 人脸库列表(分页) | | `GET` | `/api/v1/groups/:id` | 人脸库详情 | | `PUT` | `/api/v1/groups/:id` | 更新人脸库 | | `DELETE` | `/api/v1/groups/:id` | 删除人脸库 | ### 人员 | 方法 | 路径 | 说明 | |------|------|------| | `POST` | `/api/v1/groups/:id/persons` | 注册人员 | | `GET` | `/api/v1/groups/:id/persons` | 人员列表(分页) | | `GET` | `/api/v1/groups/:id/persons/:pid` | 人员详情 | | `PUT` | `/api/v1/groups/:id/persons/:pid` | 更新人员 | | `DELETE` | `/api/v1/groups/:id/persons/:pid` | 删除人员 | ### 人脸图片 | 方法 | 路径 | 说明 | |------|------|------| | `POST` | `/api/v1/groups/:id/persons/:pid/images` | 上传注册人脸 | | `GET` | `/api/v1/groups/:id/persons/:pid/images` | 查看图片列表 | | `DELETE` | `/api/v1/groups/:id/persons/:pid/images/:iid` | 删除图片 | ### 人脸比对 | 方法 | 路径 | 说明 | |------|------|------| | `POST` | `/api/v1/compare/one2one` | 1:1 比对 | | `POST` | `/api/v1/compare/one2n` | 1:N 检索(不传 `group_id` 则全局搜索) | | `POST` | `/api/v1/compare/detect` | 人脸检测(调试) | | `POST` | `/api/v1/compare/feature` | 特征提取(调试) | --- ## cURL 示例 ```bash # 1:1 比对 curl -X POST http://localhost:8080/api/v1/compare/one2one \ -H "Content-Type: application/json" \ -d '{"image_data1":"","image_data2":""}' # → {"code":0,"data":{"score":0.87,"similar":true,"threshold":0.62}} # 1:N 检索 curl -X POST http://localhost:8080/api/v1/compare/one2n \ -H "Content-Type: application/json" \ -d '{"image_data":"","group_id":1,"top_k":5}' # → {"code":0,"data":{"results":[...],"top_k":5,"cost_ms":42}} ``` --- ## 数据库选择 | 场景 | 推荐 | 原因 | |------|------|------| | 开发/测试/单机 | **SQLite** | 零依赖,自动建表即用 | | 多实例生产 | **MySQL** | 真正并发读写,高可用 | | 10万级人脸库 | **MySQL** | 索引效率更高 | | 嵌入式/IoT | **SQLite** | 无需外部进程 | > SQLite 在 WAL 模式下支持无限并发读,但写操作串行。写入瓶颈约 50 QPS。MySQL 无此限制。 --- ## 并发调优 | pool_size | 场景 | 预估 1:1 QPS | |-----------|------|-------------| | 1 | 开发调试 | ~110 | | 4 (默认) | 4核 CPU | ~440 | | 8 | 8核 CPU | ~880 | | 1 (GPU) | Tesla T4 | ~500 | > 引擎池使用 `atomic.AddUint64` 无锁 round-robin,各引擎实例独立运行。 --- ## 图片存储 图片不存储在数据库中。`face_images.image_url` 字段存储路径: - 本地存储: `./data/images/2026/07/04/1709123456789.jpg` - S3 存储: `s3://mybucket/facereg/images/2026/07/04/1709123456789.jpg` 通过 `config.yaml` 中的 `image_storage.type` 切换。删除人员图片时会同步删除存储文件。 --- ## 架构简图 ``` HTTP 请求 → Gin Router → Handler → Service ├── MySQL/SQLite (AutoMigrate 自动建表) ├── zvec (alibaba/zvec 嵌入式向量DB, cgo→C API) ├── Filestore (本地/S3) └── Engine Pool (N×SeetaFace6, 无锁) ``` ## 目录结构 ``` faceregserver/ ├── cmd/server/main.go # 服务入口(配置加载 → 组件初始化 → HTTP 服务启动) ├── configs/config.yaml # 配置文件(SQLite/MySQL 切换、引擎参数、存储类型) ├── web/index.html # Web 管理界面 ├── scripts/ # 辅助脚本 │ ├── download_models.sh # Linux 模型下载脚本 │ ├── download_models.bat # Windows 模型下载脚本 │ ├── setup_zvec.sh # Linux zvec 编译脚本 │ └── setup_zvec.ps1 # Windows zvec 编译脚本 ├── internal/ │ ├── config/config.go # Viper 配置加载(Server/DB/ZVec/Engine/Log/ImageStorage) │ ├── model/ # GORM 数据模型(AutoMigrate 自动建表) │ │ ├── face_group.go # 人脸库分组模型 │ │ ├── face_person.go # 人员模型 │ │ └── face_image.go # 人脸图片模型(图片路径 + zvec vec_id) │ ├── store/ │ │ ├── mysql/ # 数据库访问层(MySQL + SQLite 双驱动 + AutoMigrate) │ │ │ ├── mysql.go # 连接初始化、自动建表、WAL/外键配置 │ │ │ ├── group.go # 分组 CRUD + 人员计数原子增减 │ │ │ ├── person.go # 人员 CRUD + 图片计数原子增减 │ │ │ └── image.go # 图片 CRUD + 按 vecID/分组检索 │ │ ├── zvec/ # alibaba/zvec 嵌入式向量数据库(进程内 HNSW+COSINE) │ │ │ ├── types.go # SearchResult + Client 接口定义 │ │ │ ├── zvec.go # 全局单例管理 + 工厂注册 │ │ │ ├── native.go # zvec C API 原生引擎(cgo,HNSW 索引 M=16 efConstruction=200) │ │ │ └── stub.go # 纯 Go 内存引擎(cgo 禁用时的回退方案,暴力搜索) │ │ └── filestore/ # 图片文件存储抽象层 │ │ ├── filestore.go # FileStore 接口(Save/Delete/Read) │ │ ├── init.go # 全局单例管理 │ │ ├── local.go # 本地磁盘存储(按日期分目录,纳秒时间戳命名) │ │ └── s3.go # S3 兼容对象存储(支持 AWS S3 / MinIO) │ ├── engine/ │ │ ├── init.go # 无锁引擎池(atomic round-robin,MinPoolSize=1, MaxPoolSize=64) │ │ ├── face_engine.go # 引擎类型别名统一导出 │ │ ├── types/types.go # 核心类型定义(FaceRect/DetectResult/CompareResult/ImageData/FaceEngine) │ │ ├── cpu/ # SeetaFace6 CPU 引擎(cgo→C 动态库) │ │ │ ├── engine.go # CPU 引擎实现(cgo绑定 + Detect/Extract/Compare) │ │ │ ├── engine_stub.go # CPU 模拟引擎(!cgo 开发环境) │ │ │ └── seeta_adapter.cpp # SeetaFace6 C 适配层 │ │ └── gpu/ # SeetaFace6 GPU 引擎(CUDA+cuBLAS,cgo+linux) │ │ ├── engine.go # GPU 引擎实现 │ │ ├── engine_stub.go # GPU 不可用时返回错误 │ │ └── seeta_gpu_adapter.cpp # SeetaFace6 GPU C 适配层 │ ├── service/ # 业务逻辑层 │ │ ├── types.go # 请求/响应类型定义 │ │ ├── group_svc.go # 分组管理(增删改查 + 空字段不覆盖) │ │ ├── person_svc.go # 人员管理(增删改查 + 分组计数同步) │ │ └── compare_svc.go # 比对服务(1:1/1:N/检测/特征提取/图片注册删除) │ ├── handler/ # HTTP 处理器层(Gin) │ │ ├── router.go # 路由注册 + 静态文件服务 │ │ ├── middleware.go # 中间件(Logger/Recovery/CORS) │ │ ├── group_handler.go # 分组 API 处理器 │ │ ├── person_handler.go # 人员 API 处理器 │ │ └── compare_handler.go # 比对 + 图片 API 处理器 │ └── pkg/ # 通用工具包 │ ├── errcode/errcode.go # 统一错误码(10000段通用 / 20000段人脸) │ └── response/response.go # 统一响应格式(Success/Error/Page) ├── Dockerfile # CPU 镜像构建(多阶段:zvec编译→Go编译→运行) ├── Dockerfile.gpu # GPU 镜像构建(CUDA 12.2 基础镜像) ├── docker-compose.yml # 一键部署(MySQL + faceregserver) ├── Makefile # 构建命令(build-zvec / build / clean) ├── go.mod / go.sum # Go 模块依赖 ├── DEPLOY.md # 部署指南 └── README.md # 本文档 ```