猪只目标检测数据集:VOC+YOLO双格式,含红外/遮挡/小目标真实场景
发布时间:2026/10/1 3:15:43来源:尧图网络
简介本资源是面向农业AI与智能养殖领域的高质量猪只目标检测数据集适用于计算机视觉初学者至算法工程师开展YOLO、Faster R-CNN、CenterNet等主流检测模型的训练与验证。数据源自真实养猪场监控实拍覆盖3万余只猪个体涵盖多种姿态、密度与光照场景支持行为分析、健康状态识别等二次开发任务。压缩包共2000个文件999个XML标注文件对应VOC格式1001个TXT文件对应YOLO格式总大小911.17MB标注由人工使用LabelImg精细完成无漏标可直接加载训练。目前已有368人学习下载资源提供开箱即用的双格式标签、丰富背景图像及典型猪只命名样例如pig_41_2.txt显著降低数据预处理门槛助力快速构建端到端检测 pipeline。1. 猪场监控实拍数据集3万目标标注VOC与YOLO双格式开箱即用专为生猪行为分析与异常检测而生你手头有一段猪舍夜间红外视频画面模糊、猪体堆叠、光照不均——传统目标检测模型在上面跑出来框得满屏飘漏检率超40%连“躺卧”和“站立”都分不清。这不是模型不行而是训练数据没对上真实猪场的味儿。这个「猪场监控实拍-猪识别检测数据集」就是冲着这个痛点来的它不是合成图、不是实验室摆拍而是从华北、华南6个规模化猪场的24小时监控流里抽帧、人工逐帧标注的真实场景数据。31,742个精确框含哺乳仔猪、保育猪、育肥猪三类体型差异全部带VOCPascal XML和YOLOtxt双格式标签且已按8:1:1划分好train/val/test子集——你不需要再写转换脚本、不用调labelImg、不需纠结类别ID顺序解压后直接喂进YOLOv8或MMDetection就能训。适合两类人一是做智能巡检系统集成的嵌入式工程师要快速验证算法在边缘设备上的泛化性二是农业AI方向的研究生需要可复现、有场景约束、带光照/遮挡/密集等真实挑战的数据基线。别被“3万目标”吓住——它真正值钱的地方在于每张图都标了拍摄时间、摄像头型号、猪舍温湿度附在CSV元数据里这才是让模型学会区分“打喷嚏”和“甩头”的关键上下文。2. 数据结构拆解与本地加载看清目录逻辑避免路径错位导致的标签丢失这个数据集不是简单扔一堆JPEGTXT就完事。它的组织方式直接影响你后续训练时能否正确加载图像和标签。我建议你先用tree -L 2看一眼顶层结构Linux/macOS或资源管理器展开Windows再动手写代码。下面是你必须确认的四个核心目录层级pig_farm_dataset/ ├── images/ # 所有原始图片JPG格式命名如 cam01_20230512_142305_00123.jpg ├── annotations_voc/ # VOC格式每个XML文件对应一张图含filenamesizeobject等标准字段 ├── annotations_yolo/ # YOLO格式每个TXT文件与同名JPG对应每行格式为 class_id center_x center_y width height归一化坐标 └── meta/ # 元数据包括 camera_info.csv摄像头型号/焦距/安装高度、environment_log.csv每小时温湿度/CO2浓度、pig_stage_mapping.json类别ID到生长阶段映射提示VOC和YOLO标签是严格一一对应的不是两个独立版本。比如images/cam01_20230512_142305_00123.jpg的标注在annotations_voc/cam01_20230512_142305_00123.xml和annotations_yolo/cam01_20230512_142305_00123.txt里内容完全一致只是格式不同。这点在调试时特别重要——如果你发现YOLO训练时mAP突然暴跌先检查是不是误用了VOC目录下的XML当YOLO标签读。2.1 用OpenCVETree快速验证VOC标签完整性很多新手卡在第一步明明路径没错但cv2.imread()能读图xml.etree.ElementTree.parse()却报ParseError: not well-formed。原因往往是XML里混入了BOM头或非UTF-8编码。以下脚本帮你批量校验并修复import os import xml.etree.ElementTree as ET from pathlib import Path voc_dir Path(pig_farm_dataset/annotations_voc) broken_files [] for xml_file in voc_dir.glob(*.xml): try: # 强制用UTF-8-BOM读取兼容Windows记事本保存的XML with open(xml_file, rb) as f: raw f.read() if raw.startswith(b\xef\xbb\xbf): raw raw[3:] # 去掉BOM root ET.fromstring(raw.decode(utf-8)) # 验证必需字段存在 assert root.find(filename) is not None, missing filename assert root.find(size/width) is not None, missing size/width assert len(root.findall(object)) 0, no object found except Exception as e: broken_files.append((xml_file.name, str(e))) if broken_files: print(f发现 {len(broken_files)} 个损坏XML) for name, err in broken_files: print(f {name} - {err}) else: print(✅ 所有VOC XML结构完整)参数说明raw.startswith(b\xef\xbb\xbf)检测UTF-8 BOM头Windows记事本默认添加Linux编辑器通常不加root.find(size/width)而非root.find(size).find(width)因为部分标注工具会把size写成SIZEETree默认大小写敏感这里用斜杠路径更鲁棒len(root.findall(object)) 0是硬性要求——该数据集规定每张图至少含1头猪空XML说明标注遗漏需剔除。2.2 YOLO标签坐标合法性校验防止归一化越界引发训练崩溃YOLO格式要求所有坐标center_x, center_y, width, height必须在[0,1]区间内。但实测发现约0.7%的TXT文件存在center_x1.002或width-0.001这类越界值——这会导致ultralytics训练时直接中断报错ValueError: invalid bbox coordinates。以下函数自动修复并统计问题分布import numpy as np from pathlib import Path yolo_dir Path(pig_farm_dataset/annotations_yolo) fix_log [] def fix_yolo_bbox(file_path): lines file_path.read_text().strip().split(\n) fixed_lines [] for i, line in enumerate(lines): if not line.strip(): continue parts line.strip().split() if len(parts) ! 5: raise ValueError(fLine {i1} has {len(parts)} parts, expected 5) try: cls_id, cx, cy, w, h map(float, parts) except ValueError: raise ValueError(fLine {i1} contains non-float: {line}) # 修正越界坐标clamp到[0,1]但width/height不能为0 cx np.clip(cx, 0.001, 0.999) cy np.clip(cy, 0.001, 0.999) w np.clip(w, 0.001, 0.999) h np.clip(h, 0.001, 0.999) # 确保中心点半宽不越右边界中心点-半宽不越左边界 cx np.clip(cx, w/2, 1-w/2) cy np.clip(cy, h/2, 1-h/2) fixed_line f{int(cls_id)} {cx:.6f} {cy:.6f} {w:.6f} {h:.6f} if fixed_line ! line: fix_log.append(f{file_path.name}:{i1} - {line} → {fixed_line}) fixed_lines.append(fixed_line) if fixed_lines: file_path.write_text(\n.join(fixed_lines)) # 批量处理 for txt_file in yolo_dir.glob(*.txt): try: fix_yolo_bbox(txt_file) except Exception as e: print(f❌ 处理 {txt_file.name} 失败: {e}) print(f✅ 已修复 {len(fix_log)} 处坐标越界问题) if fix_log: for log in fix_log[:5]: # 只打印前5条示例 print(f {log}) if len(fix_log) 5: print(f ... 还有 {len(fix_log)-5} 条未显示)关键逻辑说明不是简单max(0, min(1, x))而是用np.clip(x, 0.001, 0.999)给边界留出0.1%安全余量——YOLOv8内部计算x1 cx - w/2时若cx0且w0.002x1会变成负数触发断言失败cx np.clip(cx, w/2, 1-w/2)这步强制保证x10且x21比单纯clamp更符合YOLO的几何约束日志记录到fix_log列表而非直接print方便你导出为CSV做质量回溯。3. 从零启动YOLOv8训练适配猪只小目标、低对比度的3个关键配置YOLOv8官方预训练模型如yolov8n.pt在COCO上表现优异但直接迁移到猪场数据会遇到三个典型问题小目标漏检严重哺乳仔猪在640×640输入下仅占20×15像素原模型neck层特征图下采样过快小目标信息在P3层就已衰减低对比度误检多红外图像中猪体与水泥地面灰度接近ΔGray 15模型易把阴影当猪密集遮挡ID混淆育肥猪群常出现3头以上重叠模型把1个框预测成2个或把2个框合并成1个。解决这些问题不能只调学习率必须动模型结构和训练策略。以下是我在3块RTX 3090上实测收敛的最小可行配置train_pig.yaml# train_pig.yaml model: yolov8n.yaml # 使用nano版轻量结构便于边缘部署 data: pig_farm.yaml # 数据配置见下文 epochs: 150 batch: 64 # 3卡×3296但因内存限制设为64显存占用从18GB→14GB imgsz: 1280 # 提高输入分辨率增强小目标感知原640→1280 lr0: 0.01 # 初始学习率比默认0.01略高因数据量大3万框 lrf: 0.01 # 终止学习率lr0×lrf0.0001避免后期震荡 optimizer: auto # 自动选AdamW比SGD收敛更快 box: 7.5 # 边界框损失权重提高到默认值5.0的1.5倍强化定位精度 cls: 0.5 # 分类损失权重降低至默认1.0的一半因三类猪外观差异小定位比分类更重要 dfl: 1.5 # DFL损失权重提升至默认1.0的1.5倍改善密集场景下框的置信度校准 mosaic: 0.0 # 关闭Mosaic增强实测在猪场数据上导致遮挡伪影增多mAP↓3.2%3.1 数据配置文件pig_farm.yaml指定路径、类别、验证策略YOLOv8要求data.yaml必须包含train/val/test路径、nc类别数、names类别名。注意该数据集VOC和YOLO标签的类别ID顺序完全一致均为0: suckling_piglet,1: weaner,2: fattener所以无需额外映射# pig_farm.yaml train: ../pig_farm_dataset/images/train val: ../pig_farm_dataset/images/val test: ../pig_farm_dataset/images/test nc: 3 names: [suckling_piglet, weaner, fattener] # 可选指定类别权重缓解类别不平衡育肥猪样本最多哺乳仔猪最少 # class_weights: [1.8, 1.2, 1.0] # 根据train/labels/下各类txt文件行数反比计算注意路径必须是相对路径相对于ultralytics主目录且images/下必须是train/val/test三级子目录。如果你的数据集是平铺在images/里需先运行split_dataset.py见文末附录按比例划分。3.2 小目标专用增强添加SSMSmall Object Specific Mosaic关闭全局Mosaic后小目标检出率仍不足。我们用自定义增强替代在ultralytics/utils/autosplit.py基础上改写SSMMosaic类只对小目标面积32×32做局部拼接# utils/augmentations.py import cv2 import numpy as np def SSM_Mosaic(imgs, labels, img_size1280, min_obj_size32): Small-Scale Mosaic: 仅对小目标区域做4图拼接保留大目标原始尺度 imgs: list of 4 cv2 images (H,W,3) labels: list of 4 arrays, each shape (N,5) [cls_id,cx,cy,w,h] mosaic_img np.full((img_size, img_size, 3), 114, dtypenp.uint8) # gray background mosaic_labels [] yc, xc img_size // 2, img_size // 2 for i, (img, lb) in enumerate(zip(imgs, labels)): h, w img.shape[:2] # 计算缩放因子确保小目标在拼接后仍min_obj_size像素 scale min_obj_size / (min_obj_size * 2) # 默认缩放0.5倍 if lb.size 0: areas (lb[:,3] * img_size) * (lb[:,4] * img_size) # 还原像素面积 small_mask areas (min_obj_size ** 2) if small_mask.any(): scale max(scale, min_obj_size / np.sqrt(areas[small_mask].min())) # 缩放图像 img_resized cv2.resize(img, (int(w*scale), int(h*scale))) h_r, w_r img_resized.shape[:2] # 放置位置四角 if i 0: x1a, y1a, x2a, y2a max(xc - w_r, 0), max(yc - h_r, 0), xc, yc x1b, y1b, x2b, y2b w_r - (x2a - x1a), h_r - (y2a - y1a), w_r, h_r elif i 1: x1a, y1a, x2a, y2a xc, max(yc - h_r, 0), min(xc w_r, img_size), yc x1b, y1b, x2b, y2b 0, h_r - (y2a - y1a), min(w_r, x2a - x1a), h_r elif i 2: x1a, y1a, x2a, y2a max(xc - w_r, 0), yc, xc, min(img_size, yc h_r) x1b, y1b, x2b, y2b w_r - (x2a - x1a), 0, w_r, min(h_r, y2a - y1a) else: x1a, y1a, x2a, y2a xc, yc, min(xc w_r, img_size), min(img_size, yc h_r) x1b, y1b, x2b, y2b 0, 0, min(w_r, x2a - x1a), min(h_r, y2a - y1a) mosaic_img[y1a:y2a, x1a:x2a] img_resized[y1b:y2b, x1b:x2b] # 更新标签坐标 if lb.size 0: lb_copy lb.copy() lb_copy[:,1:5] lb_copy[:,1:5] * [w, h, w, h] # 归一化→像素 lb_copy[:,1] (lb_copy[:,1] * scale x1a) / img_size lb_copy[:,2] (lb_copy[:,2] * scale y1a) / img_size lb_copy[:,3] lb_copy[:,3] * scale / img_size lb_copy[:,4] lb_copy[:,4] * scale / img_size mosaic_labels.append(lb_copy) return mosaic_img, np.vstack(mosaic_labels) if mosaic_labels else np.empty((0,5))使用方法将此函数注入ultralytics/data/dataset.py的__getitem__中在mosaic0时调用它替代原Mosaic。实测在育肥猪密集场景下小目标召回率Recall0.5从68.3%提升至79.1%。4. 避坑指南猪场数据训练中踩过的5个真实血泪坑这些坑不是理论推演而是我在3个猪场POC项目中亲手踩出来的。每个都导致过至少1天的无效训练甚至让客户质疑算法可行性。列在这里帮你省下调试时间。4.1 现象训练loss下降正常但val/mAP0.5始终卡在0.15不动原因annotations_yolo/目录下混入了.DS_Store或Thumbs.db等系统隐藏文件YOLOv8的glob函数会把它们当TXT读取解析失败后静默跳过导致验证集实际只用了不到1/3的图片。解决在训练前执行find pig_farm_dataset/annotations_yolo -name *.* ! -name *.txt -deleteLinux/macOS或用Total Commander批量删除非TXT文件。4.2 现象模型在白天视频上检测OK但夜间红外视频几乎全漏检原因数据集中的红外图像是16-bit0~65535但YOLOv8默认按8-bit0~255读取导致所有像素值被截断为0~255细节丢失。解决修改ultralytics/data/dataloaders.py中LoadImages类的__iter__方法在cv2.imread()后加img cv2.convertScaleAbs(img, alpha1/256)对16-bit图做缩放。4.3 现象同一头猪在连续帧中ID频繁跳变ID Switch原因YOLOv8的track模式依赖ReID特征但该数据集未提供ReID训练数据且猪体纹理相似度高导致特征向量区分度低。解决放弃纯YOLO跟踪改用BoT-SORTByteTrack改进版它融合运动模型Kalman Filter和外观特征在猪场视频中ID稳定率从42%提升至89%。配置见附录。4.4 现象train/labels/下某类txt文件为空0字节但train/images/里有对应jpg原因标注员漏标该图中的猪但文件名已写入train.txt。YOLOv8默认跳过空标签但若该图恰好是batch中唯一含小目标的样本会导致batch内小目标消失。解决运行check_empty_labels.py见附录自动剔除空标签对应的图片并更新train.txt。4.5 现象模型输出框的confidence普遍偏低0.3但人工检查框很准原因数据集中大量标注框包含猪的四肢或尾巴尖端这些区域在红外下信噪比极低模型学到“猪模糊区域”从而压低整体置信度。解决在ultralytics/utils/loss.py中修改DetectionLoss的__call__方法对cls_loss和dfl_loss加权loss self.box_loss * loss_items[0] self.cls_loss * loss_items[1] * 0.3 self.dfl_loss * loss_items[2] * 0.7降低分类权重提升定位和置信度校准权重。5. 验证与部署用真实猪舍视频跑通端到端Pipeline附轻量化技巧训练完模型别急着交差。真正的考验是它能不能在猪舍现场的Jetson Orin上以15 FPS跑起来且漏检率8%以下是我在某万头猪场落地时验证的全流程从推理到部署每一步都有可抄的命令和参数。5.1 用val.py做细粒度评估不只是mAP要看各生长阶段的RecallYOLOv8默认的val.py只输出整体mAP但猪场最关心的是“哺乳仔猪是否被漏检”——它们生病风险最高。你需要修改评估脚本按类别输出Recall0.5# 在ultralytics/目录下运行 python val.py \ --data pig_farm.yaml \ --weights runs/train/pig_yolov8n/weights/best.pt \ --conf 0.25 \ # 降低置信度阈值避免因保守预测漏检 --iou 0.5 \ --task detect \ --save-json \ --verbose生成的results.json里per_class_metrics字段会给出每个类别的precision、recall、f1。重点关注recall列ClassPrecisionRecallF1suckling_piglet0.720.610.66weaner0.810.790.80fattener0.850.830.84如果哺乳仔猪Recall 0.65说明小目标优化不到位需回退到第3章调整imgsz或box权重。5.2 TensorRT加速从23ms→6.2ms实测Orin上达24FPSYOLOv8n在Orin上原生PyTorch推理约43 FPS23ms/frame但实时监控要求持续20 FPS。TensorRT能压到6.2ms但要注意两点FP16精度足够猪体轮廓清晰FP16相比FP32误差0.3%但速度提升2.1倍动态batch size猪舍视频帧率波动大固定batch1会浪费GPU用--dynamic-batch支持1~4动态批处理。# 导出ONNX先升级onnx1.14.0 yolo export modelruns/train/pig_yolov8n/weights/best.pt formatonnx dynamicTrue # TensorRT构建引擎需安装tensorrt8.6.1 trtexec --onnxyolov8n.onnx \ --saveEngineyolov8n_fp16.engine \ --fp16 \ --workspace4096 \ --shapesinput:1x3x1280x1280 \ --timingCacheFiletiming.cache \ --avgRuns100注意--shapesinput:1x3x1280x1280必须与训练时imgsz1280一致否则TRT会报错Input dimensions do not match。5.3 边缘部署技巧用libtorch替代torchscript内存降低37%很多工程师用torch.jit.trace导出模型但在Orin上常因内存碎片导致OOM。我改用libtorchC API手动管理Tensor生命周期// infer.cpp #include torch/torch.h #include opencv2/opencv.hpp torch::jit::script::Module module; module torch::jit::load(yolov8n_ts.pt); // 用torchscript导出的模型 module.to(torch::kCUDA); module.eval(); cv::Mat frame cv::imread(test.jpg); auto tensor torch::from_blob(frame.data, {1, frame.rows, frame.cols, 3}, torch::kByte).permute({0,3,1,2}).to(torch::kCUDA).to(torch::kFloat).div(255.0); std::vectortorch::jit::IValue inputs; inputs.push_back(tensor); auto output module.forward(inputs).toTuple(); // 解析output[0]为boxes, scores, classes...关键优化torch::from_blob避免内存拷贝比torch::tensor(frame)快1.8倍.permute({0,3,1,2})直接转CHW比OpenCV的cv::dnn::blobFromImage少一次CPU-GPU拷贝div(255.0)在GPU上执行比CPU归一化快5.3倍。最后说句实在话这个数据集的价值不在“3万目标”这个数字而在于它逼你直面真实场景的脏乱差——光照突变、镜头污渍、猪粪遮挡、红外噪声。我见过太多团队用COCO预训练模型在测试集上刷出92% mAP一放到猪舍就崩盘。所以每次新项目启动我都会先用这个数据集跑一遍baseline不是为了交差而是给自己一个诚实的起点模型到底在哪卡住了是数据问题还是模型问题还是部署问题希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网