☰
widerface人脸检测数据集B大目标VOC+YOLO双格式实战指南
2026/9/26 15:27:01 网站建设 项目流程

简介:这份资源是WIDER FACE数据集中面向大目标人脸检测的子集,采用Pascal VOC与YOLO双格式标注,适合做人脸检测训练与算法验证的开发者、学生及研究人员使用。其特点是每张图片的人脸边界框像素面积均大于3500,聚焦近距离大脸场景,能有效降低误检率,但远距离小脸检测效果相对有限。压缩包为7z格式,共2000个文件,以1999个xml标注文件和1个说明txt为主,整体约862.16MB,xml与同名jpg图片一一对应,可直接用于主流检测框架的数据加载。数据集共8188张图片,标注类别仅face一类,总框数14649个,使用labelImg按矩形框规则完成标注,标注准确合理。目前已有468人学习下载,适合需要大脸检测数据、希望减少误检的读者参考使用,但资源不对训练模型或权重文件的精度作任何保证。

1. widerface 人脸检测数据集 VOC+YOLO 双格式:8188 张 B 大目标到底怎么用

拿到一个标注为「widerface 人脸检测数据集 B 大目标 VOC+YOLO 格式 8188 张 1 类别」的 7z 压缩包时,多数人的第一反应是解压、看目录、找 data.yaml,然后直接丢进 YOLO 训练脚本。但真正跑过 widerface 的人都知道,这个数据集最坑的地方不在训练本身,而在「B 大目标」这个子集的定义和 VOC/YOLO 双格式之间的坐标换算。8188 张图、单类别 face、VOC XML 与 YOLO TXT 并存,意味着你既可以走 darknet 老路线,也可以直接喂给 ultralytics 系。这篇文章不讲人脸检测算法史,只讲一件事:拿到这个包之后,从解压、校验、格式转换到训练参数设置,每一步该怎么做、参数怎么调、哪里会翻车。适合已经跑通过至少一次 YOLO 训练、想拿 widerface 做预训练或人脸检测基线的人。

2. 先搞清楚 B 大目标子集和双格式目录结构

2.1 widerface 的 Easy/Medium/Hard 与 B 大目标的区别

widerface 官方按检测难度分 Easy、Medium、Hard 三个子集,划分依据是尺度、遮挡、姿态等属性。而「B 大目标」这个说法通常来自社区二次整理:把标注框面积较大的样本单独抽出来,形成一个大目标子集,目的是让模型先在高信噪比数据上收敛,再迁移到小脸场景。8188 张这个量级,大约是 widerface 训练集 12880 张的一个子集,单类别 face,标注框普遍偏大,最小边通常不低于 30 像素。这个子集的价值在于:训练初期 loss 下降快、mAP 容易看到正反馈,适合做课程学习的第一个阶段,或者做一个人脸检测的 sanity check 基线。如果你的目标是直接刷 widerface Hard 的 SOTA,这个子集不够用;但如果你要验证自己的训练管线、anchor 配置、数据增强是否正常,它比全量 widerface 友好得多。

2.2 解压 7z 与目录校验:Linux 和 Windows 各一条命令

7z 在 Linux 下默认不一定装,先确认:

# Debian/Ubuntu 系 sudo apt-get install -y p7zip-full # 解压,-o 指定输出目录,注意 -o 和路径之间没有空格 7z x widerface_b_8188_voc_yolo.7z -o./widerface_b # 校验解压完整性,列出文件数 find ./widerface_b -type f | wc -l

Windows 下如果用 7-Zip 图形界面,遇到「密码正确但一直报错」,九成是压缩包用了 7z 增强版的某些特性,或者下载不完整。先比对文件哈希,再用命令行7z t做完整性测试:

7z t widerface_b_8188_voc_yolo.7z

如果t通过但x失败,检查磁盘剩余空间和目标路径是否有中文或空格。解压后典型目录是images/加labels/,VOC 格式则多一层Annotations/和JPEGImages/。先确认图片数和标注数一致,再往下走。

2.3 VOC XML 与 YOLO TXT 的字段对照

VOC 的 XML 里,人脸框是<bndbox>下的xmin/ymin/xmax/ymax,绝对像素坐标,原点左上。YOLO 的 TXT 是class cx cy w h,全部归一化到 0~1,cx/cy 是框中心。单类别 face 的 class id 就是 0。转换时最容易错的是归一化用的宽高:必须用当前图片自身的 width/height,不能用数据集统一尺寸。下面这张表把两种格式的关键字段对齐:

