
简介这份智慧养殖场肉鸡健康状态检测数据集面向计算机视觉学习者、农业智能化研究者与目标检测工程人员用于训练和验证肉鸡异常与正常状态的识别模型可服务于养殖场巡检、疾病预警等场景。资源采用Pascal VOC与YOLO双格式标注包含4657张jpg图片并配有等量的xml与txt标注文件标注类别为AbNormal与Normal两类其中AbNormal框数8447、Normal框数13163总框数达21610均使用labelImg按矩形框规则完成标注。压缩包为7z格式共2000个文件以1999个xml标注文件和1个说明txt为主整体约396.56MB目录结构便于直接接入主流检测框架。目前已有395人学习下载适合需要快速获取真实养殖场景标注数据、开展模型训练与对比实验的读者参考使用。1. 智慧养殖场肉鸡健康状态检测数据集4657 张 VOCYOLO 双格式到底能干什么肉鸡养殖场里最怕的不是行情波动而是鸡群悄无声息地出现精神萎靡、扎堆、闭眼缩脖——等肉眼发现时往往已经扩散。智慧养殖场肉鸡健康状态检测数据集 VOCYOLO 格式 4657 张 2 类别解决的就是把人巡棚变成模型盯棚这一步的冷启动问题。它提供 4657 张已标注图像同时给出 VOC XML 和 YOLO TXT 两套标注2 个类别通常对应健康与异常或具体病态状态拿来就能直接喂给 YOLO 系列做训练。适合三类人想切入智慧养殖的算法工程师、做农业物联网需要视觉能力的开发者、以及拿它当课程设计或论文实验底座的学生。它不解决摄像头怎么装、鸡舍怎么控温只解决标注数据从哪来这个最耗人力的环节。2. 先搞懂 VOC 与 YOLO 双格式为什么同一批图要存两份标注拿到压缩包解压后你会看到 images 和 annotations 两套目录标注却有两份。这不是冗余而是数据集作者替你省掉了格式转换的麻烦。理解这两种格式的差异决定了你后面能不能一次跑通训练。2.1 VOC XML 与 YOLO TXT 的结构差异VOC 格式源自 PASCAL VOC 挑战赛每张图对应一个同名 XML 文件里面用绝对像素坐标记录每个目标的框annotation filenamechicken_0001.jpg/filename size width640/width height480/height depth3/depth /size object namehealthy/name !-- 类别名中文类别需映射为英文 -- bndbox xmin112/xmin !-- 左上角 x绝对像素 -- ymin88/ymin xmax305/xmax !-- 右下角 x -- ymax342/ymax /bndbox /object /annotationYOLO 格式则是每张图一个同名 TXT每行一个目标全部归一化到 0~10 0.325781 0.447917 0.301563 0.529167 1 0.712500 0.610417 0.218750 0.395833第一列是类别索引从 0 开始后四列是中心x 中心y 宽 高均为相对整图宽高的比例。这个差异是后面所有坑的根源VOC 用绝对坐标和类别名YOLO 用归一化坐标和类别索引。2.2 两种格式各自的适用场景VOC 更适合做数据审查、可视化核对和跨框架转换因为坐标是像素值肉眼一看就知道框对不对很多标注工具和检测框架如早期的 Faster R-CNN、MMDetection 的部分配置原生吃 VOC。YOLO 格式则是 Ultralytics 系YOLOv5/v8/v11训练的标准输入省去训练时的归一化计算读取更快。维度VOC XMLYOLO TXT坐标绝对像素 xmin/ymin/xmax/ymax归一化 中心宽高类别字符串名称整数索引一图多目标多个 object 节点多行典型用途审查、转换、MMDetectionYOLOv5/v8 直接训练2.3 类别映射与 data.yaml 的对应关系YOLO 训练只认索引所以你必须先确认两个类别的名称和顺序。常见做法是打开任意一个 XML看name里出现的字符串再决定索引。假设类别是healthy和sick那么data.yaml要这样写path: /data/chicken_health # 数据集根目录 train: images/train # 训练图相对路径 val: images/val # 验证图相对路径 nc: 2 # 类别数必须与标注索引最大值1一致 names: 0: healthy 1: sick提示names的顺序必须和 TXT 里第一列的索引严格对应。如果 TXT 里 0 代表 sick、1 代表 healthy而 yaml 写反了模型照样能训练但推理结果会整体错位这种错误不看混淆矩阵很难发现。3. 从 7z 解压到跑通 YOLOv8 训练一条可复现的命令链这一章是整篇的核心目标是从拿到压缩包到看到第一轮 loss 下降。我按实际操作的顺序拆每一步都给出命令和参数解释你照着改路径就能跑。3.1 解压与目录体检7z 在 Linux 下需要先装 p7zipWindows 用 7-Zip 图形界面即可。解压后第一件事不是急着训练而是数一遍文件、看一遍目录结构# 安装 7zDebian/Ubuntu sudo apt-get install -y p7zip-full # 解压到指定目录-o 后面不能有空格 7z x 智慧养殖场肉鸡健康状态检测数据集VOCYOLO格式4657张2类别.7z -o./chicken_dataset # 进入目录看结构 cd chicken_dataset find . -maxdepth 2 -type d # 统计图片数量确认是否接近 4657 find . -name *.jpg -o -name *.png | wc -l # 统计 XML 与 TXT 数量两者应大致相等 find . -name *.xml | wc -l find . -name *.txt | wc -l逻辑说明7z x是保留目录结构的解压-o指定输出目录且中间不能有空格这是新手最常翻车的地方。统计数量是为了确认压缩包完整、没有解压中断。如果图片数和标注数对不上说明有图缺标注训练时那部分图会被当成负样本直接影响召回。3.2 划分 train/val 并生成 YOLO 目录数据集如果没预先分好 train/val你需要自己切。常见做法是 8:2 或 9:1且要保证两个类别在验证集里都有分布。下面脚本把 VOC 的 XML 转成 YOLO TXT 的同时完成划分import os, random, shutil import xml.etree.ElementTree as ET # 类别名到索引的映射顺序必须与 data.yaml 一致 CLASS_MAP {healthy: 0, sick: 1} SRC_IMG images # 原图目录 SRC_XML annotations # VOC 标注目录 OUT yolo_dataset # 输出根目录 VAL_RATIO 0.2 # 验证集比例 def voc_to_yolo(xml_path, img_w, img_h): tree ET.parse(xml_path) lines [] for obj in tree.findall(object): name obj.find(name).text.strip() if name not in CLASS_MAP: continue # 跳过未定义类别避免索引越界 cls_id CLASS_MAP[name] box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) # 归一化中心点 宽高全部除以图宽高 cx (xmin xmax) / 2.0 / img_w cy (ymin ymax) / 2.0 / img_h w (xmax - xmin) / img_w h (ymax - ymin) / img_h lines.append(f{cls_id} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f}) return lines # 建立输出目录 for sub in [images/train, images/val, labels/train, labels/val]: os.makedirs(os.path.join(OUT, sub), exist_okTrue) imgs [f for f in os.listdir(SRC_IMG) if f.lower().endswith((.jpg, .png))] random.seed(42) # 固定种子保证划分可复现 random.shuffle(imgs) val_n int(len(imgs) * VAL_RATIO) val_set set(imgs[:val_n]) for img in imgs: stem os.path.splitext(img)[0] xml_path os.path.join(SRC_XML, stem .xml) if not os.path.exists(xml_path): continue # 无标注的图直接丢弃 # 读取图片真实宽高不能想当然用 640x480 from PIL import Image with Image.open(os.path.join(SRC_IMG, img)) as im: w, h im.size lines voc_to_yolo(xml_path, w, h) split val if img in val_set else train shutil.copy(os.path.join(SRC_IMG, img), os.path.join(OUT, images, split, img)) with open(os.path.join(OUT, labels, split, stem .txt), w) as f: f.write(\n.join(lines)) print(done, train:, len(imgs) - val_n, val:, val_n)参数说明CLASS_MAP决定索引改类别时同步改data.yamlVAL_RATIO控制验证集比例数据量 4657 张时 0.2 足够random.seed(42)保证每次划分一致方便复现实验。关键点是宽高必须从图片实际读取很多公开数据集图片尺寸不统一硬编码 640×480 会让归一化坐标全错。3.3 用 YOLOv8 起训关键参数怎么设环境用 conda 或 venv 都行装 ultralytics 即可pip install ultralytics # 单卡训练batch 按显存调8G 显存建议 16 yolo detect train \ data./yolo_dataset/data.yaml \ modelyolov8n.pt \ epochs100 \ imgsz640 \ batch16 \ lr00.01 \ patience20 \ projectruns/chicken \ nameexp1逻辑说明modelyolov8n.pt用官方预训练权重做迁移学习小数据集上比从头训收敛快得多imgsz640是 YOLOv8 默认输入尺寸若原图分辨率远大于此小目标会被缩没需要评估lr00.01是初始学习率数据量几千张时这个值比较稳patience20表示 20 轮无提升就早停省时间。训练中重点看mAP50和mAP50-95两条曲线如果 loss 一直震荡不降先查标注而不是调参。3.4 推理验证与结果落盘训练完用 best.pt 跑推理确认框的位置和类别都对yolo detect predict \ modelruns/chicken/exp1/weights/best.pt \ source./yolo_dataset/images/val \ conf0.25 \ saveTrue \ projectruns/chicken \ namepredconf0.25是置信度阈值低于它的框不输出养殖场场景如果漏检代价高可以降到 0.15 再人工复核。结果图会存到runs/chicken/pred逐张看有没有把健康鸡误判成病鸡这比只看 mAP 数字更直观。4. 训练不收敛、mAP 上不去肉鸡检测的 5 个血泪坑这一章按现象 → 原因 → 解决写都是我在这类养殖数据集上真实踩过的。4.1 现象loss 正常下降但 mAP 始终接近 0原因data.yaml里names顺序和 TXT 索引反了或者nc写成了 1。模型在学但类别对不上评估时全判错。 解决抽 5 张图用脚本把 TXT 画回图上肉眼确认框和类别再核对nc是否等于索引最大值加一。4.2 现象训练几十轮后突然 NaNBN 崩溃原因batch 里混入了宽高为 0 的脏标注或者某张图归一化后坐标超过 1。VOC 转 YOLO 时如果 xmax 小于 xmin宽就是负数。 解决转换脚本里加校验w0 or h0的框直接丢弃并记录文件名训练前跑一遍全量标注检查。# 标注体检找出越界和零面积框 for line in open(txt_path): c, cx, cy, w, h line.split() if not (0 float(cx) 1 and 0 float(cy) 1): print(越界, txt_path) if float(w) 0 or float(h) 0: print(零面积, txt_path)4.3 现象验证集 mAP 高实际棚内视频漏检严重原因数据集图像多为近距离单鸡或小群实际监控是俯视远景、鸡只密集扎堆域差异大。 解决训练时开 Mosaic 和随机缩放增强imgsz适当调大有条件补采俯视远景图哪怕只标几百张域适应效果立竿见影。4.4 现象两个类别样本极不均衡病鸡几乎检不出原因健康鸡远多于病鸡模型倾向全预测为健康也能拿高准确率。 解决用cls损失加权或在data.yaml同级配置里对少数类过采样评估时重点看少数类的 recall 而不是整体 mAP。4.5 现象换机器后训练结果对不上原因随机种子、cuDNN 非确定性、数据加载顺序都会影响结果。 解决固定seed设置deterministicTrue并把划分脚本的种子写死。追求完全复现要接受一定速度损失。5. 把 4657 张用到极致小数据集的增强与半自动标注技巧4657 张对两分类检测不算多想让它撑起一个能上线的模型关键在榨干每一张。我一般会做三件事离线增强扩样、难例挖掘回标、以及用训练好的模型做半自动标注反哺。先说离线增强。YOLO 训练自带的在线增强Mosaic、HSV、翻转已经够用但养殖场特有的光照变化——白天强光、夜间红外补光——在线增强模拟不出来。我的做法是单独生成一批亮度扰动和对比度扰动的副本只对训练集做验证集保持原样避免评估虚高import cv2, os, numpy as np src yolo_dataset/images/train dst yolo_dataset/images/train_aug os.makedirs(dst, exist_okTrue) for f in os.listdir(src): img cv2.imread(os.path.join(src, f)) # 亮度扰动模拟不同补光强度 bright cv2.convertScaleAbs(img, alpha1.0, beta30) dark cv2.convertScaleAbs(img, alpha1.0, beta-30) cv2.imwrite(os.path.join(dst, b_ f), bright) cv2.imwrite(os.path.join(dst, d_ f), dark) # 标签直接复制几何未变 stem os.path.splitext(f)[0] for p in [b_, d_]: src_lbl fyolo_dataset/labels/train/{stem}.txt if os.path.exists(src_lbl): import shutil shutil.copy(src_lbl, fyolo_dataset/labels/train_aug/{p}{stem}.txt)参数说明beta±30是亮度偏移量太大失真、太小没效果30 左右比较合适只做亮度不做几何变换是为了让标签能直接复用省去重算坐标。增强后训练集翻三倍小数据集上通常能涨 2~4 个点 mAP。再说半自动标注。第一版模型训完后拿它去推理未标注的新视频抽帧把高置信度conf0.6的框导出成 YOLO TXT人工只做删改不做从零画框效率能提升好几倍。这一步的坑是模型自己的错误会被固化进新标注形成闭环偏差。所以人工复核不能省尤其是低置信度区间0.25~0.6的框必须逐一看。最后给一个判断值不值得投入的标准如果你的场景里鸡只互相遮挡严重、单帧目标超过 30 个4657 张两分类可能不够需要先补数据再谈模型如果是单排笼养、目标清晰这套数据加上述增强训一个能用的检测器完全够。我自己踩过最深的坑是急着调参而没先做标注体检结果两天时间全浪费在 NaN 上——先体检、再训练这个顺序别颠倒。希望帮到你。本文还有配套的精品资源点击获取