简介:这份资源面向从事智慧养殖、家禽健康监测方向的研究者与算法工程师,提供YOLOv5养殖场肉鸡健康状态检测的预训练权重及配套数据集,可用于异常与正常两类肉鸡状态的识别任务,适合作为课程设计、科研实验或工业落地的起点。压缩包共983个文件,约58.62MB,以441张jpg图像与435个txt标签为主体,另含29个yaml配置、24个py脚本及3个pt权重文件,覆盖数据、训练与推理全流程。数据集已按train、val、test划分完毕,并附data.yaml,标注nc为2、类别为Abnormal与Normal,yolov5、yolov7、yolov8、yolov9等算法可直接接入训练。目前已有146人学习,读者可借此省去数据整理与配置成本,快速复现检测流程,并参考作者博文中的检测结果与目录结构,理解养殖场场景下的数据组织与模型调参思路。
1. 养殖场里那点事:为什么肉鸡健康检测值得用 YOLOv5 认真做一遍
在规模化养殖场里,肉鸡的健康状态直接决定出栏率和用药成本。传统做法靠饲养员巡棚肉眼观察,一个人管几万只鸡,等发现精神萎靡、羽毛蓬乱、跛行的个体时,往往已经扩散了一片。我最早接触这个方向,是因为一个做养殖设备的朋友抱怨:摄像头装了不少,但没人盯着看,录像只能事后回放,起不到预警作用。后来我们把思路转到目标检测上——让模型自动框出疑似病态个体,人只需要复核报警框。YOLOv5 在这个场景里是个务实的选择:单阶段检测、推理快、权重文件小、部署到边缘盒子或工控机上都不费劲,而且社区里现成的训练脚本和导出工具链足够成熟,不用从零造轮子。这篇笔记就围绕「YOLOv5 养殖场肉鸡健康状态检测权重+数据集」这条线,把数据怎么标、权重怎么训、参数怎么调、坑在哪,按我自己跑过的流程讲清楚。适合想把这个方向落地到实际棚舍的工程师,也适合刚拿到一份数据集不知道从哪下手的新手。
2. 数据集与权重到底长什么样:先看清手里的牌
2.1 肉鸡健康状态检测的类别定义与标注边界
这个任务的核心不是「检测鸡」,而是「检测鸡的健康状态」。常见做法是把类别分成几档,比如健康、疑似患病、重度病态,或者按具体症状分:精神萎靡、跛行、羽毛异常、呼吸异常。类别怎么定,直接决定后面标注一致性和模型能不能收敛。我一般建议先跟现场兽医对齐,把肉眼能稳定判断、且不同人标注差异小的状态留下来。比如「精神萎靡」这种主观描述,如果三个人标同一张图能标出三种结果,那这个类别就是灾难。更稳的做法是绑定可观察的物理特征:低头缩颈超过一定时长、单腿站立、明显跛行步态、羽毛大面积逆立。标注时用矩形框把整只鸡框住,不要只框头部或腿部,因为 YOLOv5 学的是整体外观特征。如果一只鸡被遮挡超过一半,宁可不标,也不要猜。
2.2 权重文件与数据集目录的对应关系
拿到一份「权重+数据集」的组合,第一件事是确认权重对应的类别数和数据集标签是否一致。我见过太多人直接拿一个 80 类 COCO 预训练权重去训 3 类肉鸡状态,结果模型完全不收敛,还以为是学习率问题。正确的做法是:要么用官方在 COCO 上预训练的 backbone 权重做迁移学习,把检测头换成自己的类别数;要么直接用别人训好的肉鸡状态权重做微调。数据集目录一般长这样:
dataset/ ├── images/ │ ├── train/ │ ├── val/ ├── labels/ │ ├── train/ │ ├── val/ └── data.yamldata.yaml里写清楚train、val路径、nc类别数、names类别名。权重文件通常是.pt格式,放在weights/下。如果你拿到的权重是.pt但不知道类别顺序,可以用下面这段脚本读一下:
import torch # 加载权重文件,map_location 保证在无 GPU 环境也能读 ckpt = torch.load('weights/best.pt', map_location='cpu') # 模型结构里通常保存了类别名和类别数 model = ckpt['model'] print('类别数:', model.nc) print('类别名:', model.names)逻辑说明:torch.load把权重读成字典,model.nc和model.names是 YOLOv5 在训练时写进模型对象的属性。如果names是['healthy', 'sick', 'severe']这种,说明权重和你的任务对得上;如果是['person', 'bicycle', ...],那它只是 COCO 预训练权重,需要重新训检测头。参数上注意map_location,在 CPU 机器上读 GPU 训的权重必须加,否则会报 CUDA 相关错误。
2.3 数据量够不够:一个粗略的判断标准
肉鸡状态检测的数据集,我个人的经验是:每个类别至少 800 到 1000 个标注框,且要覆盖不同光照、不同密度、不同日龄。如果某个类别只有两三百框,模型大概率会偏向多数类。这时候要么补数据,要么用重采样和类别权重去平衡。另外,验证集不能只放同一天同一棚的图,否则指标虚高,上线就翻车。我一般会按棚舍和时间段切分,训练集和验证集来自不同天,这样验证指标才有参考意义。
3. 用 YOLOv5 训一版权重:从环境到推理的完整命令
3.1 环境准备与依赖安装
YOLOv5 对 PyTorch 版本有要求,太新或太旧都可能出玄学问题。我一般用 Python 3.8 到 3.10,PyTorch 1.12 到 2.0 之间。安装命令如下:
# 创建虚拟环境,避免污染系统 Python python -m venv yolov5_env source yolov5_env/bin/activate # Windows 用 yolov5_env\Scripts\activate # 安装 PyTorch,根据 CUDA 版本选对应命令,这里以 CUDA 11.8 为例 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 克隆 YOLOv5 仓库并安装依赖 git clone https://github.com/ultralytics/yolov5.git cd yolov5 pip install -r requirements.txt逻辑说明:虚拟环境是为了隔离依赖,避免和系统里其他项目冲突。PyTorch 的 CUDA 版本要和显卡驱动匹配,装错了会在训练时报CUDA error: no kernel image is available。requirements.txt里包含了 numpy、opencv、tqdm 等,装完可以用python -c "import torch; print(torch.cuda.is_available())"验证 GPU 是否可用。
3.2 修改 data.yaml 与模型配置
在data/下新建chicken.yaml,内容如下:
# 训练集和验证集路径,可以是绝对路径或相对 yolov5 根目录的路径 train: ../dataset/images/train val: ../dataset/images/val # 类别数和类别名,顺序要和标注文件里的 class id 一致 nc: 3 names: ['healthy', 'sick', 'severe']逻辑说明:nc必须等于names的长度,否则训练时会在计算损失时报维度不匹配。names的顺序决定了推理结果里类别 id 对应的含义,标反了会导致健康鸡被框成病鸡。路径建议用绝对路径,相对路径在不同工作目录下容易找不到文件。
3.3 启动训练:关键参数怎么设
训练命令我一般这样写:
python train.py \ --img 640 \ --batch 16 \ --epochs 100 \ --data data/chicken.yaml \ --weights weights/yolov5s.pt \ --cfg models/yolov5s.yaml \ --hyp data/hyps/hyp.scratch-low.yaml \ --name chicken_exp \ --cache逻辑说明:--img 640是输入分辨率,肉鸡个体在画面里如果比较小,可以提到 1280,但显存占用会翻倍。--batch 16是批大小,显存不够就降到 8 或 4。--epochs 100是训练轮数,小数据集 100 到 300 轮都常见,看验证集 mAP 什么时候不再涨。--weights指定预训练权重,用yolov5s.pt做迁移学习比从头训收敛快很多。--cfg指定模型结构,s 版最轻,适合边缘部署;如果精度不够可以换 m 或 l。--hyp是超参文件,低数据量场景用hyp.scratch-low.yaml里的强增强,能缓解过拟合。--cache把图片缓存到内存,加快读取,但数据集大时注意内存占用。
训练过程中重点看几个指标:box_loss和obj_loss是否稳定下降,mAP@0.5在验证集上的走势。如果obj_loss震荡厉害,可能是学习率太大或 batch 太小。如果mAP早早饱和然后下降,就是过拟合,需要加数据或加增强。
3.4 推理与导出:把权重用起来
训完之后,用detect.py跑单张图或整个文件夹:
python detect.py \ --weights runs/train/chicken_exp/weights/best.pt \ --source ../dataset/images/val \ --img 640 \ --conf 0.4 \ --iou 0.5 \ --save-txt \ --save-conf逻辑说明:--conf 0.4是置信度阈值,低于这个值的框不输出。养殖场场景我一般设 0.35 到 0.5,太低会误报太多,太高会漏掉病鸡。--iou 0.5是 NMS 的 IoU 阈值,控制重叠框的合并。--save-txt把结果存成 YOLO 格式的 txt,方便后续统计每张图里病鸡数量。--save-conf在 txt 里带上置信度,便于按置信度排序复核。
如果要部署到边缘设备,可以导出 ONNX 或 TensorRT:
python export.py \ --weights runs/train/chicken_exp/weights/best.pt \ --include onnx \ --img 640 \ --batch 1逻辑说明:--include onnx导出 ONNX 模型,--batch 1是推理时的批大小,边缘设备一般单张推理。导出后可以用 onnxruntime 加载,推理速度比 PyTorch 快不少。注意导出时的--img要和训练时一致,否则精度会掉。
4. 避坑与排查:那些让我返工三次的细节
4.1 标注框把整只鸡框成一条线
现象:训练 loss 一直不降,推理时框歪得离谱。原因:标注时用矩形框但拉得太扁,或者把多只鸡框在一个框里。YOLOv5 对宽高比极端的目标学习很差。解决:标注规范里明确要求框的宽高比在 1:5 到 5:1 之间,超出就重新标。多只鸡重叠时,分别框,不要合并。
4.2 验证集 mAP 很高但上线全是误报
现象:验证集 mAP@0.5 到 0.9,实际棚舍里跑,健康鸡被大量框成病鸡。原因:验证集和训练集来自同一时段同一棚,光照和背景几乎一样,模型学到了背景捷径。解决:按棚舍和时间切分数据集,验证集必须包含不同天、不同棚、不同光照的图。如果条件允许,留一个棚完全不做训练,只做测试。
4.3 训练到一半显存爆了
现象:CUDA out of memory,训练中断。原因:--img或--batch设太大,或者--cache把大量图片读进内存后显存碎片化。解决:先把--batch减半,再把--img从 1280 降到 640。如果还不行,去掉--cache,用--workers 4控制数据加载进程数。另外,训练前用nvidia-smi看有没有其他进程占着显存。
4.4 类别不平衡导致病鸡全漏
现象:健康鸡检测很准,病鸡和重度病态几乎检不出。原因:健康样本远多于病态样本,模型倾向于把不确定的框判成健康。解决:在data.yaml里给类别加权重,或者在超参里调cls损失系数。更直接的办法是过采样病态样本,把病态图片在训练集里复制多份。我一般会把病态样本至少补到健康样本的三分之一。
4.5 导出 ONNX 后精度掉一大截
现象:PyTorch 推理正常,ONNX 推理框位置偏移或类别错乱。原因:导出时--img和推理时输入尺寸不一致,或者 ONNX 的 NMS 实现和 PyTorch 不同。解决:导出和推理用同一个--img,并在 ONNX 推理脚本里手动实现 NMS,不要依赖导出时融合的 NMS。另外,检查--dynamic参数,边缘设备固定输入尺寸时不要开动态轴。
5. 把检测结果变成养殖场能用的报警:一个后处理技巧
训练和推理只是前半截,真正让这套东西在养殖场里跑起来,还得把检测框变成可行动的报警。我一般会在detect.py的输出基础上加一层后处理:按帧统计病鸡数量,连续多帧超过阈值才触发报警,避免单帧误报导致饲养员跑断腿。下面这段脚本读 YOLO 格式的 txt 结果,按图片分组统计:
import os from collections import defaultdict # 读取 detect.py 保存的 txt 结果,每行格式:class_id x_center y_center w h conf def count_sick_per_image(txt_dir, sick_ids=(1, 2), conf_thres=0.4): stats = defaultdict(lambda: defaultdict(int)) for fname in os.listdir(txt_dir): if not fname.endswith('.txt'): continue img_id = fname.replace('.txt', '') with open(os.path.join(txt_dir, fname), 'r') as f: for line in f: parts = line.strip().split() if len(parts) < 6: continue cls_id = int(parts[0]) conf = float(parts[5]) # 只统计病态类别且置信度超过阈值 if cls_id in sick_ids and conf >= conf_thres: stats[img_id][cls_id] += 1 return stats # 示例:连续 5 帧病鸡数超过 3 只就报警 def alarm_rule(stats, frame_order, sick_thres=3, consecutive=5): counter = 0 for img_id in frame_order: total_sick = sum(stats[img_id].values()) if total_sick >= sick_thres: counter += 1 else: counter = 0 if counter >= consecutive: return True, img_id return False, None逻辑说明:count_sick_per_image遍历 txt 文件,按类别和置信度过滤,统计每张图里病态个体的数量。alarm_rule按帧顺序检查,连续consecutive帧病鸡数超过sick_thres才报警。参数上,conf_thres我一般设 0.4,sick_thres根据棚舍密度调,比如每千只鸡设 3 到 5 只,consecutive设 5 到 10 帧,对应几秒钟的视频。这样能把单帧抖动过滤掉,报警准确率明显提升。
还有一个细节:如果摄像头是固定机位,可以加一个 ROI 掩膜,只检测棚舍地面区域,把走道和墙壁上的误检去掉。做法是在推理前把画面裁剪到有效区域,或者在后处理里按坐标过滤。这个技巧不复杂,但能省掉大量人工复核。
最后说个我自己的习惯:每次训完一版权重,我都会拿一段没参与训练的棚舍视频跑一遍,人工数一下漏检和误检,记在本子上。指标好看不代表现场好用,只有亲眼看过报警框落在哪只鸡身上,心里才有底。希望帮到你。
本文还有配套的精品资源,点击获取