项目VOC XMLYOLO TXT
坐标类型绝对像素归一化 0~1
框表示xmin,ymin,xmax,ymaxcx,cy,w,h
类别<name>face</name>行首 0
一图多框多个<object>多行
宽高来源<size>节点需读图片实际尺寸

提示:如果 XML 里的<size>和图片实际尺寸不一致,以图片实际尺寸为准,否则归一化会整体偏移。

3. 从 VOC 转 YOLO:转换脚本与四个边界坑

3.1 转换脚本:读 XML、算归一化、写 TXT

import os import xml.etree.ElementTree as ET from PIL import Image VOC_DIR = "./widerface_b/Annotations" IMG_DIR = "./widerface_b/JPEGImages" OUT_DIR = "./widerface_b/labels" os.makedirs(OUT_DIR, exist_ok=True) for xml_name in os.listdir(VOC_DIR): if not xml_name.endswith(".xml"): continue tree = ET.parse(os.path.join(VOC_DIR, xml_name)) root = tree.getroot() # 用图片实际尺寸,不用 XML 里的 size img_path = os.path.join(IMG_DIR, xml_name.replace(".xml", ".jpg")) with Image.open(img_path) as im: iw, ih = im.size lines = [] for obj in root.findall("object"): name = obj.find("name").text.strip() if name != "face": continue bb = obj.find("bndbox") xmin = float(bb.find("xmin").text) ymin = float(bb.find("ymin").text) xmax = float(bb.find("xmax").text) ymax = float(bb.find("ymax").text) # 裁剪到图像边界,防止越界 xmin = max(0.0, min(xmin, iw - 1)) ymin = max(0.0, min(ymin, ih - 1)) xmax = max(0.0, min(xmax, iw - 1)) ymax = max(0.0, min(ymax, ih - 1)) cx = (xmin + xmax) / 2.0 / iw cy = (ymin + ymax) / 2.0 / ih w = (xmax - xmin) / iw h = (ymax - ymin) / ih lines.append(f"0 {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}") with open(os.path.join(OUT_DIR, xml_name.replace(".xml", ".txt")), "w") as f: f.write("\n".join(lines))

逻辑说明:先读图片真实宽高,再对每个 face 框做边界裁剪,最后归一化。参数上,:.6f保留六位小数足够 YOLO 使用;class id 固定 0。如果数据集里混有非 face 类别,name != "face"这一行会过滤掉。

3.2 坑一:宽高为 0 或负数的框

widerface 里存在极少数 xmax 等于 xmin 的退化框,转换后 w 或 h 为 0。YOLO 训练时这类框会导致 loss 出现 NaN。解决方式是在写 TXT 前加判断:

if xmax - xmin < 1 or ymax - ymin < 1: continue

3.3 坑二:图片格式不是 jpg

部分 widerface 二次整理包会把图片存成 png,但 XML 里仍写 jpg。转换脚本里xml_name.replace(".xml", ".jpg")会找不到文件。稳妥做法是先扫描 IMG_DIR 建立 stem 到真实文件名的映射,再按 stem 取图。

3.4 坑三:归一化后坐标超出 [0,1]

如果 XML 的框本身超出图片范围,裁剪后仍可能因为浮点误差略大于 1。写文件前统一 clamp:

cx = min(max(cx, 0.0), 1.0) cy = min(max(cy, 0.0), 1.0) w = min(max(w, 0.0), 1.0) h = min(max(h, 0.0), 1.0)

3.5 坑四:data.yaml 的路径写错

YOLO 训练读的是 data.yaml,不是目录本身。单类别 face 的 yaml 长这样:

path: ./widerface_b train: images/train val: images/val nc: 1 names: ["face"]

注意path是数据集根,train和val是相对路径。如果直接把 8188 张全放 train,val 为空,训练会报错。常见做法是按 9:1 切分,或者从 widerface 官方 val 里抽一部分。

4. 用 YOLO 训练这个子集:参数、显存与置信度门限

4.1 环境与预训练权重选择

ultralytics 系现在装起来很直接:

pip install ultralytics yolo checks

预训练权重用人脸场景更接近的,如果没有,用 yolov8n.pt 或 yolov8s.pt 做迁移。单类别、8188 张、大目标,n 或 s 足够,m 以上容易过拟合。V100 上 batch 可以开到 32 甚至 64,消费级卡按显存往下调。

4.2 训练命令与关键参数

