ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

1515张带标签人脸数据:YOLO目标检测训练全流程实战

1515张带标签人脸数据:YOLO目标检测训练全流程实战 简介这是一份面向目标检测初学者与算法工程师的人脸检测数据集专为YOLO系列算法训练与验证设计可帮助读者快速搭建人脸检测模型省去自行采集与标注的繁琐流程。压缩包共2000个文件以1214个xml与786个txt为主分别对应VOC与YOLO两种标注格式整体约59.27MB并附带data.yaml配置文件可直接对接yolov5、yolov8、yolov9、yolov7、yolov10及yolo11等主流版本。其中YOLO格式采用类别索引与归一化中心点、宽高比例值便于直接读取训练VOC格式则保留原始xml结构方便转换与复核。数据集已划分完毕涵盖1515张带标签图像开箱即可投入训练与测试。目前已有506人学习下载适合需要快速验证模型、开展课程实验或进行人脸检测项目实践的用户参考使用。1. 1515 张带标签人脸数据为什么它比一万张无标注图更值得先跑通如果你手里正躺着一个face.zip解压后是 1515 张人脸图像加对应标签想用 YOLO 把它跑起来那这篇就是写给你的。人脸检测这个方向公开数据集动辄几十万张但真正能让你在半天内把「数据 → 训练 → 推理 → 可视化」整条链路走通的往往是这种规模适中、标注干净的小数据集。1515 张不算多可它带标签意味着你能立刻验证自己的 YOLO 环境、标注格式转换、损失收敛是否正常而不是卡在「先标三千张图」这一步。我见过太多人一上来就下载几十 G 的通用数据集结果环境没配好、标签格式对不上、显存爆掉三天过去连一张预测框都没画出来。小数据集的真正价值是当「探针」用它确认你的 YOLO 训练管线是通的再换大数据集才有意义。这篇会按「先看懂数据长什么样 → 转成 YOLO 能吃的格式 → 配环境跑训练 → 排查翻车点 → 进阶调优」的顺序讲每一步都给可抄的命令和参数。适合刚接触 YOLO 目标检测、手里有标注数据但不知道怎么喂进去的从业者也适合想快速验证一个新场景可行性的老手。2. 拆开 face.zip先搞清楚 1515 张图到底该怎么读拿到一个带标签的数据集压缩包最忌讳的就是直接unzip然后往训练脚本里一扔。人脸检测的数据集有几个共性坑图像尺寸不统一、标签可能是 VOC XML 也可能是 YOLO txt、文件名和标签文件不一定一一对应。先把这些摸清楚后面能省掉大量报错时间。2.1 目录结构与标签格式的三种常见形态face.zip这类数据集解压后大概率是下面三种结构之一。你得先ls看一眼再决定怎么处理。第一种图像和标签分目录face/ ├── images/ │ ├── 0001.jpg │ └── ... └── labels/ ├── 0001.txt └── ...第二种图像和同名标签混在一起face/ ├── 0001.jpg ├── 0001.txt └── ...第三种标签是单个汇总文件比如annotations.csv或face_annotations.txt每行记录一张图的框。前两种是 YOLO 训练最常见的第三种需要先拆分。判断标签格式直接看一个 txt 的内容head -n 5 labels/0001.txt如果每行是class x_center y_center width height且后四个数都在 0~1 之间那就是标准 YOLO 格式可以直接用。如果每行是xmin ymin xmax ymax这种绝对像素坐标那是 VOC 风格需要转换。人脸检测通常只有一个类别face所以 class 基本都是 0。提示先统计一下图像数量和标签数量是否一致。ls images | wc -l和ls labels | wc -l对不上说明有图没标或有标没图训练时会报missing label或直接跳过必须提前清理。2.2 用一段脚本体检数据集尺寸、类别、框分布在写训练配置之前我习惯先跑一段体检脚本把图像尺寸分布、标签框的宽高比、类别数都打出来。这一步能提前发现「所有框都挤在左上角」「某张图有几百个框」这类脏数据。import os import cv2 import numpy as np from collections import Counter img_dir face/images lbl_dir face/labels sizes [] box_ratios [] class_counter Counter() bad_files [] for name in os.listdir(img_dir): if not name.lower().endswith((.jpg, .png, .jpeg)): continue img_path os.path.join(img_dir, name) img cv2.imread(img_path) if img is None: bad_files.append(name) continue h, w img.shape[:2] sizes.append((w, h)) lbl_path os.path.join(lbl_dir, os.path.splitext(name)[0] .txt) if not os.path.exists(lbl_path): bad_files.append(name (no label)) continue with open(lbl_path) as f: for line in f: parts line.strip().split() if len(parts) ! 5: continue cls, xc, yc, bw, bh parts class_counter[cls] 1 if float(bh) 0: box_ratios.append(float(bw) / float(bh)) print(图像总数:, len(sizes)) print(尺寸分布(前5):, Counter(sizes).most_common(5)) print(类别计数:, class_counter) print(宽高比 中位数:, np.median(box_ratios) if box_ratios else 无) print(异常文件:, bad_files[:10])这段脚本做了四件事读图确认没有损坏文件、统计图像尺寸、统计每个类别的框数量、算框的宽高比中位数。人脸框的宽高比通常在 0.7~1.3 之间如果中位数偏离很远说明标注可能有问题。bad_files会列出读不出来的图和缺标签的图这些必须在训练前处理掉。参数上img_dir和lbl_dir按你实际解压后的路径改。如果标签是混在一起的把lbl_dir改成和img_dir一样即可。跑完这一步你对这 1515 张图就有了底尺寸是否统一、类别是否只有一类、框是否合理。2.3 划分训练集与验证集别用随机划分糊弄1515 张图常见做法是 8:2 或 9:1 划分。但人脸检测有个坑如果同一个人出现在多张图里随机划分会让同一个人的脸同时进训练集和验证集验证指标虚高。如果数据集里有人物 ID 信息按 ID 划分没有的话至少用固定随机种子保证可复现。import os import random import shutil random.seed(42) img_dir face/images lbl_dir face/labels out_root face_yolo val_ratio 0.15 names [n for n in os.listdir(img_dir) if n.lower().endswith((.jpg, .png, .jpeg))] random.shuffle(names) val_count int(len(names) * val_ratio) val_names set(names[:val_count]) for split in [train, val]: os.makedirs(os.path.join(out_root, images, split), exist_okTrue) os.makedirs(os.path.join(out_root, labels, split), exist_okTrue) for n in names: split val if n in val_names else train stem os.path.splitext(n)[0] shutil.copy(os.path.join(img_dir, n), os.path.join(out_root, images, split, n)) lbl os.path.join(lbl_dir, stem .txt) if os.path.exists(lbl): shutil.copy(lbl, os.path.join(out_root, labels, split, stem .txt)) print(train:, len(names) - val_count, val:, val_count)random.seed(42)是关键保证每次划分结果一致方便对比不同训练参数的效果。val_ratio0.15对 1515 张来说验证集约 227 张够用。输出目录face_yolo就是后面 YOLO 训练要指向的根目录结构是images/train、images/val、labels/train、labels/val这是 YOLO 官方约定的布局。3. 把标签喂给 YOLO格式转换与 data.yaml 配置数据划分完下一步是让 YOLO 认识你的数据。YOLO 训练只认两样东西符合规范的目录结构和一份描述数据集路径与类别的data.yaml。如果标签不是 YOLO 格式这一步还要做转换。3.1 VOC 转 YOLO坐标归一化的四个边界坑如果体检时发现标签是xmin ymin xmax ymax绝对坐标就得转成归一化的中心点加宽高。转换公式不复杂但边界处理容易翻车。import os import cv2 def voc_to_yolo(xmin, ymin, xmax, ymax, w, h): # 裁剪到图像范围内防止标注越界 xmin max(0, min(xmin, w - 1)) xmax max(0, min(xmax, w - 1)) ymin max(0, min(ymin, h - 1)) ymax max(0, min(ymax, h - 1)) xc (xmin xmax) / 2.0 / w yc (ymin ymax) / 2.0 / h bw (xmax - xmin) / w bh (ymax - ymin) / h # 过滤掉宽或高为 0 的无效框 if bw 0 or bh 0: return None return xc, yc, bw, bh img_dir face/images lbl_dir face/labels out_lbl_dir face_yolo/labels_all os.makedirs(out_lbl_dir, exist_okTrue) for name in os.listdir(img_dir): if not name.lower().endswith((.jpg, .png, .jpeg)): continue stem os.path.splitext(name)[0] img cv2.imread(os.path.join(img_dir, name)) if img is None: continue h, w img.shape[:2] src_lbl os.path.join(lbl_dir, stem .txt) if not os.path.exists(src_lbl): continue lines_out [] with open(src_lbl) as f: for line in f: parts line.strip().split() if len(parts) 5: continue # 假设格式为: xmin ymin xmax ymax (无类别列) xmin, ymin, xmax, ymax map(float, parts[:4]) res voc_to_yolo(xmin, ymin, xmax, ymax, w, h) if res is None: continue xc, yc, bw, bh res lines_out.append(f0 {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}) with open(os.path.join(out_lbl_dir, stem .txt), w) as f: f.write(\n.join(lines_out))四个边界坑分别是坐标越界标注超出图像边界必须裁剪、宽高为零退化框必须过滤、浮点精度保留 6 位小数足够、类别列缺失人脸检测统一补0。voc_to_yolo里先做max/min裁剪再算归一化最后判断bw/bh是否为正。转换完记得抽查几张用可视化脚本画框确认位置没偏。3.2 data.yaml 的五个字段与路径写法YOLO 训练靠data.yaml找数据。字段不多但路径写错是最常见的翻车点。path: /home/user/face_yolo train: images/train val: images/val nc: 1 names: [face]path是数据集根目录train和val是相对path的子路径。nc是类别数人脸检测就是 1。names是类别名列表顺序必须和标签里的 class 索引对应标签里写0这里第一个就是face。注意path用绝对路径最稳。用相对路径时YOLO 是相对于它自己的运行目录解析的换个终端就找不到数据。另外train和val指向的是包含图像的目录标签目录 YOLO 会自动把路径里的images替换成labels去找所以目录结构必须是images/train配labels/train。3.3 用 labelimg 或 vscode 插件补标与复核1515 张里如果有漏标或错标训练时模型会学到噪声。复核工具上labelimg是经典选择支持 YOLO 格式直接读写VS Code 里也有 YOLO 标注插件适合边看代码边改标。复核重点看三类人脸被截断一半的、侧脸漏标的、框明显偏大的。复核时统一用 YOLO 格式保存避免来回转换。如果发现某张图框数量异常多比如超过 20 个先确认是不是密集人群场景不是的话大概率是误标直接修掉。这一步花一两个小时比训练完发现指标上不去再回头查要划算得多。4. 从零跑通 YOLO 训练环境、命令与参数数据准备好了接下来是让训练真正跑起来。这一章给的是能直接复制的环境配置和训练命令以及每个参数为什么这么设。4.1 环境配置conda 建环境与依赖安装我一般用 conda 隔离环境避免和系统里的包打架。YOLO 现在主流用 ultralytics 这个库安装很直接。conda create -n yolo_face python3.10 -y conda activate yolo_face # 安装 PyTorch按你的 CUDA 版本选下面以 CUDA 11.8 为例 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 安装 ultralytics pip install ultralytics # 验证 yolo checkspython3.10是兼容性比较好的版本。PyTorch 的安装命令要按你机器的 CUDA 版本改没有 GPU 就用 CPU 版。yolo checks会打印环境信息确认 PyTorch 能识别到 GPU、ultralytics 版本正常。如果这一步报错先解决环境问题再往下走别硬着头皮训练。4.2 训练命令与关键参数逐个说清环境通了训练命令其实就一行但参数值得掰开讲。yolo detect train \ data/home/user/face_yolo/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectface_runs \ nameexp1modelyolov8n.pt是最小的 YOLOv8 模型1515 张图用 nano 版足够训练快、显存占用低。epochs100对这个小数据集通常够收敛。imgsz640是输入尺寸人脸如果普遍偏小可以提到 960但显存和速度会受影响。batch16按显存调8G 显存跑 640 尺寸一般能到 16。lr00.01是初始学习率默认值小数据集不建议调太大。patience20是早停20 轮验证指标不升就停省时间。训练开始后终端会打印每轮的 box_loss、cls_loss 和 mAP。重点看mAP50人脸检测正常收敛的话几十轮后能到 0.9 以上。如果 loss 一直不降先回去查标签格式和路径。4.3 训练过程看什么loss 曲线与 mAP 的判读训练日志里几个指标要会看。box_loss是边界框回归损失cls_loss是分类损失人脸只有一类cls_loss 会降得很快。mAP50是 IoU 阈值 0.5 下的平均精度是人脸检测最直观的指标。如果box_loss震荡不降常见原因是学习率太大或 batch 太小。如果mAP50卡在某个值上不去先看验证集是不是有大量漏标。训练完在face_runs/exp1下会有results.png把 loss 和 mAP 曲线看一眼比盯终端数字直观。权重文件是weights/best.pt后面推理用它。5. 训练翻车排查人脸检测里最常见的五个坑小数据集训练人脸检测报错和指标异常基本集中在下面几类。每条按现象、原因、解决写遇到问题对号入座。5.1 现象训练报 “No labels found”原因YOLO 按images目录名去推导labels目录如果你的标签目录不叫labels或者data.yaml里train路径指向的目录下没有对应的labels同级目录就会找不到标签。解决确认目录结构是face_yolo/images/train和face_yolo/labels/train成对出现。如果标签在别处要么移动过去要么在data.yaml里用绝对路径分别指定。跑一遍ls face_yolo/labels/train | head确认 txt 文件在。5.2 现象mAP 一直是 0 或极低原因标签坐标没归一化或者 class 索引和names对不上。VOC 格式的绝对坐标直接喂进去YOLO 会当成归一化坐标解析框全跑到图像外。解决打开一个标签 txt确认后四个数都在 0~1 之间。如果大于 1说明没归一化回去跑转换脚本。再确认data.yaml里nc: 1和names: [face]标签里 class 是0。5.3 现象显存溢出 CUDA out of memory原因batch或imgsz设太大。1515 张图本身不大但 640 以上尺寸加 batch 32 在 8G 显存上容易爆。解决先把batch降到 8 或 4或者把imgsz降到 416。也可以开ampTrue默认开用混合精度省显存。如果还爆换yolov8n而不是更大的模型。5.4 现象验证集指标高但实际推理漏检多原因训练集和验证集划分时同一个人跨集或者验证集和训练集图像高度相似指标虚高。也可能是过拟合模型记住了训练集。解决重新按人物 ID 划分没有 ID 就增大验证集比例到 0.2。加数据增强YOLO 默认开了 mosaic、翻转等可以再调degrees、translate增强泛化。训练轮数别太多配合patience早停。5.5 现象推理时框位置偏移或框住整张脸以外原因推理时的imgsz和训练时不一致或者图像预处理letterbox参数不同。YOLO 推理默认会做 letterbox 缩放如果训练和推理尺寸差异大框会偏。解决推理时imgsz保持和训练一致比如都 640。用yolo detect predict时显式指定imgsz640。如果还偏检查原图是否有 EXIF 旋转信息读图时用cv2.imread默认不处理旋转可能导致坐标错位。6. 进阶用 1515 张图把模型调到能上线的几个技巧小数据集想把指标做扎实靠的不是堆轮数而是把数据增强、模型选择和验证方法用对。下面几个技巧是我在类似规模数据集上反复验证过的。6.1 数据增强参数的针对性调整YOLO 默认增强对通用目标检测够用但人脸有特殊性过度旋转和裁剪会破坏人脸结构。我一般会把旋转幅度调小同时加强亮度和小尺度缩放模拟真实场景的光照和距离变化。yolo detect train \ data/home/user/face_yolo/data.yaml \ modelyolov8n.pt \ epochs150 \ imgsz640 \ batch16 \ degrees10.0 \ translate0.1 \ scale0.5 \ hsv_h0.015 \ hsv_v0.4 \ mosaic1.0 \ patience30degrees10.0把旋转限制在正负 10 度避免人脸倒置。scale0.5允许 0.5 倍缩放增强对小脸的鲁棒性。hsv_v0.4加大亮度扰动应对不同光照。mosaic1.0保留 mosaic 增强它对小数据集提升明显。这些值不是死的跑完对比mAP50再微调。6.2 用验证集做阈值扫描找最佳置信度训练完的模型默认置信度阈值是 0.25但人脸检测场景下这个值不一定最优。用验证集扫一遍阈值找 F1 最高的点。from ultralytics import YOLO import numpy as np model YOLO(face_runs/exp1/weights/best.pt) results model.val(data/home/user/face_yolo/data.yaml, conf0.001, iou0.6) # results 里包含不同 conf 下的 precision/recall 曲线数据 # 实际使用时可直接读 results.box.f1_curve 找峰值对应的 conf f1 results.box.f1_curve conf_axis np.linspace(0, 1, len(f1)) best_conf conf_axis[np.argmax(f1)] print(最佳置信度阈值:, round(float(best_conf), 3))conf0.001是为了让验证时保留足够多的预测框才能画出完整的 F1 曲线。iou0.6是 NMS 的 IoU 阈值。f1_curve是不同置信度下的 F1 值数组取最大值对应的 conf 就是最佳阈值。实际部署时把这个值传给推理接口能明显减少漏检和误检的平衡问题。6.3 导出与推理onnx 导出和单图测试训练完的.pt权重适合 Python 环境如果要部署到其他框架导出 ONNX 更通用。yolo export modelface_runs/exp1/weights/best.pt formatonnx imgsz640导出后在同目录得到best.onnx。单图测试直接用命令行yolo detect predict \ modelface_runs/exp1/weights/best.pt \ source/home/user/test.jpg \ imgsz640 \ conf0.4 \ saveTrueconf0.4是上面扫出来的阈值附近的值按你实际扫描结果改。saveTrue会把画框后的图存到runs/detect/predict下。看一眼结果图框是否贴合人脸、有没有漏检这是最直接的验收。6.4 小数据集的验证习惯留一份「从未参与训练」的图1515 张图我习惯额外留 50 张完全不参与训练和验证只在最后验收时用。这样得到的指标才是对真实泛化能力的估计。做法是在划分前先抽 50 张出来单独放一个目录训练和调参全程不碰它。等模型定稿用这 50 张跑一遍yolo detect predict人工看漏检和误检。这个习惯帮我避免过好几次「验证集漂亮、上线就崩」的翻车。说到底1515 张带标签的人脸数据价值不在于它有多大而在于它能让你把整条链路快速跑通、把每个参数的实际影响摸清楚。我自己的习惯是每换一个新场景先用小数据集把管线验证一遍再决定要不要投入标注更多数据。希望帮到你。本文还有配套的精品资源点击获取
返回列表