
简介面向家禽养殖智能化场景的鸡只状态图像数据集用于正常与异常鸡只的自动识别适合目标检测、图像分类方向开发者及养殖监控项目使用可服务于养殖场自动化巡检与家禽健康预警等场景。数据以图像与COCO格式标注为核心压缩包共2000个文件其中1997张JPG图片为鸡只状态样本3个JSON文件提供标准化的目标框与类别标注整体约451MB可直接用于主流深度学习框架的数据准备与模型训练。该数据集平均正常识别率约91.8%可作为模型效果基线参考支持异常状态早期发现与日常健康巡查对后续算法调优具有实际参考价值。目前已有410人学习下载图片文件命名规范包含前缀编号便于按需划分训练集与验证集结合内容预览可见整套数据适合作为鸡舍状态监控、家禽健康管理等方向的基础训练数据能帮助学习者快速开展鸡只行为分析或异常检测实验减少从零采集标注的工作量。1. 拿到家禽鸡状态数据集先看3749张图和91.8%准确率背后的东西养鸡场装摄像头容易让摄像头看懂鸡有没有问题才是难点。鸡不会说话精神萎靡、缩脖子、不动弹这些异常状态靠人盯监控屏迟早看花眼。我这次拆的家禽鸡状态数据集做的就是这件事3749张训练集图片标注了正常鸡和异常鸡两类目标用的coco json格式跑出来的平均正常识别率在91.8%左右。适合谁用做养殖监控的算法工程师、搞农业物联网毕设的学生、以及手里有鸡场视频但苦于没有现成标注数据的人。这份数据集的价值不在于图片数量有多惊人而在于它是直接拿真实养殖场景的监控视角拍的背景脏、光照乱、鸡群互相遮挡这些恰恰是实际部署时要面对的硬条件。拿到手先别急着训把标注格式吃透再动手能省下后面一大半返工时间。2. 数据集结构拆解目录布局、两类样本与coco json字段2.1 解压后先看什么目录布局和文件命名规律这份数据集下载解压之后建议先别直接灌进训练脚本花两分钟把目录结构摸清楚。常见做法是images目录下放图片annotations目录下放json标注文件训练集、验证集、测试集要么分文件夹要么通过json里的划分字段来区分。拿这份鸡状态数据集来说3749张图片是训练集的量里面同时包含正常鸡和异常鸡的实例验证集和测试集会单独有一套图片和对应的标注json。文件命名一般有两种习惯一种是图片名和json文件名一一对应比如IMG_0001.jpg对应IMG_0001.json另一种是整体一个大json里面通过image_id字段关联所有图片。你拿到的这份如果按前者组织那训练时按文件名遍历就行如果是后者就得在代码里维护一个image_id到文件路径的映射表。我建议先写一段三五十行的小脚本把json里的图片数量和annotations数量扫一遍确认3749这个数字对得上。数字对不上说明可能是压缩包传输丢文件或者是json里混进了脏数据这种问题越早发现越好处理。2.2 coco json里究竟存了什么从info到annotationscoco json标注格式是目标检测领域最常见的数据交换格式之一结构上分五块info、licenses、images、annotations、categories。对训练有实际影响的只有后三块。images是一张大表每行记录一张图片的file_name、height、width、idannotations是标注实体的列表每个标注对象里包含image_id、category_id、bbox、area、iscrowd这些字段categories定义了类别编号和名称的对应关系。这条鸡状态数据集里categories应该只有两个类比如normal_chicken和abnormal_chicken分别对应类别id 0和1。bbox字段是[x, y, width, height]x和y是框左上角坐标width和height是框的宽高单位是像素没有做归一化。这里有个很容易踩的坑有的数据集bbox是[x_center, y_center, width, height]或者[x_min, y_min, x_max, y_max]原始coco标准是左上角坐标加宽高但很多第三方工具在导出的过程中悄悄改了定义。拿到手先随便挑一张图把bbox画上去看一眼比读一百行文档都管用。2.3 类别怎么分布正常鸡和异常鸡各占多少类别不平衡是养殖类数据集的通病。正常状态的鸡占大多数异常状态的鸡往往只出现在角落里或者单独一个小框数量能差出好几倍。这份数据集如果正常类占明显大头训练出来的模型会对异常类不敏感漏检率偏高。我的习惯是写段几行的统计脚本扫annotations把每个类的实例数打印出来同时看一眼bbox面积的分布。bbox面积分布也很值得关注。如果异常鸡的框普遍很小说明这些样本大多拍摄距离远、目标占比低对模型的细粒度识别能力要求更高。如果还有大量被鸡群互相遮挡的局部框那训练时就要在loss里考虑遮挡场景的影响。统计完了这两个维度再决定训练参数比如是否需要给异常类加loss权重、是否要调整mosaic增强的开启时机这比拿到数据直接跑默认参数靠谱得多。3. 把coco json转成YOLO格式类别映射与坐标归一化脚本3.1 为什么在YOLO训练流程里必须先做格式转换Ultralytics YOLO系列默认读的标注格式是每张图片对应一个同名txt文件每行一个目标格式是class_id x_center y_center width height其中四个坐标值全部相对于图片宽高做了归一化。而这份鸡状态数据集给的是coco json坐标是像素绝对值类别是category_id。格式不转换YOLO训练器根本读不了报错通常是Dataset not found之类但真正的原因往往是标注文件对不上。有一个细节值得注意coco json里的category_id和YOLO的class_id不一定一致。coco允许category_id从1开始编号而YOLO的class_id必须从0开始连续编号。这份数据集里如果category_id是1和2那转换时要减1如果已经是0和1那直接映射就行。不检查这步就直接转会出现所有框的类别整体错位一个号训练的时候loss能降但预测结果全错。3.2 转换脚本解析json输出txt附关键参数我一般会写一个独立的coco2yolo.py脚本而不是在训练脚本里内联转换逻辑因为转换只跑一次但调试的过程可能要跑好几轮。下面这个脚本按coco标准格式解析输出YOLO txt文件同时生成一个classes.txt记录类别名。import json import os from pathlib import Path def convert_coco_to_yolo(json_path, img_dir, out_dir): # 读取coco json解析images和annotations两张表 with open(json_path, r, encodingutf-8) as f: coco json.load(f) # 建立image_id - 文件名的索引 image_map {img[id]: img for img in coco[images]} # 建立category_id - class_id的映射coco的id可能从1开始 # 这里按categories列表的顺序重排保证class_id连续 category_map {} for idx, cat in enumerate(coco[categories]): category_map[cat[id]] idx # 按图片聚合所有标注框 anns_per_img {} for ann in coco[annotations]: img_id ann[image_id] anns_per_img.setdefault(img_id, []).append(ann) os.makedirs(out_dir, exist_okTrue) # 逐张图片写txt标注文件 for img_id, anns in anns_per_img.items(): img_info image_map[img_id] img_w, img_h img_info[width], img_info[height] # 输出文件名与图片名同前缀后缀换为txt txt_name Path(img_info[file_name]).stem .txt lines [] for ann in anns: cls_id category_map[ann[category_id]] x, y, w, h ann[bbox] # coco格式左上角坐标宽高 # 归一化x_center x w/2再除以图片宽 x_center (x w / 2) / img_w y_center (y h / 2) / img_h w_norm w / img_w h_norm h / img_h # 裁掉超出图像边界的坐标YOLO训练要求数值在0到1之间 x_center min(max(x_center, 0.0), 1.0) y_center min(max(y_center, 0.0), 1.0) w_norm min(max(w_norm, 0.0), 1.0) h_norm min(max(h_norm, 0.0), 1.0) lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w_norm:.6f} {h_norm:.6f}) with open(os.path.join(out_dir, txt_name), w, encodingutf-8) as f: f.write(\n.join(lines)) # 顺手写一个类别清单文件YOLO训练时能对应上 with open(os.path.join(out_dir, classes.txt), w, encodingutf-8) as f: class_names [cat[name] for cat in coco[categories]] f.write(\n.join(class_names)) print(f转换完成{len(anns_per_img)} 张图片{len(coco[annotations])} 个目标框) if __name__ __main__: convert_coco_to_yolo( json_pathannotations/instances_train.json, img_dirimages/train, out_dirlabels/train )脚本的要点在三个地方。第一category_map按categories列表的顺序重建class_id而不是直接照抄category_id这能避免类别编号不连续导致YOLO训练报错。第二归一化公式是(x w/2)/img_w转换前确认bbox的坐标系定义这里假设coco标准左上角坐标加宽高如果你的数据源是别的格式改这一行就行。第三边界裁剪不能省监控画面里鸡框偶尔会贴边标注时没裁干净转出来数值会超过1.0Ultralytics训练器默认不做容错处理必报错。3.3 转换后必须做的一轮可视化抽查转换脚本跑完别急着开训练。下一步是把txt标注画回图片上和原图叠在一起看。这一步是血泪经验换来的坐标公式错一个符号、宽高顺序写反、归一化除以了宽而不是高直接看画框结果全都能暴露出来。import cv2 def draw_yolo_labels(img_path, label_path): img cv2.imread(img_path) h, w img.shape[:2] with open(label_path, r) as f: for line in f: cls_id, xc, yc, bw, bh line.strip().split() xc, yc, bw, bh float(xc), float(yc), float(bw), float(bh) # 从归一化坐标换算回像素坐标 x1 int((xc - bw / 2) * w) y1 int((yc - bh / 2) * h) x2 int((xc bw / 2) * w) y2 int((yc bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.imshow(check, img) cv2.waitKey(0)抽查数量不用多训练集里随机抽10到15张就行但要有意识地覆盖几种情况鸡数量密集的大图、鸡在画面边缘的图、光线暗的图。重点看框是不是贴着鸡身、有没有框跑到无关背景上、有没有明显漏标的小鸡。如果框整体移位检查归一化公式如果某些图完全没框去查jpg文件名和json里的file_name是否对得上八成是文件名前缀有差别。4. 训练与评估YOLOv8在3749张图上的参数设置4.1 数据集yaml配置与模型选型格式转换完成后需要写一个数据集yaml文件告诉Ultralytics训练器图片路径、标签路径和类别清单。这个文件路径不能有中文也不能放在有权限限制的目录下Windows用户特别容易在C盘用户目录下翻车。# chicken_state.yaml path: /home/user/chicken_status # 数据集根目录 train: images/train # 训练集图片相对于根目录的路径 val: images/val # 验证集图片路径 nc: 2 # 类别数正常鸡、异常鸡 names: 0: normal_chicken 1: abnormal_chicken模型选型上训练集只有3749张图属于中小规模数据集不需要直接上yolov8x这种大模型。小模型的拟合速度更快显存占用更低在边缘设备上部署也更现实。一般这类小目标检测场景yolov8s和yolov8m是平衡点s训练快适合先跑通全流程m精度略高适合最终部署。如果后续要落地到树莓派或者Jetson这样的低算力设备yolov8n也不是不能考虑但漏检率会上去鸡群密集的场景尤其明显。4.2 训练命令和关键超参数说明跑训练之前先确认ultralytics包版本不同版本的默认参数有差异。训练命令看起来简单真正决定结果的是那些不会自动调节的超参数。yolo train \ modelyolov8s.pt \ datachicken_state.yaml \ epochs100 \ imgsz640 \ batch16 \ patience20 \ lr00.001 \ augmentTrue \ seed42epochs设为100在这个数据量下偏保守我一般先跑100轮看收敛曲线如果验证集loss在60轮左右就不再下降说明训练充分了再多只是过拟合。patience20表示验证集指标连续20轮不提升就提前停止这个参数比手动盯着loss曲线省事得多。imgsz640是速度和精度的折中如果标注框普遍很小可以考虑imgsz960但要留意显存占用。batch16在12G显存上基本是yolov8s的上限8G显存就降到8不然OOM中断很浪费训练进度。数据增强这里要单独说。Ultralytics默认开了mosaic和mixupmosaic把四张图拼成一张训练对小目标检测帮助很大但也会让模型过度适应拼接后的图像分布。养殖场监控画面鸡群密集mosaic增强产生的拼接边界容易被模型误学。我一般会在训练中期观察一下发现mAP上不去反而降就先关掉mosaic或者把mosaic的启用概率从1.0降到0.5。4.3 结果文件里先看哪几个指标训练结束后runs/detect/train下会生成result图、confusion_matrix图、PR曲线和一批验证集上的预测样例图。先看confusion_matrix确认正常类和异常类没有被互相混淆。如果异常类大量被预测成正常类说明类别不平衡问题比想象的严重要回去给异常类加loss权重。再看PR曲线重点关注AP50和AP50-95两个值。AP50是IoU阈值0.5下的平均精度AP50-95是多个IoU阈值的平均后者更能反映框回归的精度。如果AP50有90%但AP50-95只有60%说明框的位置大致对但不够贴合这种模型在实拍场景里会表现为框偏大或偏小。最后翻一遍验证集预测图重点看漏检的样例理解哪些场景是模型的高频失误点。正常类平均识别率91.8%这个基线指的应该是在这种评估口径下的结果你复现时跑出来的数字围绕这个值浮动是正常的。5. 避坑coco转yolo最常见的四个翻车点5.1 现象全部bbox画出来偏到角落第一次做完转换验证时发现每个框都跑到图片左上角放大看是一个一个的小色块。原因几乎可以锁定在坐标换算上coco的bbox第3、4个字段是width和height转换脚本里误当成了x_max和y_max于是画框时用了(x, y, xw, yh)直接画画出来的框全部偏移。解决方法是回到原始json看一串bbox的值随便挑一个验证宽度是否等于x_max减x_min其实coco官方的定义文档里写得很清楚但手动复核一下比文档可靠。5.2 现象训练时报class mismatch训练启动几秒就报错提示类别数量对不上或者加载annotation时找不到class id。原因通常是yaml文件里的nc和names顺序与txt标注里的class_id不一致比如txt里写了class_id2但yaml里nc2的合法id只有0和1。解决方法是跑一遍labels目录的扫描统计所有txt文件里出现的最大class_id值如果超过nc-1说明转换脚本里的category_map写错了。另一个容易忽略的原因是classes.txt的顺序和yaml里的names顺序不一致代码里读取labels时按这两个文件各自独立的顺序映射结果错位。5.3 现象验证集mAP高但实拍视频漏检模型在验证集上表现很好mAP到90%以上但拿实拍视频测试时漏检严重。验证集的图片往往是从训练视频中抽帧选的和训练集同源背景、光照、鸡的姿态都高度相似指标虚高很正常。现实场景里监控探头位置变了、光线方向变了、鸡群密度变了模型就露馅。解决这个问题没有捷径只能多收集不同时段、不同角度、不同天气的图补进训练集。如果一时间拿不到更多数据至少把训练时的随机遮挡、亮度扰动、平移增强开到更强的档位让模型见过更多变体。5.4 现象训练中途OOM中断前面白跑训练跑到30多轮显存突然撑爆程序直接退出断点续训也没来得及配。原因一般是验证阶段的前向推理临时占了额外显存你把batch设到了刚刚好卡在显存上限的档位。解决方法是batch从16降到12或者开amp混合精度训练显存占用能掉将近一半。还有一个容易被忽略的点imgz640时显存占用峰值可能出现在验证阶段而不是训练阶段因为训练有梯度释放机制而推理没有所以别盯着训练阶段看显存等它跑完第一个epoch验证阶段再看。6. 把这份数据集用透增量标注和基线复现6.1 用训练好的模型做预标注人工只改错3749张图训练完的模型精度已经能用了但要让它在你的场地上更准得扩数据。我一般会做一轮预标注人工纠错拿训练好的yolov8s对另一批新拍的视频抽帧预测把预测结果保存成coco json或直接转成YOLO txt再打开标注工具把错标、漏标的框改掉。这样新数据的标注成本能砍掉七八成。会漏检的通常是异常鸡因为这类样本本来就少模型对它的特征学得不够完善预标注时要把这类框单独筛出来优先处理。yolo detect predict \ modelruns/detect/train/weights/best.pt \ sourcenew_frames/ \ save_txtTrue \ save_confTrue \ conf0.25这个预测命令里save_txtTrue会把每个框的归一化坐标写进txt格式和YOLO训练标签一致可以直接拼到旧labels里。save_confTrue会把置信度也写进txt的第五个位置但训练时YOLO不读这个字段。你如果想要合并进原训练集需要把预测txt的置信度字段去掉或者先转回coco格式再统一处理。conf阈值用0.25还是0.5取决于漏检率和误检率的权衡实际标注时我会先用0.25多出一些候选框人工删比人工画省事。6.2 复现91.8%基线验证路径和评估口径有了这份数据集复现91.8%这个数字本身也是一种能力验证。复现时注意评估口径要一致确认验证集图片是否参与过训练、类别权重是否做过特殊处理、置信度阈值用的是多少。如果验证集是随训练集一起打乱划分的那这个91.8%代表的是模型在见过的环境上的表现正如前面说的实拍场景里数字会低一些。另一种做法是把验证集改成完全不参与训练的鸡场新场景这样跑出来的才是真正可部署的参考值。6.3 数据增强参数的边界在3749张图的规模下增强是把双刃剑。合理的增强等于免费扩数据增强过度等于给模型看大量虚构的鸡群形状。我的做法是固定随机种子同一份数据分别用默认增强和增强减弱两个配置各跑一版对比验证集结果再决定最终配置。如果加了增强后AP50-95反而掉说明原始标注的质量高于合成的多样性这时候优先补高质量新图比折腾增强参数更有价值。从那以后我每次拿到新数据集都会先在训练前把所有配置参数、标注格式、类别映射写进一个实验记录文件等训练完再翻回去看时很多当时以为玄学的结果都能找到具体原因。希望帮到你这套流程用顺手之后换到任何数据和任何检测模型都能少走弯路。本文还有配套的精品资源点击获取