简介:面向养殖场肉鸡检测需求构建的YOLO目标检测数据集,适合目标检测初学者、算法工程师及智慧养殖项目开发者使用。数据以鸡舍实景图片与对应标注为主,可直接用于YOLOv5、YOLOv7、YOLOv8等主流模型训练,支撑肉鸡定位、计数与养殖监控场景的算法验证。资源共1001个文件,压缩包约883.41MB,其中包含500张JPG图片、500个XML标注文件和1个TXT说明文件;JPG图片提供真实养殖环境样本,XML标注文件记录鸡只目标框位置,TXT文件可用于整理类别信息或完成训练配置,整体目录结构清晰,便于按JPG-XML对应关系快速切换不同检测框架。目前已有706人浏览学习,对需要快速获得实操数据集、搭建训练流程并评估检测效果的读者来说,是一份可直接落地的数据资源,可用于课程设计、算法对比或实际养殖监控项目的模型验证。
1. 从鸡舍到模型:YOLO养殖场肉鸡目标检测,瓶颈不在网络而在数据集
养殖场监控摄像头一天能回传上万帧画面,真正值得盯的却是死鸡、挤堆、采食异常这类偶发事件。肉鸡不像猪牛那样目标大、数量少,一栋鸡舍里几百上千只白羽鸡挤在垫料上,羽毛颜色跟麸皮垫料几乎一个色,人工盯着画面看三分钟就开始眼花。基于YOLO的养殖场肉鸡目标检测,本质上是把“找鸡”这件重复劳动丢给目标检测模型:用检测框把每只鸡从画面里捞出来,再往上游接计数、行为分析和异常报警。这个方向我接触过几个落地项目,一个共同的结论是——能不能跑通,决定性因素往往不是用v8还是v11、损失函数怎么调,而是手里有没有一套合格的养殖场肉鸡检测数据集。数据集的质量直接决定mAP上限,模型只是把数据集的水平兑现出来。
这篇文章按数据集的采集、标注、转换、训练、部署五个环节展开,给出一套可以直接抄作业的流程:怎么从RTSP拉流抽帧、怎么定标注规范、怎么把VOC XML转成YOLO的txt、训练时哪些参数值得动,以及部署时用TensorRT量化验证的实际边界。尤其适合两类人:一类是养殖场的技术负责人,想用YOLO做鸡只计数和健康监测;另一类是刚接触目标检测的初学者,正愁找不到一份能动手练手的真实数据集,想从零把“yolov8训练自己的数据集”这个流程走通。
2. 采集数据前先定规格:分辨率、光照与鸡群密度决定标注成本
2.1 从RTSP拉流到抽帧:视频怎么变成候选图片
养殖场如果已经有监控系统,最常见的做法就是直接从摄像机的RTSP地址拉流,把视频帧抽成图片。RTSP地址一般长这样:rtsp://192.168.1.64:554/Streaming/Channels/101,用OpenCV的VideoCapture就能直接读。我第一次做鸡舍数据采集时,直接拿cap.read()一帧帧存,三天攒了六万张几乎重复的图片,标注预算直接烧掉一半。后来改成按帧间隔抽帧,再把低信息量帧过滤掉,才把工作量降下来。
import cv2 import os rtsp_url = "rtsp://192.168.1.64:554/Streaming/Channels/101" cap = cv2.VideoCapture(rtsp_url) frame_interval = 30 # 每30帧取1帧,25fps视频约每秒1张 count = 0 save_dir = "raw_frames" os.makedirs(save_dir, exist_ok=True) while True: ret, frame = cap.read() if not ret: break if count % frame_interval == 0: filepath = os.path.join(save_dir, f"frame_{count:06d}.jpg") cv2.imwrite(filepath, frame, [cv2.IMWRITE_JPEG_QUALITY, 95]) count += 1 cap.release()代码的逻辑并不复杂:按帧计数器取模,只有落到frame_interval节点上的帧才落盘。frame_interval=30意味着在25fps的视频流里大约每秒保留1帧,这个密度对肉鸡这种运动幅度不大的目标足够。肉鸡大部分时间在采食、卧地或慢走,真正动作快的是受惊逃窜,那种瞬间在单帧里往往也是模糊的,标了反而给模型添乱。需要留神的是不要贪多,同样的机位、同样的光照、同样的鸡群密度,抽100帧和抽1000帧信息量差别不大;多样性来自时间段、天气和鸡群日龄,多换场景比多抽帧划算。
抽完帧后我会跑一个简单的去重:把连续帧缩到小尺寸算灰度直方图方差,相似度超0.95的直接删掉。这一步不复杂,但能去掉大量镜头静止时的重复帧,节省后面的标注工时。
2.2 光照、角度与背景控制:采错了后面全是返工
养殖场的实际环境比想象中难伺候。白天窗户光、晚上灯光、黄昏时的混合光,都在同一个画面里来回切换。最怕的是摄像头开启自动白平衡和自动曝光,鸡舍亮度一变,画面色彩跟着飘,这会给标注和训练同时埋坑。我一般会在采集前把相机参数固定下来:白平衡选“荧光灯”或“多云”对应的固定色温,曝光模式切到手动,快门速度固定在1/250秒以上避免运动模糊。如果你用的摄像头不支持手动改参数,就在采集后用脚本做一次颜色校正,让所有帧的鸡身白色尽量统一。
还有一个容易忽略的点是拍摄角度。鸡舍里的摄像头多半斜装在墙上或立柱上,俯视角度大约30度到60度之间,鸡只相互遮挡非常严重。如果条件允许,优先选接近垂直向下的角度,检测框的重叠率会明显下降。没有条件改机位的话,就靠标注规则和增强来弥补,后面章节会专门讲。背景方面,垫料颜色和鸡羽毛颜色本来就接近,我倒不建议刻意换垫料,反而应该在数据里保留足够多的垫料类型变化,让模型学会区分。
提示:不要把所有历史视频一股脑全采下来当数据。先看一个摄像头的24小时录像,把光照、鸡群密度、人员走动这几个维度列出来,再决定每个时段要抽多少帧,比例按“白天40%、黄昏20%、夜间灯照40%”这种梯度去分配,避免夜间样本太少导致的偏差。
2.3 类别定义与数据量预估:别急着上多分类
很多第一次做养殖检测的人上来就想分“正常鸡、病鸡、死鸡”三类。这个思路在业务上没错,但落到数据集上非常容易翻车:死鸡和病鸡的样本数量天然稀少,一万帧里未必找得到50只,类别不平衡会让模型直接把这两类当噪声忽略掉。我现在的做法是数据集阶段只建一个“chicken”类别,把鸡只个体检测做扎实;死鸡、病鸡这类状态判断,放到检测结果之上用行为分析和时序逻辑去做——比如同一位置长时间不移动、周围鸡群密度异常,这些都不需要单独训练一个稀疏类别。
数据量方面,有一个经验公式可以参考:单场景单机位下,2000到3000张干净标注图足够让YOLOv8s的mAP50跑到0.7以上;低于1000张,过拟合和漏检都会很明显。需要重点保证的是“小目标”的比例——也就是640分辨率下边长小于32像素的鸡只框,至少占到总框数的10%到15%。如果全是近景大鸡,模型在远视角场景里会漏得没法看。先按这个标准去抽帧、筛选,再进入标注阶段。
3. 用LabelImg标注肉鸡:密集场景的标注规范与一致性检查
3.1 标注工具选型:LabelImg和labelme怎么选
标注工具我一般只在两种里选:LabelImg和labelme。LabelImg输出的是Pascal VOC格式的XML,通过脚本转YOLO的txt很顺;labelme输出JSON,适合做分割标注,但如果只做框检测就有点绕。对于肉鸡目标检测,直接选LabelImg,安装很简单:
pip install labelImg labelImg启动前先把类别写进classes.txt,放在标注保存目录下。如果只用“chicken”一个类,文件里写一行就够了。注意这个文件的行号顺序就是YOLO训练时的类别索引,比如0对应第一行。标注中途千万不要改这个文件的顺序,否则之前标的所有txt标签全部错位——这个错位并不会在训练时报错,模型会默默学会一个错乱的映射,等你发现时已经浪费了好几天。
echo chicken > classes.txt代码本身没有复杂逻辑,但有一个细节值得说:类别的名称和顺序要在标注第一天、第一张图就定死。你可以后面再加新类别,但千万别删改已有类别的顺序。这是个血泪教训。
3.2 密集场景下的边界框规则
肉鸡挤在一起时,边界框互相重叠是常态。标注规则不提前定清楚,两个人标出来的框风格能差出一大截。我这边长期用的规则是三条:
第一,只要鸡的头部或躯干主体露出超过三分之一,就算一只独立鸡,必须单独画框;第二,两只鸡重叠时,边界框各自贴着自己的可见轮廓,不为了“避让”而故意缩小;第三,如果一只鸡只剩头露在外面,躯干完全被挡住,仍然要标,因为计数场景里漏掉一只和错把一只当两只一样严重。
这个规则听起来简单,实际执行起来很容易走偏。我给标注员的建议是先拿10张密集图试标,我来检查一遍再批量开工。检查的标准也很朴素:把标注框渲染回图片上看,框的边缘如果大面积压在鸡身内侧或明显包住旁边的鸡,就说明规则没执行到位。标注产生的框会直接影响后续YOLO的anchor匹配和边界回归,框偏了五个像素,在小目标上的IoU损失可能就超过0.1。
3.3 一致性检查:把标注误差控制在合理范围
标注完成不等于数据可用。我习惯每标完一批就做一个快速体检,主要看三样东西:
import os from collections import Counter label_dir = "labels/train" counter = Counter() empty_files = [] for name in os.listdir(label_dir): if not name.endswith(".txt"): continue filepath = os.path.join(label_dir, name) with open(filepath, "r") as f: lines = f.readlines() counter[len(lines)] += 1 if len(lines) == 0: empty_files.append(name) print("标注框数分布:", counter.most_common()) print("空标签文件:", empty_files[:20])这段脚本读的是YOLO格式的txt标签目录,统计每张图标注了几个框,以及有没有空文件。标注框数分布能直观反映数据质量:如果大部分图都只有1到2个框,只有少数图有几十个框,说明采集阶段选帧偏向稀疏场景,密集样本不够,训练出来的模型遇到高密度画面会直接崩溃。空标签文件则要单独看,如果空文件对应的图片里确实没有鸡,那是正常的负样本;如果有鸡但没标,那就是漏标,必须补上。
除了数量,还要看尺寸。我会写个脚本统计所有标注框的宽高,按像素尺寸分桶。正常的话,框的尺寸分布应该覆盖从十几个像素到几百个像素的连续区间;如果小框占比非常低,说明标注员习惯性放大边界,把两只靠近的鸡吞并进一个大框——这种错误对密集场景的破坏性极大,务必要在训练前纠正。
注意:标注质量检查一定要在数据划分之前做。如果划分完训练集和验证集再发现标注问题,修完还得重新划分,否则同一摄像头的相邻帧会同时出现在两边,模型的mAP虚高,部署时立刻现原形。
4. 转成YOLO格式:目录结构、转换脚本与数据增强
4.1 标准目录结构与data.yaml
拿到一批标注好的XML后,第一步是搭目录结构。Ultralytics YOLO的标准结构是images和labels两个根目录,各自下面分train、val、test三份。图片和标签一一对应,靠文件名前缀关联,比如frame_000012.jpg对frame_000012.txt。同名文件必须成对出现,光有图片没有标签会报错,光有标签没有图片则会在数据加载阶段给人感觉像中邪一样难排查。
path: /home/user/ychicken_dataset train: images/train val: images/val test: images/test nc: 1 names: ['chicken']path字段建议用绝对路径。train、val、test都是相对于path的子目录路径,nc是类别数,names的列表顺序必须跟标注时classes.txt的顺序一致。整个yaml文件就这么点东西,但它决定了训练脚本能不能正确找到数据,写错一个路径都不会有人帮你发现,模型会直接报“Dataset not found”之类的错,很多人会卡在这一步很久。
4.2 VOC XML转YOLO txt:转换脚本与四个边界坑
LabelImg默认存成Pascal VOC XML,YOLO训练需要的是归一化后的txt。转换脚本不复杂,但四个边界情况要处理好:坐标越界、空标签、图片尺寸读取失败、类别名不匹配。
import xml.etree.ElementTree as ET import os def xml_to_yolo(xml_path, out_dir, class_map): tree = ET.parse(xml_path) root = tree.getroot() img_w = int(root.find("size/width").text) img_h = int(root.find("size/height").text) lines = [] for obj in root.findall("object"): name = obj.find("name").text if name not in class_map: continue cls_id = class_map[name] bndbox = obj.find("bndbox") xmin = float(bndbox.find("xmin").text) ymin = float(bndbox.find("ymin").text) xmax = float(bndbox.find("xmax").text) ymax = float(bndbox.find("ymax").text) # 坐标越界保护 xmin = max(0, min(xmin, img_w - 1)) ymin = max(0, min(ymin, img_h - 1)) xmax = max(0, min(xmax, img_w - 1)) ymax = max(0, min(ymax, img_h - 1)) if xmax <= xmin or ymax <= ymin: continue cx = (xmin + xmax) / 2 / img_w cy = (ymin + ymax) / 2 / 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}") out_path = os.path.join(out_dir, os.path.splitext(os.path.basename(xml_path))[0] + ".txt") with open(out_path, "w") as f: f.write("\n".join(lines)) class_map = {"chicken": 0} # 遍历某个目录下所有XML,逐个调用 xml_to_yolo转换脚本的核心是坐标归一化:把xmin、ymin、xmax、ymax转成中心点坐标加宽高的形式,并除以图片宽高。越界保护那段很关键,因为手动标注时鼠标拖出边界是很常见的事,XML里会出现比图片尺寸还大的坐标值,不处理的话训练时损失计算会出现负值或超范围索引。空标注的情况也要考虑——如果一张图确实没有鸡,转换出来的txt应该是空文件,而不是不生成文件,这样数据加载时才不会读到缺失标签。
四个常见坑里,最隐蔽的是类别名不匹配。XML里写的是“chicken”,dict里的键也是“chicken”,看起来没问题,但如果有哪张图的XML里多打了个空格或者大小写不同,这只鸡就会被静默跳过,训练时那个样本变成空标签。我的习惯是转换完扫一遍:统计每张图的标签行数,和XML里的object数量比对,不一致的单独列出来查。
4.3 增强策略:mosaic、HSV和样本重复的取舍
数据集转完格式,进入训练前的增强配置。Ultralytics的默认增强参数在大多数场景下够用,但密集鸡群场景需要做两个改动。一是控制mosaic概率,二是调整HSV的扰动强度。
mosaic: 0.3 mixup: 0.1 hsv_h: 0.015 hsv_s: 0.4 hsv_v: 0.3mosaic把四张图拼在一起训练,能有效提升模型对遮挡和小目标的鲁棒性,但在鸡只这种密集排列的目标上,mosaic概率太高反而会让模型学到“框内混着半只鸡”的奇怪模式,所以我一般压在0.3以下。mixup同理,设成0.1意思一下就好。HSV的扰动参数我调得比较保守:色相偏移0.015、饱和度0.4、明度0.3,因为鸡身颜色本来就只有白、黄白、少量杂色,扰动过头会让模型把紫色也当成鸡。
增强阶段还有一个常被忽略的操作是“样本重采样”。如果密集场景的图片太少,我会在训练配置里给它们加权,或者在数据准备阶段复制几份。复制不改变信息量,但它能让模型在同一个epoch里多看见几次密集样本,效果比单纯调mosaic更直接。反正我自己在这个坑上翻过车——默认增强参数训出来的模型,稀疏场景表现很好,一遇到全是鸡的帧直接漏掉一半。
5. 避坑指南:密集鸡群训练的5条踩坑记录
5.1 小目标漏检严重:loss在降但mAP50卡在0.4
现象:训练时loss曲线一路下降,看起来一切正常,但验证集上的mAP50始终徘徊在0.4左右,尤其远角画面里的鸡几乎全部漏检。
原因:图像分辨率把看远角的能力压没了。YOLO默认训练尺寸是640×640,如果原图是1080p,缩到640后远处的鸡可能只有10×10像素,特征图上一个点都分不出来。再加上标注数据里小目标占比不足,模型根本没有机会学到这个尺度上的模式。
解决:先把训练分辨率提到960或1280,ultralytics的imgsz参数直接改960,对显存要求不高的话优先选1280。同时增强小目标样本的占比,用前面提到的重采样或者裁剪放大局部区域。这两个动作做完,mAP50通常能拉到0.6以上。如果还卡着,再去查标注框是不是把密集区域合并成了大框。
5.2 昼夜切换后漏检率暴涨
现象:白天训练完的模型在晚间灯照下跑,漏检率从3%跳到30%,检测框还特别自信,置信度普遍高于0.8。
原因:训练集里夜间画面占比太低,模型把“日光下的鸡身颜色”学成了鸡的充分必要条件。夜间灯照偏黄偏暖,鸡身上反射的颜色跟白天差两个色温,模型没见过这种分布。
解决:采集阶段就必须按时间段配比,白天、黄昏、夜间灯照各保证一定比例,夜间样本至少占15%到20%。模型训练阶段不要靠拉大HSV扰动来硬扛——那会让模型把“色彩宽容度”拉到自己都分不清的程度,宁可把不同时段的样本按比例配好,让模型自己学出不同光照下的形态。
5.3 垫料和饲料被当成鸡
现象:模型在鸡舍里跑出大量误检框,尤其集中在垫料结块、饲料颗粒边缘。单看置信度还不低,滤都滤不掉。
原因:肉鸡羽毛颜色和浅色垫料太接近,模型学到的“鸡”特征里掺进了背景纹理。如果负样本不够或者标注框边缘贴得太松,模型很容易把靠近鸡身的背景纹理一并学进去。
解决:数据里必须有一定比例的“只含垫料、不含鸡”的负样本,让模型有机会学到“没有鸡”这个分支。标注时框紧贴鸡身轮廓,别留一圈背景。部署时把置信度阈值从默认的0.25调到0.35到0.4,能滤掉一批背景误检。我用的一个土办法是统计误检框的尺寸分布,如果特别集中在固定大小区间,多半是垫料纹理,可以通过后处理按尺寸区间过滤。
5.4 多人标注的边界漂移
现象:换了个标注员之后,验证集的loss突然波动变大,mAP忽高忽低,重训两次结果都不一样。
原因:不同标注员对“这只鸡是否可见”“遮挡到什么程度还要不要标”的理解不一样。一个标成全框,一个只标可见部分,造成边界框尺寸分布不一致,训练时模型来回适应两种标准,收敛自然不稳。
解决:把标注规范写成一页纸的Checklist,每人开工前先标5张,统一检查后再放量。我还会定期抽检已经标完的数据,把同一个人前后期标注风格差异控制在合理范围内。这个工作不能省,多人协作标注成本低,但一致性成本高,越早定标准越省事。
5.5 预训练权重直接套用不生效
现象:用COCO预训练权重直接跑自己的鸡舍数据集,验证集loss很低,但实际视频流里几乎什么都检测不到,或者输出一堆乱框。
原因:COCO数据集里没有鸡,预训练权重学的是80个通用类别的特征,直接微调时模型把“鸡”的特征映射到已有特征空间的角落里,看起来收敛了,实际上泛化极差。
解决:从零预训练不现实,但可以冻结前10层、只训练后面层。用freeze=10这个参数,让模型先用预训练权重里的低层纹理和边缘特征,再重新学高层语义。还有一个更稳的路径:先用少量公开家禽数据集做一次中间预训练,再切到自己的数据微调。步骤多一步,效果通常比直接套COCO权重好不少。
注意:以上五条是我在这个场景里反复踩过的经验,但数据集的坑远不止这么多。有一条通用的排查思路——模型表现不正常时,先怀疑数据,再怀疑参数,最后才怀疑网络结构。绝大多数“看起来像模型问题”的怪现象,最后都查到数据头上。
6. 部署前的最后验证:TensorRT跑多路,先看mAP再看速度
6.1 FP16序列化与批处理测速
模型训练完进入部署,我习惯先转TensorRT的FP16引擎并在T4或类似推理卡上做一次实测。网上经常有人问“T4 1080p25帧每秒用TensorRT YOLO 640分辨率检测能支持多少路”,答案其实取决于引擎的批处理配置和预处理开销,不是简单一个数。我的测法很笨但可靠:用实际RTSP流解码出来的帧做输入,跑一轮带前后处理的完整流程,记录单路处理时间,再按25帧每秒的标准反推路数。
import tensorrt as trt logger = trt.Logger(trt.Logger.WARNING) with open("best_fp16.trt", "rb") as f: runtime = trt.Runtime(logger) engine = runtime.deserialize_cuda_engine(f.read()) context = engine.create_execution_context() # 输入尺寸必须与训练时的imgsz一致 input_shape = (1, 3, 640, 640) output_shape = (1, 25200, 7) # 输出数量与模型结构相关,需实际查询这段代码只是加载引擎和创建执行上下文,真正的关键在形状匹配。输入尺寸、输出张量的形状都必须在引擎序列化时确定,直接拿默认值跑会有各种报错和乱结果。实际部署时我不会把预处理和后处理放在Python里做,而是用GPU端到端处理,否则CPU上的缩放和归一化会成为瓶颈,单路都跑不满25帧。
6.2 用PR曲线校准置信度阈值
速度之外,部署前还要做一道验证题:用验证集跑一遍PR曲线,根据业务需求选置信度阈值。养殖场景里漏检一次可能就意味着死鸡没被及时发现,所以我的习惯是阈值往低定,0.2到0.25之间,宁可多几个误检也不漏。这个选择跟“精准优先”的通用目标检测经验相反,但业务场景说了算。
验证命令很简单:
yolo detect val model=best.pt data=data.yaml split=val conf=0.001 iou=0.6conf=0.001的意思是把置信度阈值压到最低,让模型把能检的都检出来,这样才能看清召回率上限。观察PR曲线时重点看召回率在0.8到0.9之间时精度的下降斜率,如果掉得太快,说明模型有不少低置信度正确框,部署阈值定低是合理的。
我自己的经验是第一次做鸡只检测时,数据集时段划分没做好,模型在夜间灯照下漏检率飙升,折腾了半个月才发现是训练集里夜间样本不够。后来把采集和标注规范补齐,同样一个模型,漏检率从30%压回5%以内。整个过程最深的体会是:YOLO本身很成熟,真正决定上限的是数据集的覆盖度和标注一致性。希望这篇笔记能帮你少走这些弯路,把养殖场肉鸡目标检测真正落到自己的监控系统里。
本文还有配套的精品资源,点击获取