yolo detect train \ data=./widerface_b/data.yaml \ model=yolov8s.pt \ epochs=100 \ imgsz=640 \ batch=32 \ lr0=0.01 \ lrf=0.01 \ mosaic=1.0 \ close_mosaic=10 \ patience=20 \ device=0 \ name=widerface_b_s

参数说明:imgsz=640对大目标足够,不必上 1280;mosaic=1.0前期增强,close_mosaic=10最后 10 轮关掉,让模型适应真实分布;patience=20早停,防止过拟合;lr0=0.01是 SGD 常用起点,如果用 AdamW 要降到 1e-3 量级。

4.3 置信度门限怎么调

训练完做推理时,conf默认 0.25。人脸检测场景下,如果漏检多,降到 0.1~0.15;如果误检多,升到 0.4~0.5。验证集上画 PR 曲线,找 F1 最大的点。命令:

yolo detect val model=runs/detect/widerface_b_s/weights/best.pt data=./widerface_b/data.yaml conf=0.001 iou=0.6

conf=0.001是为了让 val 计算完整 PR 曲线,不是最终部署门限。部署时再按业务定。

4.4 训练中 BN 崩溃与 loss 异常排查

如果 loss 突然变 NaN,先看是不是有退化框没过滤干净;其次看 batch 里是否有全黑或全白图片。BN 崩溃常见于 batch 太小加 lr 太大,把 batch 调到 16 以上,或者把 lr0 减半。另外,如果用了 mosaic 且图片尺寸差异极大,前期 loss 抖动是正常的,观察 10 轮再判断。

5. 避坑与常见问题:从解压到训练的血泪记录

5.1 解压后图片和标注数量对不上

现象:find images -type f | wc -l是 8188,但 labels 只有 8100 多。原因:部分图片没有 face 框,转换脚本没生成对应 TXT。解决:YOLO 允许空 TXT 表示负样本,但需要显式创建空文件,否则训练时该图被跳过。在转换脚本末尾对无框图片写一个空文件。

5.2 训练时提示「No labels found」

现象:启动训练立刻报错,说找不到标签。原因:data.yaml 里train路径指向了图片目录,但 YOLO 默认按「图片同 stem 的 txt 在 labels 目录」去找,目录结构必须是images/train配labels/train。解决:把图片和标签按 train/val 分好,保持 stem 一致。

5.3 验证集 mAP 高但实际推理漏检

现象:val mAP 0.9,但拿真实场景图推理,侧脸、小脸全漏。原因:B 大目标子集本身偏大脸,验证集分布和真实场景不一致。解决:把 widerface 的 Hard 子集抽一部分做额外验证,或者直接在真实场景图上做少量标注微调。

5.4 7z 解压报错但密码没错

现象:Windows 下 7-Zip 提示密码错误,但密码确实对。原因:压缩包可能用了 7z 增强版的加密头,或者下载不完整。解决:先7z t测完整性,不通过就重新下载;通过但解压失败,换 p7zip 命令行试。

5.5 训练完模型很大,部署慢

现象:yolov8s 训练完 best.pt 几十 MB,边缘设备跑不动。原因:没做导出优化。解决:导出 ONNX 或 TensorRT:

yolo export model=best.pt format=onnx opset=12 simplify=True

再按目标平台做量化。人脸检测单类别,量化后精度损失通常可接受。

6. 进阶:用这个子集做课程学习的第一阶段

B 大目标子集最大的价值不是刷榜,而是做课程学习的 warmup。我一般会先用这 8188 张训练 50 轮,让模型在大脸上收敛,然后再混入 widerface 全量或 Hard 子集继续训练。这样做的原因是:大目标梯度稳定,前期不会因为小脸样本的噪声导致模型学偏。具体操作是把第一阶段 best.pt 作为第二阶段预训练权重,第二阶段把 imgsz 提到 960 或 1280,mosaic 关掉,lr 降到第一阶段的十分之一。验证时分别在大目标 val 和 Hard val 上看 mAP,如果 Hard 掉得厉害,说明第二阶段数据配比有问题,适当增加小脸样本权重。

另一个技巧是用这个子集做 anchor 聚类。虽然 YOLOv8 是 anchor-free,但如果你还在用 YOLOv5 或 darknet,k-means 聚出来的 anchor 在大目标上会更集中。命令上,YOLOv5 的train.py带--noautoanchor可以手动指定。我自己的习惯是:任何新数据集到手,先跑一遍格式转换和 10 轮短训,看 loss 曲线和几张推理图,确认管线通了再上长训练。这个 8188 张的 B 大目标子集,正好适合做这个 sanity check。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询