ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

柑橘害虫数据集详解:YOLOv5格式标注、可视化与训练避坑指南

柑橘害虫数据集详解:YOLOv5格式标注、可视化与训练避坑指南 简介面向目标检测与病害识别场景这份资源提供了一套开箱即用的柑橘害虫检测数据集包含苍蝇、木虱两个类别数据已按YOLOV5标准目录划分为训练集与验证集适合正在学习YOLO系模型、病虫害视觉识别或需要标准格式数据训练检测器的开发者直接使用。压缩包共603个文件其中300张高分辨率JPEG原图配套301个txt标签文件另附可视化python脚本与说明图可随机读取图片绘制边界框并保存结果无需修改即可运行。数据集样本总量约300张训练集与验证集分别240张、60张图片分辨率普遍在1000至4000像素区间能较好反映田间复杂背景下的害虫形态差异。资源整体体积约260MB便于下载与本地训练。目前已有401人学习该资源适合作为算法验证、课程作业或项目起步时的标准数据支撑。1. 目标检测数据集为什么我拿到一份柑橘害虫数据集先看目录而不是看图片做目标检测的人都有个习惯性动作拿到新数据集先翻几张图过过眼瘾。但真正决定这个数据集能不能用的从来不是图片拍得多清晰而是目录结构、标签格式和类别定义这三样东西对不对。这份柑橘害虫数据集YOLOV5目录格式2类别含训练集与验证集属于已经按YOLOv5规范排好版的数据集训练集240张图配240个txt标签验证集60张图配60个txt标签全部是1000到4000分辨率的大尺度RGB图总计260MB拿过来就能直接开训省去从JSON或XML转YOLO格式的折腾。适合正在做农业虫害检测、植保无人机巡田、或者刚入门YOLOv5想找一份干净数据跑通全流程的人。本文就把目录结构、可视化脚本、训练前自查和这几个类别的标注陷阱一次说透。2. 先看懂YOLOv5格式的数据集目录结构、标签规范与两类害虫的标注差异2.1 目录结构为什么 images 和 labels 必须严格分家YOLOv5训练时通过数据配置文件data.yaml里的路径去同时索引图片和标签它默认的约定是图片在images目录下标签在同名路径的labels目录下。这份数据集的目录结构就是最标准的YOLOv5布局剥开来看长这样datasets/ ├── images/ │ ├── train/ │ │ ├── train_001.jpeg │ │ ├── train_002.jpeg │ │ └── ... │ └── val/ │ ├── train_163.jpeg │ ├── train_258.jpeg │ └── ... ├── labels/ │ ├── train/ │ │ ├── train_001.txt │ │ ├── train_002.txt │ │ └── ... │ └── val/ │ ├── train_163.txt │ ├── train_258.txt │ └── ... └── 类别文件包含2类注意一个细节验证集的图片文件名也是train_*开头这是原始采集时按批次命名的遗留问题不影响使用因为YOLOv5只认目录不认文件名前缀。训练时train.txt里记录的是图片的绝对或相对路径只要images/train和labels/train一一对应文件名是否带train字样根本不重要。2.2 标签txt格式五个数字背后的归一化坐标YOLO格式的每个txt文件与同名图片一一对应每一行代表一个目标框格式是class_id x_center y_center width height四个坐标值全部是相对于图片宽高的归一化比例取值范围在0到1之间。拿训练集里的一个木虱标签举例1 0.485156 0.628472 0.046875 0.031944这行数据的意思是类别ID为1木虱目标框中心点位于图片宽度方向的48.5%、高度方向的62.8%处框的宽度占整张图宽度的4.69%高度占整张图高度的3.19%。归一化的好处是图片无论被resize成640还是1280标注框的数值都无需改变模型训练时按输入尺寸等比缩放即可。2.3 两类害虫的标注差异苍蝇与木虱的目标尺寸完全不同数据集的2个类别是苍蝇和木虱这两类害虫在标注上有明显的尺寸差异。苍蝇体型相对较大在1000到4000分辨率的大图上通常占据几十到上百像素的宽高木虱体型小尤其是若虫阶段在同样分辨率下可能只有二三十个像素归一化后width和height值常常不到0.05。这直接影响后文训练的anchor设置和推理时的NMS阈值调整。另外提醒一点如果训练时发现loss曲线降得很快但mAP上不去先怀疑是不是小目标木虱的召回率不够这是后文避坑章会展开讲的典型问题。2.4 训练集与验证集的划分比例8:2在当前数据量下的合理性这份数据集训练集240张、验证集60张划分比例约为8:2符合目标检测任务的主流划分习惯。240张的训练集在当前深度学习时代看起来不算多但对农业虫害检测这类场景其实是够用的——每一张大图上通常包含多只害虫实例有效训练样本数量是图片数的数倍。不过也要心里有数这个数据量下模型初始权重建议直接继承YOLOv5s或YOLOv5m的COCO预训练权重不要从零训练否则收敛速度和最终精度都会很不理想。3. 动手前先验证可视化脚本实测随机传一张图画出全部边界框3.1 数据集自带可视化脚本的作用这份数据集附带了一个可视化py脚本干的活是随机传入一张图片脚本自动读取同名的标签txt文件把里面所有检测框画在图上并标注类别名称最终图片保存到当前目录。它的核心价值在于验证标签与图片的对应关系是否正确、边界框是否贴合真实目标轮廓。我第一次拿到数据集时必做这件事因为标签错位是目标检测数据集里最容易踩的坑之一——肉眼看起来很正常的目录可能因为一张标签文件内容为空而导致训练曲线异常。3.2 核心代码拆解从cv2读取到坐标换算我这里给出与数据集脚本功能等价的实现关键逻辑是解析YOLO格式的txt文件、把归一化坐标换算回像素坐标、再用OpenCV画框import cv2 import os import numpy as np def visualize_yolo_bbox(image_path, label_path, class_names, output_path): # 读取图片注意中文路径需要用 imdecode 处理 img cv2.imdecode(np.fromfile(image_path, dtypenp.uint8), cv2.IMREAD_COLOR) if img is None: print(f无法读取图片: {image_path}) return height, width img.shape[:2] # 读取YOLO格式标签文件 with open(label_path, r, encodingutf-8) as f: lines f.readlines() for line in lines: parts line.strip().split() if len(parts) ! 5: print(f跳过非法行: {line.strip()}) continue class_id int(parts[0]) cx, cy, bw, bh map(float, parts[1:]) # 归一化坐标 - 像素坐标 x1 int((cx - bw / 2) * width) y1 int((cy - bh / 2) * height) x2 int((cx bw / 2) * width) y2 int((cy bh / 2) * height) # 边界框夹紧防止越界 x1, y1 max(0, x1), max(0, y1) x2, y2 min(width - 1, x2), min(height - 1, y2) # 画矩形框和类别标签 color (0, 255, 0) if class_id 0 else (0, 0, 255) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) label_text f{class_names[class_id]} cv2.putText(img, label_text, (x1, max(0, y1 - 5)), cv2.FONT_HERSHEY_SIMPLEX, 1.2, color, 2) # 保存结果用 imencode 避免中文路径问题 cv2.imencode(.jpg, img)[1].tofile(output_path) print(f可视化结果已保存到: {output_path}) if __name__ __main__: class_names [苍蝇, 木虱] # 与数据集的类别顺序保持一致 img_path datasets/images/train/train_001.jpeg label_path datasets/labels/train/train_001.txt visualize_yolo_bbox(img_path, label_path, class_names, visualized_result.jpg)逻辑说明代码先读取图片和同名txt标签对每一行标注做字符串解析然后把归一化的中心点坐标和宽高换算成像素坐标。cx - bw/2和cy - bh/2是把中心点表示转换为左上角表示这是YOLO格式转OpenCV画框时最容易出错的一步。最后按类别ID分配不同颜色苍蝇用绿色、木虱用红色便于区分类别间的目标尺度差异。参数说明class_names列表的顺序必须和标签中的class_id一一对应数据集里的txt类别文本文件写明了第0类是苍蝇、第1类是木虱如果顺序搞反画出来的框颜色和类别名就会错乱。cv2.imdecode(np.fromfile(...))和cv2.imencode这两处是处理中文路径的标准写法Windows系统下直接传路径给cv2.imread会因编码问题读不到图。3.3 看可视化结果时应该关注什么脚本跑完一张图只是第一步我建议在训练集和验证集里各随机抽10到20张图做可视化重点看三件事一是框是否紧贴目标边缘如果框明显偏大或偏小说明标注时存在系统误差二是是否存在漏标目标大图上经常有成群出现的木虱漏标会导致训练时模型把漏标区域当成背景三是类别是否混标苍蝇和木虱在成虫阶段外形差异明显但若虫阶段的木虱体型极小偶尔会被标成苍蝇。4. 训练前的五步自查显存、标签越界、类别混淆与大图处理的避坑指南4.1 坑一大分辨率直接训练显存直接爆炸现象把1000到4000分辨率的原图直接喂给YOLOv5训练batch size设为16一启动就报 CUDA out of memory。原因YOLOv5默认训练时会读取原图再resize到imgsz指定尺寸默认640。但如果data.yaml里配置不当、或者代码里显式传了--imgsz 1280高分辨率大图配合大batch size会消耗数倍显存。1000到4000分辨率的大图宽高比还不固定直接resize到1280后显存占用远高于常规的640输入。解决训练参数保持--imgsz 640即可YOLOv5内部会对原图做等比缩放和letterbox填充不会因为原图分辨率大而增加额外负担。如果你确实需要检测小目标木虱可以先用--imgsz 1280跑几个epoch观察显存占用再把batch size降到4或2。我一般习惯先用640跑通流程确认数据集没问题后再考虑大尺寸微调。4.2 坑二标签坐标越界导致训练loss为nan现象训练到一半 loss 突然变成 nan或者某个类别完全学不出来精度始终为零。原因YOLO格式的标注坐标理论上应在0到1之间但人工标注或格式转换时偶尔会留下越界数据——比如x_center为1.05、width为0.2换算后目标框有一部分超出图片边界。YOLOv5在读取标签时会做合法性校验越界数据可能导致计算图异常或损失函数溢出。解决训练前写一个小脚本扫一遍所有txt标签检查每个数值是否在合理区间内把越界行修复或剔除。检查逻辑很简单import os label_dir datasets/labels for split in [train, val]: split_dir os.path.join(label_dir, split) for txt_name in os.listdir(split_dir): txt_path os.path.join(split_dir, txt_name) with open(txt_path, r) as f: for line_num, line in enumerate(f, 1): parts line.strip().split() if len(parts) ! 5: print(f异常: {split}/{txt_name} 第{line_num}行字段数不为5) continue try: values list(map(float, parts)) except ValueError: print(f异常: {split}/{txt_name} 第{line_num}行含非数值) continue if not (0 values[1] 1 and 0 values[2] 1): print(f越界: {split}/{txt_name} 第{line_num}行中心点越界) if values[3] 0 or values[4] 0: print(f异常: {split}/{txt_name} 第{line_num}行宽高为负)这段代码遍历所有标签文件逐行检查字段数量、数值类型和取值范围。中心点必须在0到1之间宽高必须为正数但允许略微超过1目标可以延伸到图片边缘之外一小段距离不过超过1.1就建议人工复核了。4.3 坑三类别ID和类别名顺序混淆现象训练时显示两个类别但loss下降正常、mAP却一直很低可视化时发现木虱的框画在了苍蝇身上。原因数据集自带的类别顺序是苍蝇在第0位、木虱在第1位但使用者在写data.yaml时把names写反了。YOLOv5训练和推理时的类别索引完全依赖data.yaml里的顺序一旦顺序和标签文件里的class_id不一致整个训练过程等于在学一套错位的映射。解决打开data.yaml确认names顺序和标签文件一致。正确写法参考下面train: datasets/images/train val: datasets/images/val nc: 2 names: [苍蝇, 木虱]注意nc必须等于类别数2names列表长度也必须为2。一个自查技巧随便挑几张训练图跑可视化脚本看画出来的框上标的类别名和肉眼判断是否一致这一步能同时暴露类别顺序和标签错位两个问题。4.4 坑四验证集指标虚高以为模型效果很好现象验证集上mAP达到0.85以上但拿到实地拍摄的照片一测漏检严重尤其是小目标木虱几乎全部丢失。原因这份数据集的60张验证图与训练图来自同一批采集环境背景、光照、拍摄距离高度相似验证集loss低不代表模型学到了泛化能力。这不完全是数据集本身的问题而是所有整理好的数据集都存在的通病——发布方已经帮你划分好了但环境差异大的情况下这个划分并不代表真实场景分布。解决把验证集指标只作为参考训练完成后用自己保留的、来自不同田块或不同时间段的图片做一次独立测试。如果条件不允许至少要把验证集里检测效果最好的几张图拿出来人工看看确认是真正检测对了而不是靠背景先验猜对的。4.5 坑五直接拿280张小图训练忽略大图切块现象训练集240张图训练速度很快但loss下降不明显最终mAP不到0.3。原因240张图看起来少但实际上每张大图上可能有多个害虫实例数据量并不完全等同于图片数量。如果训练时直接整体resize到640大图上的小目标会被压缩到十几个像素特征几乎丢失模型学不到有效信息。解决先用640尺寸训练一个baseline然后尝试--imgsz 1152或更大的尺寸微调。如果显存不够另一个常见做法是把原图切成若干patch再训练但这需要改数据集路径和标签坐标属于进阶操作。这份数据集当前标注是整图级别的直接用官方训练命令即可python train.py --data citrus_pest.yaml --weights yolov5s.pt --img 640 --batch 16 --epochs 1005. 拿到这份数据集后最该做的事先跑一轮完整的数据体检再谈训练5.1 数据体检脚本一次扫完所有隐患每次拿到新的目标检测数据集我都会先跑一遍完整的数据体检流程而不是直接开训。这个习惯是被坑出来的——有一次我花了整整一天训练才发现标签文件和图片文件名对不上原因只是某个图片文件名后缀大小写不一致在Windows上能读到图在Linux上直接爆错。从那以后我每次拿到新数据集都强制走一遍先查文件名对应关系再查标签数值合法性最后统计目标尺寸分布。文件完整性和标签合法性检查可以合并成一个脚本import os from collections import defaultdict base_dir datasets class_count defaultdict(int) size_distribution [] for split in [train, val]: img_dir os.path.join(base_dir, images, split) lbl_dir os.path.join(base_dir, labels, split) img_files set(os.listdir(img_dir)) lbl_files set(os.listdir(lbl_dir)) # 检查图片和标签文件名是否一一对应后缀替换后比较 img_stems {os.path.splitext(f)[0] for f in img_files} lbl_stems {os.path.splitext(f)[0] for f in lbl_files} missing_lbl img_stems - lbl_stems missing_img lbl_stems - img_stems if missing_lbl: print(f[{split}] 缺少标签的图片: {missing_lbl}) if missing_img: print(f[{split}] 缺少图片的标签: {missing_img}) # 统计类别数量和目标尺寸 for lbl_name in lbl_files: lbl_path os.path.join(lbl_dir, lbl_name) with open(lbl_path, r) as f: for line in f: parts line.strip().split() if len(parts) ! 5: continue class_id int(parts[0]) w float(parts[3]) h float(parts[4]) class_count[class_id] 1 size_distribution.append((w, h)) print(f\n类别分布: {dict(class_count)}) print(f目标总数: {len(size_distribution)}) # 小目标占比统计宽或高小于5%图片尺寸的框占比 small_targets sum(1 for w, h in size_distribution if w 0.05 or h 0.05) print(f小目标(宽或高0.05)占比: {small_targets / len(size_distribution) * 100:.1f}%)脚本输出的关键信息包括缺失对应关系的文件名、各类别目标数量、小目标占比。其中小目标占比是决定训练策略的最重要指标——如果这个占比超过40%建议训练时将imgsz提到960以上同时把mAP的置信度阈值调低否则木虱的召回率会非常难看。5.2 验证通用YOLOv5训练流程完全适配数据体检通过后把数据集放到YOLOv5工程目录下或修改data.yaml里的路径为绝对路径按标准流程依次执行# 第一轮用预训练权重快速验证能跑通 python train.py --data citrus_pest.yaml --weights yolov5s.pt --img 640 --batch 16 --epochs 50 # 第二轮精度调优加大输入尺寸和训练轮数 python train.py --data citrus_pest.yaml --weights runs/train/exp/weights/best.pt --img 1152 --batch 8 --epochs 100 --patience 20参数说明第一轮的--weights yolov5s.pt使用COCO预训练模型作为起点比从头训练收敛更快--patience 20表示连续20个epoch验证集指标没提升就提前终止避免无效训练浪费算力。第二轮的--img 1152针对小目标做分辨率增强代价是训练速度明显变慢如果你的GPU显存只有8G建议batch size别超过8。5.3 推理阶段的两个小技巧训练完成后推理时的参数设置直接影响最终检测效果。这份数据集的木虱是小目标建议检测时把conf_thres设低到0.15左右iou_thres设到0.5你会发现召回率比默认参数0.25和0.45高不少代价是误检略有增加python detect.py --weights runs/train/exp/weights/best.pt --source test_images/ --conf-thres 0.15 --iou-thres 0.5这些参数不是玄学而是针对小目标和密集目标场景被反复验证过的组合。建议在自己的验证集上多跑几组参数对比找到精度和召回率的平衡点——通常我会在0.15到0.3之间以0.05为步长做一组小实验结果往往比想当然用默认值好很多。希望这份解析能帮你在柑橘害虫检测这条路上少踩几个坑把时间花在真正重要的模型调优上。本文还有配套的精品资源点击获取
返回列表