首页 / 资讯中心 / 文章详情

深度学习人脸识别签到系统:从模型训练到部署避坑指南

深度学习人脸识别签到系统:从模型训练到部署避坑指南 ★ FEATURED ARTICLE
简介这份毕业设计项目聚焦于基于深度学习的人脸识别签到系统的完整实现面向计算机专业毕业生、Python开发学习者以及需要快速搭建人脸识别考勤场景的开发者可直接作为课程设计、毕业设计或小型企业考勤系统的参考蓝本。项目共27个文件压缩包大小约102.26MB核心文件包括8个Python脚本、7个HTML页面、SQLite数据库以及若干数据文件兼顾后端算法、前端模板和数据持久化。除核心源码外还提供依赖清单、数据库迁移配置、样式表、中文字体、说明文档及初始管理员账户覆盖从环境搭建、数据库初始化到系统运行的完整闭环显著降低部署门槛。系统依托深度学习模型提取人脸特征实现用户注册、登录验证、人脸识别签到、用户信息编辑等典型模块代码层次分明便于理解人脸识别链路并快速改造扩展。该资源已有4467人学习目录结构清晰对希望快速掌握人脸识别系统工程项目化实现、用于毕业设计或实际考勤应用的读者非常实用。1. 人脸识别签到系统到底在解决什么问题不只是把打卡机换成摄像头公司考勤的痛点从来不是“机器不识别”而是“识别不认人”。IC卡可以代刷指纹可以套膜密码可以共享——传统签到手段验证的是“你持有的东西”而不是“你这个人”。基于深度学习的人脸识别签到系统把身份验证从“拿什么证明”变成“你就是你”这才是它值得做的根本原因。这套系统要拆开看是四个环节人脸检测从画面里把人脸框出来关键点对齐把脸摆正卷积神经网络把脸映射成一段高维特征向量最后用余弦相似度决定“这个人是不是注册库里那位”。对在校学生做课程签到、对中小公司做考勤、对实验室做门禁管理这套方案都能在普通摄像头加一台服务器上跑起来成本远低于采购人脸识别门禁机。下面我会把方案选型、数据流、训练参数、部署步骤和最容易翻车的五个坑一次说透目标是让看完的人能照着搭出一套可用的最小系统。2. 方案选型为什么深度学习方案把传统几何特征甩开一个时代2.1 传统人脸识别的瓶颈在哪里早期人脸识别走的是几何特征路线检测出眼睛、鼻子、嘴角的位置计算它们之间的距离比例、角度关系用这些手工设计的几何量拼成特征向量。这个方法在正脸、光照均匀、表情平静的证件照场景下能跑但一遇到侧脸、低头、逆光就崩。原因很直接人脸的几何结构差异其实不大两个陌生人五官比例可能非常接近而同一个人的不同表情可能让嘴型和眼距测量值波动很大。类内距离大于类间距离是这个路线无法回避的根本缺陷。另一条传统路线是整体特征比如PCA降维后的“特征脸”把整张人脸图像铺平做主成分分析取前若干主成分当作身份描述。问题在于PCA是线性变换而人脸在光照、姿态、遮挡下的变化是非线性的。你要用线性子空间去描述非线性流形数据稍微偏一点就匹配错误。传统方法不是不能用而是它对输入条件太挑剔部署到实际签到场景里光线、角度、口罩遮挡这些不可控因素会直接把识别率打到不可接受的水平。2.2 深度学习方案的核心流程检测、对齐、特征提取、比对深度学习的思路完全不同不再手工设计特征而是让卷积神经网络从大量人脸图像里自己学出一组高维向量让同一个人在不同条件下的特征尽可能接近不同人的特征尽可能远离。这组向量通常叫Embedding维度常见的是128维、256维或512维。人脸识别图像进入神经网络到输出高维度向量的过程本质是把一张112×112的RGB图像逐层卷积池化最后压缩成一个特征向量这个向量在特征空间里的位置就代表这张脸的身份。整个系统要落地链路分四步。第一步检测用MTCNN或RetinaFace把画面里的人脸位置框出来第二步对齐根据双眼和鼻尖的关键点做仿射变换把脸摆到标准位置消除旋转和尺度差异第三步特征提取把对齐后的人脸图像归一化后送进骨干网络得到特征向量第四步比对把现场特征向量和注册库里预先算好的特征向量做余弦相似度计算超过阈值就判定为同一人。这四步里检测和特征提取是深度模型对齐是几何计算比对是纯数学运算各环节可以独立替换和调试。2.3 骨干网络与损失函数的取舍骨干网络的选择决定特征提取能力的上限。常见选项有ResNet系列、MobileFaceNet、GhostNet这些。用ResNet50做特征提取精度高但参数量大CPU上做一次前向推理要几百毫秒不适合并发签到MobileFaceNet是专门为人脸识别设计的轻量网络在保持精度的同时把模型压到几兆字节适合部署在普通服务器甚至边缘设备上。我的建议是如果跑在GPU服务器上用ResNet50或IR-SE50如果跑在普通CPU上用MobileFaceNet识别精度损失不大但单次推理能控制在50毫秒以内。损失函数是这个任务里比骨干网络更关键的部分。早期用Softmax交叉熵直接做分类学出来的特征在判别上够用但类间没有显式的Margin特征分布比较松散。后来的改进思路是让同类特征在超球面上聚拢不同类之间拉开角度。典型代表有CosFace和ArcFace前者在余弦距离上加Margin后者在角度上加Margin。实际效果上ArcFace更常用它在类内紧凑性和类间分离度上比Softmax有质的提升。训练时把网络最后一层改成ArcFace分类头推理时丢掉分类头只取前面的Embedding向量这条路线是人脸识别签到系统的主流做法值得优先采用。3. 整体架构与数据流设计注册特征库与签到记录怎么落库3.1 系统流程注册与签到两个主链路人脸识别签到系统本质上是一个“先注册、后比对”的身份验证系统。注册链路负责把员工的正面照送进特征提取模型得到特征向量并存入数据库同时建立员工基本信息和特征的映射关系。签到链路则是现场抓拍人脸实时提取特征与库里的特征逐条比对相似度最高的那条超过阈值就算签到成功然后把签到时间、人员ID写入签到记录表。这里有一个非常重要的设计决策比对逻辑必须放在服务器端不能把整个特征库下发到前端。原因有三条第一特征库是全校或全公司的人脸数据属于敏感个人信息下发到终端会增加泄露面第二终端设备的算力参差不齐逐条比对几万条特征会让部分设备卡死第三如果以后要升级比对算法或调整阈值只需要改服务端不需要重新部署终端。正确的做法是终端只负责抓拍和上传图片服务器端做完整的人脸检测、特征提取、相似度比对和签到记录写入。提示如果你做的是课程签到这类几百人规模的小系统服务器端比对的方案完全够用。几百条特征的余弦相似度计算在毫秒级瓶颈只会在图片上传和特征提取上不用担心并发。3.2 数据库表设计与签到API实现数据库至少需要三张表员工表存人员基本信息人脸特征表存特征向量签到记录表存每次签到的日志。特征向量是浮点数组不同数据库的存储方式不一样MySQL 8.0以上可以用JSON类型也可以用BLOB存二进制打包数据如果追求查询性能可以把特征降维后存成多个浮点列但这样表结构会很冗余。我一般用MySQL的JSON类型简单直接一条记录存一个JSON数组。签到接口的完整流程可以这样设计前端把摄像头抓到的图片Base64编码后POST到/api/checkin服务端先做人脸检测没检测到人脸就直接返回“未检测到人脸”检测到人脸就提取特征向量再和注册库里所有特征做余弦相似度计算取最大值和平均值做判定超过阈值且当天没有重复签到记录就写入签到记录表。# 签到接口核心逻辑FastAPI实现 from fastapi import FastAPI, HTTPException from pydantic import BaseModel import numpy as np import base64 import cv2 import json app FastAPI() class CheckInRequest(BaseModel): user_id: str None # 可空主要用于日志记录 image_base64: str # 摄像头抓拍的图片 app.post(/api/checkin) async def checkin(req: CheckInRequest): # 1. 解码图片 img_bytes base64.b64decode(req.image_base64) img_array np.frombuffer(img_bytes, dtypenp.uint8) img cv2.imdecode(img_array, cv2.IMREAD_COLOR) # 2. 人脸检测返回人脸框和关键点 faces face_detector.detect(img) if len(faces) 0: raise HTTPException(status_code400, detail未检测到人脸) # 3. 取面积最大的人脸避免误检背景 largest_face max(faces, keylambda f: f.bbox.width * f.bbox.height) aligned_face align_face(img, largest_face.keypoints) # 4. 提取特征向量 feature feature_extractor.extract(aligned_face) # shape: (512,) # 5. 与注册库所有特征比对 candidates load_all_features_from_db() best_score -1.0 best_person_id None for person_id, registered_feature in candidates: score cosine_similarity(feature, registered_feature) if score best_score: best_score score best_person_id person_id # 6. 阈值判定THRESHOLD 为全局配置通常取 0.5~0.68 if best_score THRESHOLD: raise HTTPException(status_code401, detail签到失败未匹配到注册用户) # 7. 防重复签到同一人当天只能签到一次 if has_checked_in_today(best_person_id): raise HTTPException(status_code409, detail今日已签到) write_checkin_record(best_person_id, time_now()) return {person_id: best_person_id, score: best_score, time: time_now()}这段代码里最值得注意的参数是THRESHOLD也就是判定阈值。阈值设得太低陌生人容易被误判成已注册用户设得太高本人稍微换个发型或角度就拒识。实际部署时不能拍脑袋定要拿一批真实签到场景的照片做测试画ROC曲线选一个错误率可接受的点。另外第7步的幂等检查很重要否则同一人连续刷脸会写入多条签到记录虽然可以在数据库里用人员ID日期做唯一索引兜底但应用层直接拦截更友好能返回明确的“今日已签到”提示而不是数据库报错。3.3 特征比对与阈值判定逻辑特征比对用的相似度指标是余弦相似度公式是cos(A, B) A·B / (|A||B|)取值范围是-1到1。人脸识别场景里同一个人的不同照片通常能到0.5到0.8不同人的相似度大多在0.1到0.4之间。为什么不直接用欧氏距离因为特征向量经过L2归一化后余弦相似度和欧氏距离是单调等价的但余弦相似度更直观而且ArcFace训练得到的特征天然分布在高维超球面上用余弦相似度度量符合模型的几何语义。比对性能也是要提前考虑的。几百个注册用户时逐条计算余弦相似度完全没问题但如果注册人数到几万每次签到都遍历全库就不合适了。常见做法是用近似最近邻检索比如用FAISS建索引。把注册特征全部加载到内存里用IndexFlatIP或者IndexIVFFlat做检索一次性返回Top-K个候选再在候选里做精确判定。这样即使几十万人脸特征单次检索也能控制在几十毫秒。但需要注意特征库更新后要定期重建索引否则新注册的人脸可能查不到。4. 用PyTorch训练人脸识别模型L2正则、特征维度与关键参数4.1 训练数据准备与预处理管线人脸识别模型的训练数据来源通常有两个选择一是直接用公开数据集如CASIA-WebFace、VGGFace2、MS1MV2二是自己采集业务场景的数据做微调。对签到系统来说公开数据集预训练一个通用模型再用本公司的员工照片微调效果会比只用公开数据集好不少。原因是签到场景有固定的摄像头角度和光照环境微调能让模型适应这种分布。预处理管线是训练前必须统一的。读入图片后先做人脸检测和对齐对齐后的图像缩放到112×112这是ArcFace系列模型的常用输入尺寸。每个像素值要归一化到[-1, 1]或者[0, 1]不同模型的预处理要求不一样但核心原则是训练和推理必须走同一条预处理管线否则模型在训练时看到的分布和推理时不一致识别率会断崖式下降。RGB通道顺序也要统一OpenCV读图是BGRPyTorch预训练模型通常按RGB输入这个错位是很多人训练完才发现识别率不对的经典坑。数据增强方面人脸识别场景下常用的是随机水平翻转、随机亮度对比度调整、随机裁剪一小段边缘、轻微色彩抖动。但要注意人脸识别不能像分类任务那样做太强的随机旋转人脸本身有固定朝向旋转角度超过15度反而会破坏对齐语义。另外遮挡增强要谨慎随机遮挡可能把眼睛或鼻尖挡住导致模型学到错误特征。# 训练数据预处理管线PyTorch Dataset import torch import torch.nn.functional as F from torch.utils.data import Dataset import cv2 import numpy as np import random class FaceDataset(Dataset): def __init__(self, image_paths, labels, is_trainTrue): self.image_paths image_paths self.labels labels self.is_train is_train def __len__(self): return len(self.image_paths) def __getitem__(self, idx): img cv2.imread(self.image_paths[idx]) # BGR img cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 转为 RGB与 PyTorch 输入对齐 img cv2.resize(img, (112, 112)) if self.is_train: # 随机水平翻转人脸左右对称这是安全的增强 if random.random() 0.5: img img[:, ::-1, :] # 亮度抖动模拟不同光照环境 brightness random.uniform(0.8, 1.2) img np.clip(img.astype(np.float32) * brightness, 0, 255).astype(np.uint8) # 归一化到 [-1, 1] img img.astype(np.float32) / 127.5 - 1.0 # HWC - CHW img np.transpose(img, (2, 0, 1)) return torch.tensor(img), self.labels[idx]这段预处理里翻转和亮度抖动是安全增强不会破坏身份信息。比较关键的是最后一步归一化人脸图像的像素值范围是0到255直接送进网络会让初始梯度不稳定归一化到[-1, 1]后分布更接近零均值训练收敛速度和稳定性都有明显改善。112x112这个尺寸对应绝大部分人脸识别模型的预设输入MobileFaceNet和ArcFace系列模型在这个分辨率下计算量和精度有比较好的平衡不推荐随意改成224或其他尺寸否则预训练权重可能无法直接复用。4.2 ArcFace损失函数与L2正则的PyTorch实现ArcFace的核心思路是在Softmax损失的基础上给正确类别的角度加上一个固定的Margin让模型在训练时必须把同类特征压得更紧才能降低损失。具体数学形式是把特征向量和权重向量归一化后计算角度再在目标类的角度上加上一个m然后乘上缩放系数s。PyTorch实现ArcFace损失通常要自己写一个自定义层因为标准Softmax不带角度Margin的机制。实现里需要维护一个权重矩阵W形状是(特征维度, 类别数)前向计算时把特征和权重都做L2归一化计算cos(θ)再用arccos恢复角度加上Margin后重新计算cos(θm)。要注意数值稳定性arccos的输入要限制在[-1, 1]范围内否则会出现NaN梯度。另一个必须处理的细节是L2正则。人脸识别模型参数量大训练数据如果不做正则化很容易过拟合表现为训练集损失很低但验证集识别率上不去。L2正则的实现方式很简单PyTorch的优化器里直接设置weight_decay参数就行。常见取值是5e-4到1e-3之间太小起不到约束作用太大又会压制模型的表达能力。我通常先设5e-4观察验证集损失曲线如果训练集和验证集损失差距持续拉大就调高到1e-3。# ArcFace 损失函数的 PyTorch 实现 import math import torch import torch.nn as nn import torch.nn.functional as F class ArcFaceLoss(nn.Module): def __init__(self, feature_dim, num_classes, s32.0, m0.5): super().__init__() self.s s # 缩放系数控制特征在超球面上的半径 self.m m # 角度Margin弧度制约 28.6 度 self.cos_m math.cos(m) self.sin_m math.sin(m) self.th math.cos(math.pi - m) self.mm math.sin(math.pi - m) * m # 权重矩阵每一列代表一个类别的类中心向量 self.weight nn.Parameter(torch.FloatTensor(num_classes, feature_dim)) nn.init.xavier_normal_(self.weight) def forward(self, features, labels): # L2 归一化特征和权重 features F.normalize(features, p2, dim1) weight F.normalize(self.weight, p2, dim1) # 计算 cos(theta) cos_theta F.linear(features, weight) cos_theta torch.clamp(cos_theta, -1.0 1e-7, 1.0 - 1e-7) # 计算 sin(theta) sin_theta torch.sqrt(1.0 - cos_theta * cos_theta) # 计算 cos(theta m) cos_theta_m cos_theta * self.cos_m - sin_theta * self.sin_m # 对超出范围的 cos(theta) 做处理防止数值不稳定 cond cos_theta self.th cos_theta_m torch.where(cond, cos_theta_m, cos_theta - self.mm) # 构造 one-hot 标签 one_hot F.one_hot(labels.long(), num_classesself.weight.shape[0]) # 目标类别用 cos(thetam)其他类别保持原值 output one_hot * cos_theta_m (1.0 - one_hot) * cos_theta output * self.s # 乘以缩放系数 return F.cross_entropy(output, labels)这个实现里s32和m0.5是ArcFace论文的默认推荐值实际训练时可以直接用。s控制特征半径太大让Softmax输出过于尖锐训练初期梯度不稳定太小则分类边界不够清晰。m直接决定类间Margin的大小0.5是一个经过大量实验验证的安全取值想进一步压低误识率可以试0.6但训练难度会随之增大需要更长的迭代周期。优化器用SGD加上动量为0.9是比较常见的组合Adam虽然收敛快但在ArcFace损失上最终精度往往略逊一筹。4.3 训练循环里的关键参数与监控指标训练人脸识别模型时除了损失函数本身还有几个参数直接决定最终效果。Batch size是一次前向计算喂给模型的样本数太大占用显存太小梯度噪声大。对112×112的输入ResNet50在12GB显存上可以跑Batch size 256MobileFaceNet可以跑到512。学习率初始值一般是0.1乘以Batch size对256的缩放比例比如Batch size 512就用0.2。训练总步数一般看数据量几十万张图片的训练集上训练25到30个Epoch即可学习率在第10和第20个Epoch时分别下降10倍。训练过程中要盯着两个指标看。第一个是ArcFace损失本身它会缓慢下降如果出现NaN说明学习率过大或数据里有异常值第二个是验证集上的识别率具体做法是拿一批验证人脸对分别计算同一人的相似度和不同人的相似度观察分布是否清晰分离。如果两个分布重叠严重说明模型还没训练好或损失函数设置不对。这里要注意验证集必须和训练集完全没有身份重叠否则验证结果会虚高部署后被陌生人刷脸成功的情况大概率是验证集构造出了问题。# 训练循环关键片段优化器、L2正则和余弦退火 import torch.optim as optim from torch.optim.lr_scheduler import CosineAnnealingLR model resnet50_face() # 骨架网络输出 512 维特征 arcface ArcFaceLoss(feature_dim512, num_classesnum_identities, s32.0, m0.5) # SGD momentum 是 ArcFace 训练的标配 optimizer optim.SGD( model.parameters(), lr0.1, momentum0.9, weight_decay5e-4 # L2 正则控制权重范数防止过拟合 ) # 余弦退火前 5 个 epoch 线性预热之后余弦下降到接近 0 scheduler CosineAnnealingLR(optimizer, T_max30, eta_min1e-6) for epoch in range(30): for batch_images, batch_labels in train_loader: features model(batch_images) # 前向得到特征向量 loss arcface(features, batch_labels) optimizer.zero_grad() loss.backward() optimizer.step() scheduler.step() print(fEpoch {epoch:02d}, Loss: {loss.item():.4f}, Lr: {scheduler.get_last_lr()[0]:.6f})代码里的weight_decay5e-4就是L2正则的落地方式。正则化之所以对人脸识别重要是因为模型要学习一个泛化能力强的特征空间而不仅仅是记住训练集里的人脸。如果权重范数过大特征空间会被个别方向主导泛化性变差。权重衰减本质上是给每个权重加一个小的衰减项迫使权重保持在较小范围内模型只能学习更本质的特征模式。特征维度选512是一个经验共识太低放不下足够多的身份信息太高会增加比对计算量但对精度提升不明显。5. 避坑手册签到系统最容易翻车的 5 个常见问题5.1 问题一陌生人识别成已注册用户现象随便拿一部手机拍一张照片去比对系统判定为某位已注册员工签到成功。做演示时翻车率极高。原因阈值设置过低是最常见的原因。另外如果注册库里的特征向量没做L2归一化余弦相似度计算的结果会偏大也会放大误识风险。解决先把阈值从0.45往上调到0.5、0.55、0.6每次调完拿一批“本人照片”和“陌生人照片”分别测试记录通过率和拒识率。实际项目中0.58以上通常是一个比较稳的点。同时检查特征提取是否做了L2归一化注册和签到两侧必须一致否则相似度分布完全没有可比性。5.2 问题二同一个员工被识别成两个人现象员工今天签到成功明天换了个摄像头位置或者摘了眼镜系统就提示未注册。原因特征提取模型对输入图像的预处理非常敏感。如果训练时用112×112部署时却把图片resize成96×96再送进去特征表达会漂移。更隐蔽的问题是关键点对齐不稳定每次检测出来的眼睛位置有几像素抖动仿射变换后的人脸图像就不同了。解决核对训练和推理的预处理管线确认输入尺寸、归一化范围、通道顺序完全一致。对齐模块的关键点检测结果要可视化验证确保两只眼睛和鼻尖在注册和签到两条链路上都能稳定检出。建议在代码里写死统一的preprocess()函数注册和签到共用一个函数避免两套代码各自实现导致差异。5.3 问题三签到记录重复写入现象员工在摄像头前站了一会儿系统在几秒内写入了七八条签到记录考勤统计一下子出现多条重复数据。原因前端摄像头连续抓帧每一帧都触发一次签到API后端没有做幂等控制。解决后端在写入前查一次“员工ID日期”的唯一记录已存在就直接返回“今日已签到”。更稳的方案是在数据库层加联合唯一索引(person_id, checkin_date)设为unique数据库兜底拒绝重复插入。另外前端也应该加防抖逻辑比如同一人签到成功后30秒内不再发起签到请求这能减少无效的服务器压力。5.4 问题四口罩、眼镜、刘海变化后识别率骤降现象员工戴着口罩来上班系统直接识别失败。部分用户换了新发型也被拒识。原因训练数据里没有遮挡样本模型没有见过只露半张脸的人脸发型变化让脸部外围像素变化剧烈特征向量被大幅扰动。这是纯算法层面的局限不是配置错误。解决训练阶段加入模拟遮挡的数据增强比如随机用矩形块遮住下巴区域。更符合真实场景的做法是采集一批员工的戴口罩照片加入训练集做微调。如果项目周期不允许重新训练可以在部署时采用“多特征投票”策略注册时录入三张不同角度、不同状态的照片签到时分别比对三次两次以上超过阈值才算通过。这个策略能显著降低单张图片偶然性波动带来的误拒。5.5 问题五显存不足导致训练中断现象训练到第几个Batch时PyTorch直接报CUDA out of memory进程被杀掉。加了pin_memory和num_workers之后反而更严重了。原因Batch size设置超出显卡显存容量或者数据加载线程太多导致显存和内存的交换压力增大。人脸识别训练通常要跑递归的骨干网络中间激活值占显存很大。解决先把Batch size降到显卡能装下的最大值比如12GB显存跑MobileFaceNet可以从256开始ResNet50从128开始。如果一定要用大Batch size可以用梯度累积每跑4个Batch累积一次梯度再更新参数效果等价于大Batch size但显存占用不变。另外训练时关闭torch.backends.cudnn.benchmark以外的多余缓存torch.cuda.empty_cache()在Epoch间调用一次也可以缓解碎片化。注意以上五个问题在真实项目里是按概率叠加出现的不是一次只出一个。调阈值、改预处理、加幂等、补数据、降Batch size这五件事最好整理成一份checklist每次部署新环境按顺序排查一遍。6. 从训练到落地摄像头接入、模型导出与阈值工程6.1 本地摄像头接人脸识别服务的思路训练完模型之后不能只是放在PyTorch里跑签到系统需要一条完整的流媒体链路。常见做法是前端用OpenCV或摄像头SDK抓帧每隔一定时间或检测到人脸时把图像压缩成JPEG然后Base64编码POST到服务端的签到接口。抓帧频率不要太高每秒一帧足够连续抓帧不仅浪费带宽还会让服务器排队处理大量重复图片。检测逻辑可以放在前端也可以放在服务器端放前端的好处是没人脸时不上传省流量坏处是终端需要额外部署一个检测模型。我建议把检测也放在服务器端终端只负责抓图和上传统一管理和升级更方便。6.2 模型导出与部署训练好的模型要脱离PyTorch环境才能稳定部署。最省事的做法是导出为ONNX格式然后转成OpenVINO或TensorRT加速这样完全摆脱Python的训练环境依赖还能在CPU上获得不错的推理速度。导出时要把预处理算子也封装进模型图里这样部署层不需要再写归一化逻辑能避免预处理不一致的问题。ONNX导出遇到的最常见问题是动态维度人脸检测模型的输出尺寸会随人脸数量变化导出时要显式设置动态轴否则推理阶段一遇到多张人脸就报错。特征提取模型没有这个问题输入固定112×112输出固定512维向量导出最顺利。6.3 阈值工程用真实数据标定拒绝线阈值调整是最容易被忽视但也最影响体验的一环。不要拿论文里的标准值直接部署要用现场采集的100张“本人签到图”和100张“陌生人图”做一次离线测试画出相似度分布直方图。本人分布和陌生人分布之间的距离越宽说明模型在该场景下效果越好如果两个分布贴着就得回头查预处理和对齐问题而不是硬调阈值找安慰。阈值定好后建议在代码里做成配置文件而不是硬编码因为不同教室、不同摄像头高度和光线环境下最佳阈值可能差0.05以上。我自己的习惯是每个部署点位单独测一轮把阈值写到该点位的配置里而不是全公司共用一个值。人脸识别签到系统做到能跑通容易做到稳定难。前期最值得投入的时间不是在模型结构上反复尝试而是把数据预处理、阈值标定、重复签到拦截这些边边角角的细节磨平。我做过好几套类似的系统最后发现让项目成功的往往不是某个惊艳的网络结构而是那些看起来不起眼却每天都在起作用的小决策比如对齐函数的统一、阈值配置的独立、接口的幂等控制。希望这篇笔记里的方案和坑能让你少走一段弯路祝你一次跑通。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站