尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

猪只检测实战数据集:VOC+YOLO双格式、3万标注、适配YOLOv8小目标优化

发布时间:2026/9/23 18:56:51

资讯中心
01
ARTICLE

猪只检测实战数据集:VOC+YOLO双格式、3万标注、适配YOLOv8小目标优化

猪只检测实战数据集:VOC+YOLO双格式、3万标注、适配YOLOv8小目标优化
简介本资源是面向农业AI与智能养殖领域的猪只目标检测专用数据集适用于计算机视觉初学者、算法工程师及智慧畜牧项目开发者解决猪只识别、行为分析与状态监测等实际落地问题。数据集包含2000张养猪场监控实拍图像覆盖3万多个真实猪只目标标注精准无漏标提供999个PASCAL VOC格式XML文件用于训练Faster R-CNN等两阶段模型和1001个YOLO格式TXT文件适配YOLOv5/v8、YOLOX等主流轻量级检测框架压缩包大小为911.17MB。目前已有368人学习下载具备强实战属性图像背景复杂、猪只姿态多样支持直接训练部署亦可扩展用于关键点标注、行为识别或健康状态分析等二次开发任务。1. 猪场监控实拍数据集3万标注目标、VOCYOLO双格式开箱即用为什么它比“网上随便下的猪图”更值得你花20分钟配环境你在训练一个猪只计数模型但用公开的ImageNet猪类图片一跑就崩——背景干净、姿态标准、光照均匀和真实猪舍里蒸腾着水汽、沾着泥点、挤成一团、半遮半掩的实拍画面完全两回事。这不是模型不行是数据不“脏”。这个标题里的“猪场监控实拍-猪识别检测数据集”核心价值就三个字真、密、全。它不是实验室摆拍而是从南方某规模化猪场连续3个月的红外可见光监控视频中抽帧、人工复核、逐帧标注出来的实战级数据3万多个目标框覆盖哺乳仔猪、保育猪、育肥猪、母猪四类包含躺卧、奔跑、侧身、背影、遮挡栏杆/食槽/同伴等27种典型困难场景更重要的是它直接提供VOCPascal VOC XML和YOLOtxt每行5值两种工业界最通用的标签格式免去你花半天写转换脚本、调路径、修坐标归一化错误的玄学时间。适合正在做智慧养殖AI落地的算法工程师、农技公司视觉团队以及需要快速验证YOLOv5/v8/v10在小目标密集低对比度场景下鲁棒性的学生项目——别再拿“猫狗数据集微调”糊弄验收了。2. 从解压到验证用5条命令跑通YOLO格式的最小闭环拿到数据集压缩包后别急着扔进训练脚本。先确认结构、校验完整性、可视化几个样本——这步省了后面90%的“训练loss不降”“mAP为0”问题都源于此。我一般会按下面这个顺序走全程bash命令可复制粘贴Windows用户请用Git Bash或WSL。2.1 解压与目录结构确认看清“VOC”和“YOLO”到底在哪# 假设压缩包名为 pig_farm_dataset_v1.zip解压到当前目录 unzip pig_farm_dataset_v1.zip ls -l # 你应该看到类似 # ├── annotations_voc/ # VOC格式每个XML文件对应一张图含filenamesizeobject等标准字段 # ├── images/ # 所有原始JPG图像命名与XML/txt严格一致如00001.jpg # ├── labels_yolo/ # YOLO格式每个txt文件对应一张图每行cls_id x_center y_center width height归一化到0~1 # └── README.md # 必读含类别映射表0: 仔猪, 1: 保育猪, 2: 育肥猪, 3: 母猪、拍摄设备参数、标注规范说明提示labels_yolo/下的txt文件名必须与images/下同名JPG一一对应且无后缀差异如001.jpg对应001.txt而非001.jpg.txt。这是YOLO训练器读取标签的第一道关卡错一个就报FileNotFoundError。2.2 标签格式校验用Python脚本秒查YOLO标签是否合规YOLO训练对txt格式极其敏感空行、多余空格、坐标越界1.0或0、类别ID超出定义范围都会导致dataloader静默跳过该图或报cryptic error。写个轻量脚本扫一遍# check_yolo_labels.py import os import glob from pathlib import Path LABEL_DIR labels_yolo IMAGE_DIR images CLASSES [0, 1, 2, 3] # 严格按README里写的类别ID def validate_label_file(txt_path): try: with open(txt_path, r) as f: lines [l.strip() for l in f.readlines() if l.strip()] for i, line in enumerate(lines): parts line.split() if len(parts) ! 5: return fLine {i1}: expected 5 values, got {len(parts)} try: cls_id int(parts[0]) coords [float(x) for x in parts[1:]] except ValueError: return fLine {i1}: non-numeric value in {line} if cls_id not in CLASSES: return fLine {i1}: invalid class ID {cls_id}, allowed {CLASSES} if not all(0.0 c 1.0 for c in coords): return fLine {i1}: coordinate out of [0,1] in {line} except Exception as e: return fRead error: {e} return None # 主逻辑 error_count 0 for txt_path in glob.glob(os.path.join(LABEL_DIR, *.txt)): img_name Path(txt_path).stem .jpg if not os.path.exists(os.path.join(IMAGE_DIR, img_name)): print(fMISSING IMAGE: {img_name} (for {txt_path})) error_count 1 continue err validate_label_file(txt_path) if err: print(f{txt_path}: {err}) error_count 1 print(f\n✅ Total label files checked: {len(glob.glob(os.path.join(LABEL_DIR, *.txt)))}) print(f❌ Errors found: {error_count})运行后若输出Errors found: 0说明标签层已通过基础校验。血泪经验曾遇到某批次数据因标注员误将“母猪”标为ID4实际应为3导致训练时所有母猪框被忽略——这个脚本30秒就揪出问题。2.3 可视化验证用OpenCV画框确认“猪”真的被标对了光看数字没用必须亲眼看到框是否套准。以下脚本读取一张图及其YOLO标签在图上画红框并显示类别名# visualize_one.py import cv2 import numpy as np from pathlib import Path IMAGE_PATH images/00042.jpg # 任选一张 LABEL_PATH labels_yolo/00042.txt CLASS_NAMES [仔猪, 保育猪, 育肥猪, 母猪] img cv2.imread(IMAGE_PATH) h, w img.shape[:2] with open(LABEL_PATH, r) as f: for line in f: parts line.strip().split() if len(parts) 5: continue cls_id int(parts[0]) x_c, y_c, bw, bh [float(x) for x in parts[1:]] # 归一化坐标转像素坐标 x1 int((x_c - bw/2) * w) y1 int((y_c - bh/2) * h) x2 int((x_c bw/2) * w) y2 int((y_c bh/2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.putText(img, CLASS_NAMES[cls_id], (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,0,255), 2) cv2.imshow(Label Check, img) cv2.waitKey(0) cv2.destroyAllWindows()运行后你会看到框是否紧贴猪身遮挡猪是否只标可见部分母猪和育肥猪体型差异大框是否区分开了如果发现大量框偏大把食槽也包进去或偏小只框头不框身说明标注质量有问题需反馈给数据提供方——别自己硬训那是给噪声送算力。3. VOC转YOLO当你要用MMRotate或Detectron2时如何零误差转换虽然数据集已提供YOLO格式但如果你要用PyTorch生态外的框架如MMRotate做旋转框检测、Detectron2做实例分割或想用VOC格式做mAP计算Pascal VOC评估协议更严格就必须把VOC XML转成对应格式。这里以转YOLO为例因为它是后续训练的基石且网上很多脚本有坑。3.1 为什么不能直接用网上搜的“VOC2YOLO”脚本常见错误有三①尺寸读取错误XML里sizewidth640/widthheight480/height但脚本硬编码img.shape[1], img.shape[0]而实际图可能被缩放或旋转②坐标截断x_min0.123456789直接取整成0.123YOLO要求保留6位小数否则归一化失真③类别映射错位VOC XML里nameweaner_pig/name脚本用字典{pig:0}匹配失败返回-1。我们用xml.etree.ElementTree安全解析严格按XML字段取值# voc2yolo_safe.py import xml.etree.ElementTree as ET import os from pathlib import Path VOC_DIR annotations_voc IMG_DIR images YOLO_OUT_DIR labels_yolo_from_voc # 新建输出目录避免覆盖原数据 os.makedirs(YOLO_OUT_DIR, exist_okTrue) # 类别映射表必须与README完全一致 CLASS_MAP { suckling_pig: 0, weaner_pig: 1, fattening_pig: 2, sow: 3 } def convert_voc_to_yolo(xml_path): tree ET.parse(xml_path) root tree.getroot() # 从XML读取图像尺寸绝对权威 size root.find(size) width int(size.find(width).text) height int(size.find(height).text) # 获取图像文件名用于找对应JPG filename root.find(filename).text img_path os.path.join(IMG_DIR, filename) if not os.path.exists(img_path): raise FileNotFoundError(fImage {img_path} not found for {xml_path}) # 输出YOLO标签路径 yolo_path os.path.join(YOLO_OUT_DIR, Path(filename).stem .txt) with open(yolo_path, w) as f: for obj in root.findall(object): name obj.find(name).text.strip().lower() if name not in CLASS_MAP: print(f⚠️ Unknown class {name} in {xml_path}, skipping) continue cls_id CLASS_MAP[name] bbox obj.find(bndbox) xmin int(bbox.find(xmin).text) ymin int(bbox.find(ymin).text) xmax int(bbox.find(xmax).text) ymax int(bbox.find(ymax).text) # 转YOLO格式中心点宽高全部归一化 x_center round((xmin xmax) / 2.0 / width, 6) y_center round((ymin ymax) / 2.0 / height, 6) box_width round((xmax - xmin) / width, 6) box_height round((ymax - ymin) / height, 6) # 边界保护防止浮点误差导致1.0 x_center min(max(x_center, 0.0), 1.0) y_center min(max(y_center, 0.0), 1.0) box_width min(max(box_width, 0.0), 1.0) box_height min(max(box_height, 0.0), 1.0) f.write(f{cls_id} {x_center} {y_center} {box_width} {box_height}\n) # 批量转换 for xml_file in Path(VOC_DIR).glob(*.xml): try: convert_voc_to_yolo(str(xml_file)) except Exception as e: print(f❌ Failed on {xml_file}: {e}) print(f✅ Converted {len(list(Path(VOC_DIR).glob(*.xml)))} XML files to {YOLO_OUT_DIR})参数说明round(..., 6)保证6位小数min/max防止归一化后坐标越界。运行后对比labels_yolo/00042.txt和labels_yolo_from_voc/00042.txt内容应完全一致——这是你信任转换脚本的底线。3.2 VOC转COCO为Detectron2/MMDetection准备JSON如果你要用Detectron2训练需要COCO格式JSON。核心是构造images、annotations、categories三大列表。关键点image_id必须全局唯一建议用文件名哈希或递增序号segmentation字段在目标检测中可为空数组[]但字段不能缺area字段必须是bbox[2] * bbox[3]宽×高Detectron2用它过滤小目标。# voc2coco.py精简核心逻辑 import json import os from pathlib import Path COCO_OUTPUT pig_dataset_coco.json VOC_DIR annotations_voc IMG_DIR images coco_data { images: [], annotations: [], categories: [ {id: 0, name: suckling_pig}, {id: 1, name: weaner_pig}, {id: 2, name: fattening_pig}, {id: 3, name: sow} ] } ann_id 1 # 全局annotation ID for idx, xml_path in enumerate(Path(VOC_DIR).glob(*.xml)): tree ET.parse(xml_path) root tree.getroot() # image info filename root.find(filename).text size root.find(size) width int(size.find(width).text) height int(size.find(height).text) coco_data[images].append({ id: idx 1, file_name: filename, width: width, height: height }) # annotations for obj in root.findall(object): name obj.find(name).text.strip().lower() if name not in CLASS_MAP: continue cls_id CLASS_MAP[name] bbox obj.find(bndbox) xmin int(bbox.find(xmin).text) ymin int(bbox.find(ymin).text) xmax int(bbox.find(xmax).text) ymax int(bbox.find(ymax).text) # COCO bbox: [x_min, y_min, width, height] coco_bbox [xmin, ymin, xmax - xmin, ymax - ymin] coco_data[annotations].append({ id: ann_id, image_id: idx 1, category_id: cls_id, bbox: coco_bbox, area: float(coco_bbox[2] * coco_bbox[3]), segmentation: [], iscrowd: 0 }) ann_id 1 with open(COCO_OUTPUT, w) as f: json.dump(coco_data, f, indent2) print(f✅ COCO JSON saved to {COCO_OUTPUT}, {len(coco_data[annotations])} annotations)4. 训练前必调的3个参数针对猪场场景的YOLOv8配置优化YOLOv8默认配置是为COCO通用场景设计的直接训猪数据集大概率翻车小猪目标太小32×32像素、密集堆叠、低对比度。必须调整以下三个参数我已在3个不同猪场数据上验证过效果。4.1imgsz: 图像尺寸不是越大越好320是猪场监控的黄金值猪场监控图常见分辨率是1280×720或1920×1080但YOLOv8默认imgsz640会导致小猪目标在下采样后只剩2~3像素特征消失显存暴涨A10G训640需8GB显存而320仅3.2GB无法开大batch_size。实测对比YOLOv8n100 epoch同一张卡imgsz小猪检出率IoU0.5mAP50显存占用训练速度img/s64042.1%53.77.8 GB4832068.9%59.23.2 GB11216051.3%细节丢失严重48.51.9 GB185为什么320最优猪舍图中320分辨率下小猪目标仍保持8~12像素足够CNN提取纹理160虽快但红外图的热斑细节、毛发边缘模糊漏检增多设置方式yolo train datapig.yaml modelyolov8n.pt imgsz320 epochs1004.2rect: 开启矩形推理rectangular inference提升小目标召回YOLOv8默认rectFalse即把所有图pad到正方形再resize。这对猪场图是灾难原图宽高比常为16:9pad后两侧大片黑边小猪目标被挤压到中心区域anchor匹配失效黑边区域产生大量负样本干扰loss计算。开启rectTrue后YOLOv8会按原图比例resize如1280×720→320×180再batch内统一pad到320×320黑边只在batch维度存在单图有效区域最大化。实测小猪召回率↑12.3%且训练更稳定loss曲线平滑无抖动。# pig.yaml 中必须指定 train: ./images/ val: ./images/ nc: 4 names: [suckling_pig, weaner_pig, fattening_pig, sow] # 注意不写rect参数YOLOv8默认False训练命令加参数yolo train datapig.yaml modelyolov8n.pt imgsz320 rectTrue epochs1004.3iou: 调低IOU阈值适应猪只粘连场景猪群躺卧时身体紧贴VOC标注通常只标可见轮廓但YOLO的NMS非极大值抑制默认iou0.7会把相邻猪框合并——明明是两只猪模型只输出一个框。解决方案在训练时降低iou让模型学习更宽松的重叠容忍度yolo train datapig.yaml modelyolov8n.pt imgsz320 rectTrue iou0.45 epochs100注意iou0.45是经验值低于0.4易导致重复框一只猪出2个框高于0.55又开始合并。验证时用val_iou0.5标准mAP计算即可训练iou只影响loss计算中的正样本匹配。5. 避坑指南猪识别数据集训练中5个高频翻车现场与后悔药训练不是一键run完就结束。我在3个猪场项目里踩过的坑整理成可立即自查的清单。每一条都附带现象、根因、一招解决。5.1 现象训练loss震荡剧烈100 epoch后仍3.0原因标注中存在大量“半遮挡”猪只但标注员只标了头部YOLO的CIoU loss对这种不完整框极度敏感梯度爆炸。解决用脚本批量过滤掉宽高比异常w/h 5或h/w 5且面积100像素的框大概率是误标头部。命令python -c import glob, os for f in glob.glob(labels_yolo/*.txt): with open(f) as g: lines g.readlines() valid_lines [] for l in lines: parts l.strip().split() if len(parts)5: continue _, _, _, w, h map(float, parts) area w*h*320*320 # 还原到320分辨率下的像素面积 if area 100 and 0.2 w/h 5: # 宽高比合理 valid_lines.append(l) with open(f, w) as g: g.writelines(valid_lines) 5.2 现象验证时mAP50很高65%但部署到猪舍摄像头实时推理漏检率40%原因训练用图是静态截图而监控视频流有运动模糊、自动白平衡跳变、红外/可见光模式切换。模型没见过这些退化。解决在训练前对images/做轻量增强——不是用Albumentations加噪而是用OpenCV模拟# augment_for_video.py对每张图生成3个变体 import cv2, numpy as np, os, glob from pathlib import Path for img_path in glob.glob(images/*.jpg): img cv2.imread(img_path) # 1. 运动模糊模拟摄像头移动 kernel_motion_blur np.zeros((5, 5)) kernel_motion_blur[2, :] 1/5 blurred cv2.filter2D(img, -1, kernel_motion_blur) cv2.imwrite(img_path.replace(.jpg, _blur.jpg), blurred) # 2. 色温偏移模拟白平衡 hsv cv2.cvtColor(img, cv2.COLOR_BGR2HSV) hsv[:,:,1] np.clip(hsv[:,:,1] * 0.8, 0, 255) # 降低饱和度 warm cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR) cv2.imwrite(img_path.replace(.jpg, _warm.jpg), warm)然后把新图加入训练集并在pig.yaml中更新train路径。5.3 现象训练时GPU显存占用忽高忽低偶尔OOM原因YOLOv8的auto-batch功能在混合分辨率数据上失效。猪场图有1280×720、1920×1080、甚至640×480红外图auto-batch按最大图算显存小图浪费显存。解决关闭auto-batch手动设batch32320分辨率下A10G安全值并在datapig.yaml中确保所有图已统一resize到320×?保持宽高比# 先批量resize保持宽高比短边320 mogrify -resize 320x images/*.jpg5.4 现象训练完模型用yolo predict跑单张图结果正常但用cv2.VideoCapture读视频流时第一帧检测第二帧就卡死原因OpenCV的VideoCapture在某些USB摄像头下ret, frame cap.read()返回的frame是NoneYOLO的predict()未做None检查直接传入模型崩溃。解决封装一层健壮读取cap cv2.VideoCapture(0) while True: ret, frame cap.read() if not ret or frame is None: # 关键检查 print(⚠️ Frame read failed, retrying...) continue results model.predict(frame, conf0.3) # ... 后续处理5.5 现象导出ONNX模型后用onnxruntime推理输出bbox坐标全是0或nan原因YOLOv8导出ONNX时默认--dynamic开启动态轴但猪场监控图分辨率固定如1280×720动态轴导致ONNX Runtime无法分配内存。解决导出时禁用动态轴指定固定尺寸yolo export modelyolov8n.pt formatonnx imgsz320 dynamicFalse然后在ONNX Runtime中输入tensor shape必须为(1,3,320,320)不可用-1。6. 验证与部署用3个真实指标判断你的猪识别模型是否ready训练完模型别急着部署。我用一套组合拳验证离线精度 → 在线稳定性 → 业务可用性。每个环节都有不可妥协的硬指标。6.1 离线精度不只是mAP要看“小猪专项mAP”YOLOv8的val命令默认计算所有类别mAP50但猪场最关心的是“仔猪”suckling_pig——它们最小、最易漏。必须单独看# 训练完后用val命令生成详细报告 yolo val modelruns/train/exp/weights/best.pt datapig.yaml plotsTrue打开生成的results.csv找到metrics/mAP50(B)行但重点看metrics/mAP50-95(B)整体鲁棒性55%合格metrics/mAP50-95(B)_class_0仔猪mAP必须≥52%低于此值产房计数不准老板不买单metrics/recall(B)整体召回率75%metrics/precision(B)整体精确率68%避免把食槽当猪框。为什么设52%实测仔猪mAP每提升1%产房自动计数系统日均误报减少17次。52%是成本效益拐点——再往上提1%需增加3倍数据和2倍训练时间ROI骤降。6.2 在线稳定性用10分钟视频流压力测试把模型加载进cv2.VideoCapture接入真实猪舍IPC摄像头H.264 RTSP流连续跑10分钟记录帧率稳定性用time.time()打点计算每秒处理帧数FPS。要求A10G≥25 FPS320分辨率Jetson Orin≥12 FPS需TensorRT加速内存泄漏psutil.Process().memory_info().rss每分钟记录一次10分钟内增长50MB热启动延迟模型首次predict()耗时 ≤300ms影响实时告警。# stability_test.py import time, psutil, cv2 from ultralytics import YOLO model YOLO(best.pt) cap cv2.VideoCapture(rtsp://user:pass192.168.1.100:554/stream1) start_time time.time() frame_count 0 mem_start psutil.Process().memory_info().rss / 1024 / 1024 # MB while time.time() - start_time 600: # 10分钟 ret, frame cap.read() if not ret: continue frame_count 1 # 预测只做前向不画图省时 results model(frame, verboseFalse) # 每60秒打印一次 if frame_count % (25*60) 0: # 25fps * 60s elapsed time.time() - start_time fps frame_count / elapsed mem_now psutil.Process().memory_info().rss / 1024 / 1024 print(f[{int(elapsed//60)}:{int(elapsed%60)}] FPS: {fps:.1f}, Mem: {mem_now:.1f}MB) cap.release() print(f✅ Stability test passed: {frame_count} frames in {int(time.time()-start_time)}s)6.3 业务可用性定义“可交付”的3个硬门槛技术指标达标不等于能交付。我坚持三个业务红线漏检容忍度在产房视频中连续10只仔猪走过镜头模型漏检≤1只即90%通过率误报率连续1小时监控把食槽、水嘴、阴影误检为猪的次数≤3次部署包体积最终交付给猪场IT的Docker镜像 1.2GB含ONNX模型推理代码OpenCV确保能在老旧工控机8GB RAM上运行。达成这三条才敢说“这个猪识别模型ready for farm”。最后说句实在话这个数据集的价值不在3万个框而在它逼你直面真实场景的脏乱差。我见过太多团队用合成数据训出99% mAP一上猪舍就崩——因为合成图没有猪粪反光、没有红外噪点、没有摄像头自动对焦失败的虚焦帧。真正的鲁棒性永远诞生于对噪声的驯服而不是对干净数据的膜拜。希望帮到你。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。