简介:一份面向YOLO系列算法实战的厨师帽(发罩)目标检测数据集,内含1620张带标签图像,可服务于安全生产、发罩佩戴检测、算法精度评估等常见任务,适合目标检测初学者和需要快速产出基线模型的开发人员。压缩包内共2000个文件,总大小约26.17MB,标签同时提供1289个VOC格式xml和711个YOLO格式txt两种版本,分别存放在独立文件夹中,便于在不同检测框架间切换复用,也方便对比两种标注格式的训练差异。目前已有78人浏览学习,适配YOLOv5、YOLOv7、YOLOv8、YOLOv9、YOLOv10、YOLO11等多个主流版本,可直接接入配套训练脚本。数据集已划分好训练集、验证集和测试集,并附有可直接引用的data.yaml配置,省去手动标注与目录整理的繁琐环节;txt标签严格采用class、x_center、y_center、width、height归一化字段,能帮助使用者快速进入模型训练、验证与测试流程,尤其适合作为入门的完整目标检测练习资料。
1. 厨师帽检测,躲不开的YOLO系列算法目标检测数据集
后厨视频合规检测这几年需求越来越密:食品工厂、学校食堂、酒店后厨的摄像头都要识别“厨师帽/发罩是否规范佩戴”。真动手做的时候会发现,公开数据集要么太杂乱,要么镜头全在欧式厨房里,帽型、光线和遮挡都对不上国内场景。这份“yolo算法-厨师帽数据集-1620张图像带标签-发罩.zip”解压后就是图片加标签文件,能直接进YOLO系列算法训练,省掉自己爬图、清洗、标注一大轮工作。我的判断是:真实后厨里做“只检测一个正类(发罩)”的方案,比同时做“戴帽/没戴帽”两个类别更可控,误报反而更少。1620张图对单类检测来说,配迁移学习完全够跑。适合正在做食品安全监管系统的人、拿YOLO练手但缺图缺标签的开发者,以及准备把检测器部署到边缘设备做实时告警的工程。
2. 数据集解剖:目录结构、标签格式与下载后校验
2.1 目录结构与文件语义
拿到这份压缩包后,先别急着解压跑训练。我一般会先看目录长什么样。常见做法是images/放 JPG 源图,labels/放同名 TXT 标签,偶尔附带train.txt、val.txt或者一份data.yaml。下面这张表是这套数据的典型组织方式:
| 路径 | 内容 | 训练时用途 |
|---|---|---|
| images/ | 1620 张 JPG 原图,分辨率多为 640×640 或接近 | train/val 的输入 |
| labels/ | 与图片同名的 TXT,每行一个目标 | YOLO 直接读取的标签 |
| train.txt / val.txt | 图片路径列表 | 划分训练验证集 |
| data.yaml | nc、names、train、val 路径 | train 脚本直接引用 |
这里要特别提醒一句:文件名前缀完全一致的图片和标签才是一对。解压后如果发现IMG_0001.jpg没有对应的IMG_0001.txt,说明文件在传输或打包时损坏了,训练时 YOLO 会直接跳过这张图,但你自己不知道,最后结果偏了就很难排查。我习惯先做一次全量文件配对,再谈训练。
2.2 标签坐标:归一化四参数
YOLO 系列算法用的 TXT 标签格式固定为一行一个目标:
class_id x_center y_center width height注意这四格数值全部是归一化到 0~1 的,不是像素坐标。一图一框的话就是一行;如果一张图里有三个厨师帽,就是三行,每行互不干扰。这个设计让模型在 640×640 输入下不关心原始分辨率,训练和推理的尺度一致性靠 imgsz 参数统一。
我从标注工具导出的框往往是最小外接矩形的左上角 x_min、y_min 和右下角 x_max、y_max。转成 YOLO 格式的公式很固定,写成脚本就是一个小函数:
def xyxy_to_yolo(x_min, y_min, x_max, y_max, img_w, img_h): x_center = (x_min + x_max) / 2.0 / img_w y_center = (y_min + y_max) / 2.0 / img_h w = (x_max - x_min) / img_w h = (y_max - y_min) / img_h return f"0 {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}"逻辑说明:先算外接框中心点横纵坐标,再分别除以图片宽度和高度,得到 0~1 之间的比例值。类别 ID 硬编码成了0,适用于单类发罩检测。如果你要区分厨师帽和发网,就把标签文件里的0改成对应类别的索引,并在 data.yaml 里给两个类别命名。
参数说明:img_w和img_h必须是原始图片的像素宽高,不能拿缩略图尺寸算。如果转完标签后肉眼观察发现框偏移,优先检查这一项,十次有九次是这里出了问题。
2.3 下载后的第一件事:完整性校验
解压之后先跑一次脚本,把损坏图片和缺标签的样本筛出来,再进训练。我常用的 Bash 检查步骤如下:
#!/bin/bash for img in images/*.jpg; do base=$(basename "$img" .jpg) if [ ! -f "labels/${base}.txt" ]; then echo "缺少标签: $img" fi python3 -c "from PIL import Image; Image.open('$img').load()" 2>/dev/null || echo "图片损坏: $img" done echo "校验完成"逻辑说明:遍历images/下每张 JPG,先找同名 TXT 是否存在,再用 PIL 真正把图片加载进内存,加载失败就是损坏文件。这样一轮扫完,可以避免训练中途报“image not found”这种极其打断节奏的错误。
处理建议:缺标签的图片我一般剔出数据集,而不是手工补标。数量少时补标很快,但如果发现某张图缺标签是因为图像本身模糊到人眼都看不清帽檐,补出来的标注也会让模型学到错误特征。
3. 把数据喂进训练:格式统一、划分与类别权衡
3.1 从 VOC/COCO 转成 YOLO TXT
如果你手里的标签是 XML 或 JSON,而不是直接可用的 TXT,需要先做格式统一。最常见的是 VOC 格式的 XML,装有annotation/object/bndbox。转成 TXT 时核心就两步:解析 XML 拿坐标,然后套用第二节的归一化公式。
import os import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, out_txt_path): tree = ET.parse(xml_path) root = tree.getroot() size = root.find("size") img_w = int(size.find("width").text) img_h = int(size.find("height").text) lines = [] for obj in root.findall("object"): name = obj.find("name").text cls_id = 0 # 单类数据就是 0,多类需要建立映射表 box = obj.find("bndbox") x_min = int(box.find("xmin").text) y_min = int(box.find("ymin").text) x_max = int(box.find("xmax").text) y_max = int(box.find("ymax").text) lines.append(xyxy_to_yolo(x_min, y_min, x_max, y_max, img_w, img_h)) with open(out_txt_path, "w") as f: f.write("\n".join(lines) + "\n")逻辑说明:ET.parse把 VOC XML 解析成树结构,逐条循环object节点。每次取bndbox里的四角像素值,送到转换函数。类别映射我写成固定0,如果你的数据里有“厨师帽”“发网”“围裙”等多个类别,需要把name与类别索引建一个字典对应,不能写死。
参数说明:XML 里size节点的宽高必须和图片实际尺寸完全一致。部分标注工具会把width和height写反,转换完的标签不会马上看出来问题,但训练时 mAP 会低得莫名其妙。
3.2 数据划分与数据集 YAML
标签转好了,下一步做训练集和验证集划分。1620 张图不算大,我一般按 8:2 分离,并保证同一次拍摄连拍的图片不要全挤在验证集里。
mkdir -p images/train images/val labels/train labels/val # 按文件名排序后取前 80% 做训练,后 20% 做验证 find images -maxdepth 1 -name "*.jpg" | sort > all_images.txt total=$(wc -l < all_images.txt) train_count=$((total * 8 / 10)) head -n "$train_count" all_images.txt > train_paths.txt tail -n +"$((train_count + 1))" all_images.txt > val_paths.txt这样切分有一个风险:如果图片文件名本身是按拍摄时间排序的,前 80% 是上午拍的,后 20% 是下午拍的,光线环境差异大,验证集分数可能波动剧烈。建议尽量先shuf随机化再划分。数据集小的时候,随机划分比结构化划分更能反映整体分布。
对应的data.yaml写成:
train: images/train val: images/val nc: 1 names: ["cap"]nc: 1声明只有发罩一个类别,names里的字符串不参与计算,只用于输出可视化时显示标签名。路径用相对路径的话,执行训练命令的当前目录必须在data.yaml所在目录,否则会报找不到文件。
3.3 类别权衡:一个类还是两个类
这套数据的核心检测对象是厨师帽/发罩。单纯看词面,可能是单类,也可能是“帽子+发网”两个类。我的建议是:先确认标签文件里 class_id 到底有几种。如果全是 0,就按单类处理,模型只需要学“有没有帽子”这个语义,决策边界最简单。
如果标签里出现了 0 和 1,就得想清楚两个类别是不是真的分得开。比如“厨师帽”和“发网”外形差异明显,可以分成两类;但如果你拿到的标注把白色高帽和蓝色布帽分成两类,我建议合并成“帽子”一个类,因为模型学“帽子轮廓”比学“帽檐褶皱细节”容易得多。单类检测的另一个实际好处是,部署时的置信度阈值可以放宽到 0.25 而不担心类间误判——反正只有一种帽子。
4. 训练实操:YOLOv8 的训练套餐与参数对照
4.1 环境准备与依赖
训练 YOLOv8 不需要自己写网络结构,装 ultralytics 库就够了。我建议用独立的 Python 环境,避免和已有项目打架。
conda create -n yolo python=3.10 -y conda activate yolo pip install ultralytics安装耗时 2~5 分钟。GPU 机器上 pip 会自动匹配 CUDA 版本;遇到 torch 报错,可以单独执行pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121重新装一遍 CUDA 12.1 版本。
环境装完后加一句网络检查,确认能读到显卡:
python -c "import torch; print(torch.cuda.is_available())"输出True再进下一步。输出False就回到 torch 安装环节排查,这是训练前后最不值得玄学处理的一步。
4.2 训练命令与参数对照
数据准备好了直接开训:
yolo detect train data=cook_hat.yaml model=yolov8n.pt epochs=50 imgsz=640 batch=16 patience=10| 参数 | 取值 | 说明 |
|---|---|---|
| data | cook_hat.yaml | 数据集的 YAML 路径 |
| model | yolov8n.pt | 预训练权重,n 是 nano 版本 |
| epochs | 50 | 完整遍历次数,单类数据 50 轮足够 |
| imgsz | 640 | 输入分辨率,和后厨摄像头取流分辨率一致 |
| batch | 16 | 显存 8GB 以下建议降到 8 |
| patience | 10 | 连续 10 轮 mAP 不涨就提前停 |
| project | runs | 输出目录,可视需要修改 |
逻辑说明:用yolov8n.pt作为起点,是拿 COCO 预训练特征做迁移学习。n 版本参数量最小,跑一轮不到 2 分钟,适合先验证数据和标签有没有问题。验证通过后再换yolov8s.pt或yolov8m.pt提精度,而不是一上来就开大模型,翻车了都不知道是数据问题还是模型问题。
batch 参数直接影响显存占用。如果不填,ultralytics 会按显存自动猜一个值,但猜出来的往往偏保守。固定写死 16 有利于复现:别人用 16 跑出来的结果和你的有可比性,写 auto 则每次可能不同。
训练结束后的权重在runs/detect/train/weights/best.pt。设计上的经验是:best 是根据验证集 mAP 挑出来的,最终部署选它,不要选last.pt。
4.3 训练过程怎么看:loss 曲线与 PR 指标
训练日志每小时刷一次,需要盯的核心指标是Box P、Box R和mAP50。数值达到多少算过关没有绝对标准,但结构上大致遵循:
- 前 10 轮 mAP50 从 0 快速拉到 0.6 以上,说明数据和标签基本干净;
- 之后进入缓慢提升期,每轮涨 0.01~0.03 都属正常;
- 验证集 P 值和 R 值差距过大,比如 P 0.95 但 R 0.45,说明模型找到了很多框,但厨师帽出现角度变化就漏检,需要补数据增强或加正样本。
Box Loss曲线如果持续不降,卡在 0.05 附近震荡,常见原因是同一张图里的目标框标注不一致,模型在两个冲突的框之间反复横跳。这时候不要调参,回头查标注更有效。
5. 避坑:厨师帽数据集训练翻车的五个现场与排查路径
5.1 最容易踩的三个数据坑
现象一:训练 loss 正常下降,但验证集 mAP50 始终卡在 0.3 附近不动。 原因:验证集里包含了和训练集几乎完全相同的图片,或者说验证集本身太简单,模型只学会了记忆样本。这套数据集按次序划分时尤其容易出现这种情况。 解决:随机化重划分,或者用k-fold交叉验证跑一轮看稳定性。
现象二:帽檐贴脸太紧,检测框把脸也包进去一半,实际部署时头皮和帽子边界分辨不清。 原因:标注框画得贴边框,而帽子最下缘和头发之间本来就有一小段皮肤色过渡区,模型学到的边界比人眼松。 解决:标签框回收 3~5 个像素,不追求完全贴边,留出过渡带反而让框更稳定。
现象三:深色帽子大量漏检,而白色帽子基本全检。 原因:样本不平衡。多数公开后厨图都是白色高帽,深色布帽、黑色发网占比明显不足。 解决:把深色帽子的图复制两份做随机亮度扰动,扩到总样本的 30% 以上再训。数据增强参数用hsv_h=0.03 hsv_s=0.7 hsv_v=0.5可以缓解光照影响。
5.2 模型权重部署后效果反转的排查路径
模型在训练集的验证集上 mAP 很高,但跑视频流时框乱跳,或者画面里戴了厨师帽的人没被框出来。这类问题通常不在权重本身,而在输入差异:
第一步排除图像尺寸。训练时imgsz=640,部署推理最好用同一分辨率。摄像头取流是 1080p 时,先缩到 640×640 再做推理,而不是直接把 1080p 送进模型。
第二步排除锚框尺寸先验问题。YOLOv8 是 anchor-free,不需要手动调 anchor,但如果检测对象占比极小,比如 3 米外拍到的帽子只有 20×20 像素,建议在训练时把帽子尽量放大裁剪到 80×80 以上。
第三步检查 NMS 阈值。默认iou=0.7、conf=0.25。部署时有误报就提高 conf 到 0.4,有漏检就降到 0.15。这是上线前最值得花半小时扫一遍的两个旋钮,比换模型快得多。
6. 验证部署:用真图框尺量一量,别只看 mAP
6.1 跑真实场景抽帧比看指标更有说服力
训练完权重后,我习惯先跑一遍真实抽帧图,而不是直接拿测试集看 mAP。测试集和训练集同源,指标再漂亮也说明不了光线和视角变化后的表现。用下面这段脚本批量验证一张目录里的真实画面:
from ultralytics import YOLO model = YOLO("runs/detect/train/weights/best.pt") results = model.predict( source="real_samples/", imgsz=640, conf=0.25, save=True, project="runs/val_real", name="sample_01" ) for r in results: boxes = r.boxes print(f"图 {r.path}: {len(boxes)} 个目标") for box in boxes: x1, y1, x2, y2 = box.xyxy[0].tolist() conf = box.conf[0].item() print(f" cap conf={conf:.2f} box=({x1:.0f},{y1:.0f},{x2:.0f},{y2:.0f})")参数说明:source指向真实场景图片目录,imgsz必须与训练时一致,save=True会把画了框的结果图存到runs/val_real/sample_01/。人工检查输出图时,重点不是看“有没有框住帽子”,而是看“框住的部分是不是只有帽子”。如果框住额头甚至框住整个头部,说明模型把“头顶区域”当成了“帽子存在区域”,部署时误报会很严重。
后续部署到边缘盒子时,把 best.pt 转成 ONNX 再推,能省掉 PyTorch 的依赖:
yolo export model=runs/detect/train/weights/best.pt format=onnx imgsz=640ONNX 文件在 CPU 或 NVIDIA 的 TensorRT 上都能跑,转出来后用 onnxruntime 做一次一致性验证,确认输出框和 PyTorch 原版差距小于 1%。
做厨师帽检测这些年,我最大的感受是数据干净程度决定模型上限,参数只是保住这个上限。每换一个新场景,我都强制走一遍校验→训练→真实图验证的流程,省下过太多半夜调参的时间。如果你手里正缺带标签的后厨图,这份 1620 张的厨师帽数据集值得按上面的步骤完整跑一轮,希望帮到你。
本文还有配套的精品资源,点击获取