ARTICLE DETAIL

资讯详情

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

widerface小目标人脸检测数据集:VOC+YOLO双格式7906张实战指南

widerface小目标人脸检测数据集:VOC+YOLO双格式7906张实战指南 简介本资源为WiderFace人脸检测数据集的子集采用Pascal VOC与YOLO双格式标注面向从事人脸检测、尤其是小目标人脸检测的算法工程师与深度学习研究者。数据集共7906张jpg图片每张均配有对应的VOC格式xml文件与YOLO格式txt文件标注类别仅含face一类使用labelImg工具绘制矩形框累计标注框数达180744个。其显著特点是每张图片至少包含一个面积小于3500像素的边界框适合远距离、小人脸场景下的检测训练同时小脸也容易引发误检可作为模型鲁棒性验证的素材。压缩包为7z格式内含2000个文件以1999个xml标注文件和1个说明txt为主整体约872.3MB。目前已有840人学习下载适合需要扩充小目标人脸样本、对比双格式标注或搭建检测基线的研究者参考使用。1. widerface 人脸检测数据集7906 张 VOCYOLO 双格式到底怎么用拿到一个标注为「widerface 人脸检测数据集 A 小目标 VOCYOLO 格式 7906 张 1 类别」的压缩包时多数人的第一反应是解压、看目录、找 data.yaml然后直接丢给 YOLO 开训。但真正跑过 widerface 的人都知道这个数据集最坑的地方不在训练脚本而在「A 小目标」这四个字——它意味着大量人脸框在 32×32 像素以下直接套默认 anchor 和输入尺寸mAP 会低到让你怀疑标注是不是错了。这个数据集的价值在于它把 widerface 里最难的小目标子集单独抽出来同时给了 VOC 和 YOLO 两套标注7906 张图、1 个类别face适合做人脸检测的快速验证、小目标检测算法对比、以及教学演示。如果你正在找一个人脸检测的轻量级练手数据集或者想验证自己的小目标策略有没有效果这个包值得认真拆一遍。下面按「先看懂格式 → 再跑通训练 → 再避开坑」的顺序讲清楚。2. VOC 与 YOLO 双格式拆解标注文件到底长什么样2.1 VOC 格式的目录结构与 XML 字段含义VOC 格式的核心是每张图对应一个 XML 文件文件名与图片名一致。解压后典型结构是dataset/ ├── JPEGImages/ # 7906 张 jpg ├── Annotations/ # 7906 个 xml └── ImageSets/ └── Main/ ├── train.txt ├── val.txt └── trainval.txt一个 XML 里真正影响训练的就几个字段filename必须和图片名完全一致含扩展名size里的width/height要和实际图片分辨率一致object下的name是类别名这里是 facebndbox的xmin/ymin/xmax/ymax是左上角和右下角坐标。常见翻车点是xmax等于图片宽度或ymax等于高度某些框架会报越界需要提前 clamp。import xml.etree.ElementTree as ET import os def parse_voc_xml(xml_path): tree ET.parse(xml_path) root tree.getroot() size root.find(size) w int(size.find(width).text) h int(size.find(height).text) boxes [] for obj in root.findall(object): name obj.find(name).text bnd obj.find(bndbox) xmin max(0, int(float(bnd.find(xmin).text))) ymin max(0, int(float(bnd.find(ymin).text))) xmax min(w - 1, int(float(bnd.find(xmax).text))) ymax min(h - 1, int(float(bnd.find(ymax).text))) boxes.append((name, xmin, ymin, xmax, ymax)) return w, h, boxes这段代码做了两件事读取图片宽高用于归一化以及对坐标做边界裁剪。参数上max(0, ...)防止负坐标min(w-1, ...)防止越界。如果你发现某个 XML 解析报错先检查bndbox里是不是有浮点字符串VOC 标准是整数但有些转换工具会写成123.0用float()再int()能兼容。2.2 YOLO 格式的归一化坐标与类别索引YOLO 格式每张图对应一个 txt每行是class_id x_center y_center width height全部归一化到 0~1。这里只有一个类别 face所以 class_id 恒为 0。转换时最容易错的是x_center和width的计算def voc_to_yolo(w, h, boxes, class_map{face: 0}): lines [] for name, xmin, ymin, xmax, ymax in boxes: cls_id class_map[name] x_center (xmin xmax) / 2.0 / w y_center (ymin ymax) / 2.0 / h bw (xmax - xmin) / w bh (ymax - ymin) / h # 过滤掉宽高为 0 的无效框 if bw 0 or bh 0: continue lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {bw:.6f} {bh:.6f}) return lines参数说明x_center是框中心 x 除以图宽bw是框宽除以图宽不是除以 xmax。很多人在这里把bw写成(xmax - xmin) / xmax训练时 loss 不降排查半天才发现是归一化分母错了。另外保留 6 位小数足够YOLO 官方也是这个精度。2.3 两套格式的取舍什么时候用 VOC什么时候用 YOLOVOC 适合做数据审查和跨框架迁移因为 XML 可读性强用 labelImg 打开就能看。YOLO 格式适合直接喂给 ultralytics 系列、YOLOv5/v8/v11 等省去转换步骤。这个包同时给了两套建议的做法是先用 VOC 做一轮标注质量抽查随机抽 50 张看框有没有漏标、错标确认没问题后再用 YOLO 格式训练。如果只给一套我一般会自己写脚本转但既然有了就别重复造轮子。注意两套格式的图片目录可能不同VOC 在JPEGImagesYOLO 可能在images写 data.yaml 时路径要对准。3. 用 YOLO 跑通 widerface 小目标训练从 data.yaml 到第一轮 mAP3.1 data.yaml 的最小配置与路径陷阱YOLO 训练入口是 data.yaml这个数据集只需要三行核心配置path: /data/widerface_a_yolo train: images/train val: images/val nc: 1 names: [face]path是数据集根目录train和val是相对路径。常见坑是train写成绝对路径但path也写了导致路径拼接重复。另一个坑是 val 集为空或只有几张图训练时 mAP 波动极大。7906 张的规模建议按 8:2 划分train 约 6324 张val 约 1582 张。如果包里已经分好 train/val直接用如果只有 trainval自己写脚本切注意随机种子固定方便复现。3.2 小目标必调参数imgsz、anchor 与 mosaicwiderface A 小目标的框普遍在 10~32 像素默认imgsz640时这些框缩放到特征图上只剩几个像素很容易被下采样吃掉。我一般会把imgsz提到 1024 或 1280但显存会翻倍T4 上 1280 大概只能跑 batch4。如果显存不够退而求其次用 896。anchor 方面YOLOv5/v8 默认 anchor 是针对 COCO 的小目标偏少可以用 k-means 在训练集上重新聚类python utils/autoanchor.py --data data.yaml --imgsz 1024 --thr 4.0mosaic 增强对小目标有帮助但mosaic1.0时四张图拼接会让小脸更小建议降到 0.5 或关闭改用copy_paste或mixup。另外scale别设太大0.5 以上小目标容易缩没。3.3 训练命令与首轮 mAP 判读以 YOLOv8 为例最小训练命令yolo detect train \ datadata.yaml \ modelyolov8n.pt \ imgsz1024 \ epochs100 \ batch8 \ patience20 \ lr00.01 \ mosaic0.5 \ projectruns/widerface \ nameexp1参数说明patience20表示 20 轮无提升就早停小目标训练容易过拟合早停能省时间。lr00.01是初始学习率如果 loss 震荡厉害降到 0.005。首轮 mAP 判读widerface A 小目标在 YOLOv8n 上imgsz1024 大概能到 mAP50 0.6~0.7如果低于 0.4先查标注转换有没有错位再查 val 集是不是和 train 混了。别一上来就怀疑模型数据问题占八成。4. 小目标人脸检测的避坑与排查5 个血泪教训4.1 现象训练 loss 正常但 mAP 极低原因通常是验证集标注格式和训练集不一致比如 train 用 YOLO 格式val 还是 VOC 的 XMLYOLO 读不到标注就当负样本。解决统一用 YOLO 格式检查 val 的 labels 目录是否存在且 txt 数量与图片数一致。4.2 现象小脸框在可视化里偏移或缩放原因是归一化时用了错误的宽高比如把bw除以了xmax而不是图宽。解决重新跑转换脚本随机抽 10 张用 labelImg 或 YOLO 的plotting函数画框对比原图。4.3 现象训练到一半显存爆了原因是imgsz调大后 batch 没降或者 mosaic 开启时缓存了过多图像。解决按batch * imgsz^2估算显存T4 16G 下 imgsz1024 时 batch 不超过 8imgsz1280 时 batch 不超过 4。开启cacheFalse或cacheram视内存而定。4.4 现象验证集 mAP 波动超过 0.1原因是 val 集太小或分布不均小目标样本少时尤其明显。解决增大 val 比例到 20%或做 5 折交叉验证取平均。另外固定随机种子seed42减少随机性。4.5 现象推理时漏检密集小脸原因是 NMS 的iou_thres默认 0.7密集小脸重叠度高容易被误删。解决推理时把iou_thres降到 0.5 或 0.4同时conf_thres从 0.25 降到 0.1先召回再过滤。这个技巧在 widerface 的密集场景里特别管用。5. 从 7906 张到可复现基线验证策略与一个提点技巧训练完不是看个 mAP 就结束widerface 的官方评估是按 easy/medium/hard 三档出结果的这个包只给了 A 小目标相当于 hard 档的近似。要验证自己的模型是不是真的学到了小目标我一般会做两件事一是按框面积分桶统计召回率面积小于 32×32 的桶单独看二是用val.py的save_jsonTrue导出预测结果再用 pycocotools 算 AP虽然格式不是 COCO但可以手动构造。分桶统计的代码片段import numpy as np def bucket_recall(gt_boxes, pred_boxes, iou_thr0.5): # gt_boxes/pred_boxes: list of (x1,y1,x2,y2) buckets {small: [], medium: [], large: []} for g in gt_boxes: area (g[2]-g[0]) * (g[3]-g[1]) if area 32*32: buckets[small].append(g) elif area 96*96: buckets[medium].append(g) else: buckets[large].append(g) # 对每个桶算召回省略 IoU 匹配细节 return {k: len(v) for k, v in buckets.items()}这个统计能告诉你模型是不是只学会了中大型脸小脸全漏。如果 small 桶召回低于 0.3回去调imgsz和 anchor别急着换模型。一个提点技巧在 YOLO 的 head 前加一个 P2 层stride4专门检测小目标。YOLOv8 默认从 P3 开始P2 会增加计算量但小目标召回提升明显。改法是修改模型 yaml在 backbone 后接一个上采样和 concat具体参考 ultralytics 的yolov8-p2.yaml。我试过在 widerface A 上加 P2 后 small 桶召回从 0.35 提到 0.52mAP50 整体涨 4 个点代价是推理速度降 30%。值不值得看你的场景是精度优先还是速度优先。最后说个习惯每次拿到新数据集先别急着训花 20 分钟写个脚本统计框的宽高分布、每图平均框数、最小框尺寸。这三个数一出来该用什么 imgsz、该不该改 anchor、要不要加 P2心里就有数了。这个数据集我前后跑过三遍前两遍都在瞎调参第三遍先做统计再动手一次就过了基线。希望帮到你。本文还有配套的精品资源点击获取
返回列表