简介这份资源提供基于YOLOv8的人脸检测模型面向计算机视觉开发者、边缘计算部署工程师及深度学习学习者解决从训练权重到多平台推理落地的完整需求。压缩包共7个文件约31.79MB包含pt与onnx两种通用模型格式分别适配PyTorch训练微调与跨框架部署同时提供RKNPU优化版本含rknn、bin、xml及tar打包文件可直接用于RK3588、RK3576等瑞芯微NPU平台输入尺寸为640×640。资源覆盖从桌面端到嵌入式端的多种部署路径开发者可依据硬件条件选择合适格式省去模型转换与算子适配的重复工作。目前已有671人学习下载适合需要快速验证人脸检测效果或搭建边缘端实时检测方案的中高级开发者参考使用。1. 从一张合影里把人脸框出来yolov8 人脸检测到底能解决什么上周帮朋友处理一批活动合影三百多张照片需要把每张里的人脸位置标出来做后续裁剪。手动框不现实。用传统 Haar 级联侧脸和遮挡基本歇菜。这时候 yolov8 人脸检测就是那个能让你少加两天班的方案。它本质上是把 YOLOv8 这个通用目标检测框架通过人脸数据集微调或直接加载人脸专用权重让模型只对人脸这一个类别做检测。相比通用 COCO 预训练权重人脸专用权重在密集小脸、侧脸、口罩遮挡场景下的召回率明显更高。适合谁做安防监控截图分析、活动照片批量处理、嵌入式设备端人脸计数、以及拿人脸检测当毕业设计题目的同学。你不需要从零训一个检测器但需要知道权重从哪来、输入尺寸怎么设、置信度阈值怎么调。2. 环境搭建与权重选择别在第一步就把自己埋了2.1 为什么优先用 ultralytics 而不是自己搭 DarknetYOLOv8 和 YOLOv5 最大的工程差异在于v8 官方主推ultralytics这个 pip 包把训练、推理、导出、验证全部封装成统一 API。你不需要像当年玩 Darknet 那样编译 Makefile、改 cfg 文件、手动算 anchor。常见做法是直接pip install ultralytics然后三行代码跑推理。但这里有个选型理由要说清楚如果你只是做人脸检测推理用ultralytics加载人脸专用权重是最短路径如果你要改网络结构比如加协调注意力机制那还是得把源码 clone 下来改ultralytics/nn/modules里的模块定义。新手建议先走 pip 路线把流程跑通再动结构。2.2 环境配置的具体步骤先确认你的 CUDA 版本这决定了 PyTorch 装哪个。GTX 1660 Ti 这类卡跑 yolov8n 或 yolov8s 的人脸检测完全够用6GB 显存下 batch size 设 8 到 16 问题不大。RK3588 或 Orin 这类边缘设备则是另一套流程后面单独说。# 创建独立环境别在 base 里乱装 conda create -n face_yolo python3.10 -y conda activate face_yolo # 根据你的 CUDA 版本装 PyTorch这里以 CUDA 11.8 为例 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 装 ultralytics pip install ultralytics # 验证安装 yolo checksyolo checks会打印出你的 PyTorch 版本、CUDA 是否可用、以及 ultralytics 版本。如果 CUDA 显示不可用别急着往下走先把驱动和 PyTorch 版本对齐。这一步翻车的人最多血泪经验是显卡驱动版本、CUDA 运行时版本、PyTorch 编译版本三者必须匹配缺一个就是torch.cuda.is_available()返回 False。2.3 人脸检测权重从哪来这是检索里问得最多的问题之一。YOLOv8 官方 COCO 预训练权重里没有人脸这个类别它只有 person 类。所以你有两条路第一条是找社区已经用人脸数据集比如 WIDER FACE微调好的权重直接加载做推理第二条是下载官方 yolov8n.pt 作为起点自己用人脸数据集训练。如果你只是要快速出结果走第一条如果你要针对特定场景比如工地安全帽下的人脸、夜间红外优化走第二条。from ultralytics import YOLO # 加载人脸专用权重假设你已经拿到了 face_yolov8n.pt model YOLO(face_yolov8n.pt) # 对单张图片推理 results model.predict( sourcegroup_photo.jpg, conf0.4, # 置信度阈值人脸检测建议 0.3~0.5 iou0.5, # NMS 的 IoU 阈值 imgsz640, # 输入尺寸小脸多的话可以提到 1280 device0 # 用 GPU 0 ) # 保存带框的结果图 results[0].save(output.jpg)conf参数是人脸检测里最需要调的。设太高比如 0.7侧脸和戴口罩的脸会被漏掉设太低比如 0.1背景里的纹理会被误检成人脸。我一般先用 0.4 跑一批看效果再根据漏检和误检情况微调。imgsz也关键合影里人脸像素少640 可能不够提到 1280 能明显改善小脸召回但推理速度会下降。3. 训练自己的人脸数据集从标注到损失曲线3.1 数据标注格式与目录结构YOLOv8 用的是 YOLO 格式标注每张图对应一个 txt 文件每行是类别 x_center y_center width height坐标都归一化到 0 到 1。人脸检测只有一个类别所以类别 id 全是 0。常见做法是用 labelImg 或 Roboflow 标注后导出 YOLO 格式。目录结构必须长这样不然训练脚本找不到数据dataset/ ├── images/ │ ├── train/ │ │ ├── 001.jpg │ │ └── ... │ └── val/ │ └── ... └── labels/ ├── train/ │ ├── 001.txt │ └── ... └── val/ └── ...3.2 data.yaml 的写法与参数含义# face_data.yaml path: /home/user/dataset # 数据集根目录 train: images/train # 训练集图片相对路径 val: images/val # 验证集图片相对路径 nc: 1 # 类别数人脸检测就是 1 names: [face] # 类别名称path写绝对路径最稳写相对路径时容易因为工作目录不同而报File not found。nc和names必须对应如果你标了多个类别但 nc 写 1训练时标签会被截断。3.3 启动训练与关键参数yolo detect train \ dataface_data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectface_runs \ nameexp1epochs是训练轮数人脸检测数据集如果只有几千张100 轮通常够收敛。patience20表示验证集指标 20 轮不提升就早停省时间。lr0是初始学习率0.01 是默认值如果你用预训练权重微调可以降到 0.001 避免把预训练特征冲掉。batch根据显存调GTX 1660 Ti 跑 yolov8n 用 16 没问题跑 yolov8m 可能得降到 8。3.4 看损失函数曲线判断训练状态训练完在face_runs/exp1/下会有results.csv和results.png。results.png里包含 box_loss、cls_loss、dfl_loss 三条训练损失和对应的验证损失。正常情况是训练损失和验证损失同步下降最后趋于平稳。如果训练损失还在降但验证损失开始往上走那就是过拟合了需要加数据增强或减模型复杂度。如果两条都居高不下检查标注是不是有问题——我见过有人把坐标没归一化就丢进去训loss 从头到尾不降。import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(face_runs/exp1/results.csv) df.columns df.columns.str.strip() # 列名可能有空格 plt.figure(figsize(10, 5)) plt.plot(df[epoch], df[train/box_loss], labeltrain box_loss) plt.plot(df[epoch], df[val/box_loss], labelval box_loss) plt.xlabel(epoch) plt.ylabel(loss) plt.legend() plt.savefig(loss_curve.png)这段脚本把 box_loss 单独画出来比看整张 results.png 更清楚。df.columns.str.strip()这行别省ultralytics 导出的 csv 列名有时带前导空格不处理会 KeyError。4. 推理部署与边缘设备适配从服务器到 RK35884.1 批量图片推理与结果解析训练完拿到best.pt后实际用的时候往往不是单张推理而是批量处理。下面这段代码遍历文件夹把每张图的人脸框坐标存成 json方便后续裁剪或入库。import os import json from ultralytics import YOLO model YOLO(face_runs/exp1/weights/best.pt) img_dir photos out {} for fname in os.listdir(img_dir): if not fname.lower().endswith((.jpg, .png, .jpeg)): continue path os.path.join(img_dir, fname) results model.predict(sourcepath, conf0.4, imgsz1280, verboseFalse) boxes results[0].boxes faces [] for i in range(len(boxes)): xyxy boxes.xyxy[i].tolist() # 左上右下坐标 conf float(boxes.conf[i]) faces.append({bbox: xyxy, conf: conf}) out[fname] faces with open(face_results.json, w) as f: json.dump(out, f, indent2)verboseFalse关掉每张图的日志输出批量处理时不然刷屏。boxes.xyxy是绝对像素坐标如果你要归一化坐标用boxes.xywhn。conf存下来方便后续按置信度过滤。4.2 导出 ONNX 与 RK3588 部署路径RK3588 这类 NPU 设备不能直接跑 PyTorch 模型需要先导出 ONNX再用 RKNN Toolkit 转成 rknn 格式。Orin 则是走 TensorRT。导出 ONNX 的命令很简单yolo export modelface_runs/exp1/weights/best.pt formatonnx imgsz640 opset12opset12是兼容性比较好的选择RKNN Toolkit 对 opset 版本有要求太高可能不支持。导出后在 RK3588 上用 rknn_model_zoo 里的 yolov8 示例做后处理注意人脸检测只有一个类别后处理里的类别数要改成 1否则解析会错位。这一步的坑在于ONNX 导出的输出层名字和 RKNN 示例里写死的不一样需要自己打印模型输出确认。4.3 实时视频流人脸检测与标注检索里有人问实时摄制视频的人脸检测与标注这其实就是把model.predict的 source 换成摄像头索引或 RTSP 流。import cv2 from ultralytics import YOLO model YOLO(face_runs/exp1/weights/best.pt) cap cv2.VideoCapture(0) # 0 是默认摄像头 while True: ret, frame cap.read() if not ret: break results model.predict(sourceframe, conf0.4, imgsz640, verboseFalse) annotated results[0].plot() # 自带画框和置信度 cv2.imshow(face detect, annotated) if cv2.waitKey(1) 0xFF ord(q): break cap.release() cv2.destroyAllWindows()results[0].plot()返回的是画好框的 numpy 数组直接 imshow 就行。如果帧率不够把 imgsz 降到 416 或者换 yolov8n。GTX 1660 Ti 上 640 尺寸大概能跑到 40 到 60 FPS够实时用。5. 避坑与常见问题排查5.1 训练 loss 不下降标注文件有问题现象训练跑了 50 轮box_loss 一直在 2.0 以上震荡mAP 接近 0。原因标注坐标没有归一化或者类别 id 写成了 1 但 data.yaml 里 nc1 只允许 id 0。解决用脚本检查每行标注的五个值是否都在 0 到 1 之间类别 id 是否为 0。5.2 推理时 CUDA out of memory现象训练能跑推理大图时爆显存。原因imgsz设太大或者 batch 推理时一次塞了太多图。解决推理时把imgsz降到 640或者用streamTrue逐张处理。GTX 1660 Ti 6GB 显存跑 1280 尺寸的 yolov8m 会爆换 yolov8n 或降尺寸。5.3 导出 ONNX 后 RK3588 上结果全错现象PC 上推理正常转 rknn 后框全乱或没有框。原因RKNN 后处理里的 anchor 或输出层解析和实际导出模型不匹配或者输入归一化方式不同。解决先用onnxruntime在 PC 上验证 ONNX 输出是否正常再对比 RKNN 示例里的后处理代码重点检查输出 tensor 的 shape 和顺序。5.4 小脸漏检严重现象合影里远处的人脸框不出来。原因输入分辨率不够人脸在特征图上只剩几个像素。解决推理时imgsz提到 1280 或 1536或者用 SAHI 切片推理把大图切成小块分别检测再合并。5.5 误检把背景纹理当人脸现象窗户格子、树叶缝隙被框成人脸。原因置信度阈值设太低或者训练集里负样本太少。解决把conf从 0.25 提到 0.5训练时加入不含人脸的背景图作为负样本。6. 进阶技巧用 SAHI 切片推理把合影小脸召回拉满最后一章说一个我实际项目里反复用的技巧。前面提到合影小脸漏检提 imgsz 是最直接的办法但显存和速度代价大。更聪明的做法是 SAHISlicing Aided Hyper Inference把原图切成有重叠的小块每块单独推理再把结果合并回原图坐标。这样每块里人脸相对变大小脸召回率能提升一截而单次推理尺寸不用拉满。from sahi import AutoDetectionModel from sahi.predict import get_sliced_prediction # 加载 yolov8 人脸模型 detection_model AutoDetectionModel.from_pretrained( model_typeultralytics, model_pathface_runs/exp1/weights/best.pt, confidence_threshold0.4, devicecuda:0 ) # 切片推理 result get_sliced_prediction( group_photo.jpg, detection_model, slice_height640, slice_width640, overlap_height_ratio0.2, # 切片间重叠比例 overlap_width_ratio0.2 ) # 导出带框结果 result.export_visuals(export_dirsahi_output/)slice_height和slice_width决定每块大小一般设成和模型训练尺寸一致640。overlap_height_ratio是重叠比例0.2 表示相邻切片有 20% 重叠防止人脸正好卡在切片边界被切掉。这个比例太低会漏边界脸太高会重复检测增加 NMS 负担。我一般用 0.2 到 0.3。验证 SAHI 效果的方法很简单拿同一张合影分别用普通推理和 SAHI 推理数一下检出的人脸数量。如果 SAHI 多检出 10% 以上说明你的场景确实需要切片。但注意 SAHI 的推理时间是普通推理的 3 到 5 倍实时视频流慎用适合离线批量处理。还有一个参数是postprocess_type默认是 NMS如果切片重叠区域出现重复框可以换成NMM或调低postprocess_match_threshold。这个阈值控制合并时多大 IoU 算同一个目标人脸检测一般设 0.5 到 0.6。从那以后我每次处理合影类项目都强制先跑一遍普通推理看基线再跑 SAHI 对比召回最后根据时间预算决定用哪个。这个习惯帮我避免了好几次以为模型不行、其实是推理策略没跟上的误判。希望帮到你。本文还有配套的精品资源点击获取