简介:谷物害虫目标检测数据集面向粮仓存储环境中的常见害虫自动检测需求,适用于农业AI开发者、智能仓储系统研发人员以及目标检测入门学习者。整包共1376个文件,包含687张实拍害虫图像与687份对应的YOLO格式标注txt,同时附有1个yaml环境配置文件和1个docx数据说明文档,压缩后仅22.76MB,轻量易用,可直接接入YOLOv5、YOLOv8等主流框架进行训练。资源聚焦单一“害虫”类别,边界框定位精准,图片来源于真实谷物环境,覆盖粮堆、仓储设备等实际场景,可有效提升模型泛化能力;配套说明文档帮助快速理解标注规则、数据目录结构与训练配置。借助该数据,开发者可快速构建害虫监测原型,应用于智能粮仓监控、农业机器人视觉系统开发及高校计算机视觉实验教学。该数据集在CSDN已有230人学习,对于缺乏采集条件的团队和初学者,无需重复标注即可快速启动模型训练,是低成本开展农业检测项目与研究的实用选择。
1. 谷物害虫目标检测数据集:687 张 YOLO 标注图,能直接开练还是还要捡垃圾?
做粮食仓储害虫监测,最难的不是训练脚本,而是“第一份数据集去哪找”。常见的公开数据集要么是实验室白底翻拍,要么类别一堆但每类只有几十张,等把格式洗好,半天就过去了。这份谷物害虫目标检测数据集把范围收得很窄:687 张训练图,只标了一个 pest 类别,标注是 YOLO 格式的边界框坐标,图片来自真实农业场景。它解决的是从零攒数据的痛点,而不是算法创新。适合两类人:一类是急着做仓储害虫监测 MVP 验证的工程师,另一类是刚接触目标检测、想拿真实照片练手的学生。单类别、小规模、格式直给,意味着你能在一个下午内把训练流程跑通,把精力留到后面真正难搞的部署环节。
2. 解压后的“长相”:图片命名、YOLO 标注格式与可视化检查
2.1 文件名里的 rf 后缀:Roboflow 导出的“出厂印记”
把 zip 解压后,看到的是09726_jpg.rf.2482cec4343a1a8570d895457b51d36e.jpg、09511_jpg.rf.f2759c021c30e9fc07d030319c195313.jpg这种命名。中间的_jpg表示原图后缀是 JPG,.rf是 Roboflow 的缩写,后面的 32 位 hash 是它在导出时为了防止重名自动生成的唯一编号。也就是说,这份数据集大概率是从 Roboflow 标注平台导出的,而不是某个仓库直接拍摄归档。
这个“出厂印记”带来的问题是,图片顺序被完全打乱,文件名里看不出采集时间、粮库编号或拍摄角度。如果你打算用文件名做 train/val 划分,千万别按字母序前 80% 后 20% 切,因为 hash 不存在语义,随机切才是合理的。我见过一个同事试图把文件名里的数字当作采集顺序,结果发现不同场景的图混在一起,验证集全是同一批图片,训练出来的模型到现场直接翻车。
如果你看不惯这种长文件名,可以批量重命名,但要注意重名风险。常见做法是去掉_jpg.rf.中间段,保留开头数字,但两个不同 hash 的图片可能原始文件名相同,直接改名会导致覆盖。所以我更推荐不重命名,让图片保持原名,只在训练时通过目录结构组织数据集。
文件的另一半是谷物害虫目标检测数据集.docx,这是说明文档。摘要里写的是 YOLO 格式标注,但 zip 内文件列表里只直接看到了 .jpg 和 .docx,没直接看到 .txt。遇到这种情况别急着删包,先打开 docx:发布方可能把标注格式规范写在了文档里,真正的 txt 标注可能和图片一起躺在某个子目录,也可能需要你根据文档补标注文件。下面的检查步骤,我默认图片和同名 txt 在同一目录。
2.2 YOLO 标注格式的五个数字:归一化坐标、中心点与单类别 ID
YOLO 格式的每个 txt 文件与图片同名,一行对应一个目标,内容是五个数字:class x_center y_center width height。class 是类别序号,从 0 开始;这份数据集只有 pest 一类,所以这一位固定是 0。后面四个数字全部是归一化后的相对坐标,取值范围 0 到 1。x_center、y_center 是边界框中心点相对于图片宽高的比例,width、height 是边界框宽高相对于图片宽高的比例。注意不是左上角坐标,也不是像素值。
很多新手第一次写 YOLO 数据集标注时,会把像素坐标直接写进 txt,比如0 500 300 120 80。这种写法在训练时 loss 会非常大,甚至变成 nan,因为模型期望 0-1 之间的值。反过来,如果你拿到一份标注,发现 width 或 height 大于 1,那基本可以确定是像素坐标没有归一化,需要先做转换再训练。
用脚本扫一遍标注文件,能快速判断格式是否干净:
from pathlib import Path label_dir = Path("./labels") for label_path in sorted(label_dir.glob("*.txt")): objs = [] for line in label_path.read_text().splitlines(): line = line.strip() if not line: continue parts = line.split() if len(parts) != 5: print(f"坏行: {label_path.name}: {line}") continue cls = int(parts[0]) xc, yc, w, h = map(float, parts[1:]) objs.append((cls, xc, yc, w, h)) print(f"{label_path.name}: {len(objs)} 个目标")这段脚本的逻辑很直接:用splitlines()按行拆,跳过空行;用split()按空格拆,所以多个空格或 Tab 也能处理;长度不是 5 的行直接打印出来。最后统计每个 txt 的目标数。正常情况下,一张谷物害虫图片里会有 1 到 10 个不等的目标。如果你发现某个 txt 有 100 个目标,也别慌,可能那张图是害虫虫口爆发的特写,但这种极端样本在训练集里占比过高会让模型对目标数量产生倾向,最好单独拎出来看看。
2.3 可视化检查:把标注框画回图片,比盯数字直观一百倍
数字检查只能判断格式,不能判断框的位置是否准确。我会把标注画回原图,随机翻几十张,人工确认框有没有偏、有没有少标。这个习惯能让后面少走很多弯路。常见做法是用 OpenCV 画矩形,再用 Matplotlib 展示:
import cv2 import matplotlib.pyplot as plt from pathlib import Path def draw_label(img_path: Path, label_path: Path): img = cv2.imread(str(img_path)) if img is None: print(f"读不到图片: {img_path}") return h, w = img.shape[:2] for line in label_path.read_text().splitlines(): parts = line.strip().split() if len(parts) != 5: continue cls, xc, yc, bw, bh = parts xc, yc, bw, bh = map(float, (xc, yc, bw, bh)) # YOLO 存的是中心点坐标,画框要换算成左上角和右下角 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.putText(img, f"pest {cls}", (x1, max(0, y1 - 6)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1) plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) plt.axis("off") plt.show() img_path = Path("./images/09726_jpg.rf.2482cec4343a1a8570d895457b51d36e.jpg") draw_label(img_path, img_path.with_suffix(".txt"))这段脚本里有一个地方最容易错,就是坐标换算。YOLO 给的 x_center、y_center 是中心点,而 OpenCV 的 rectangle 需要左上角和右下角,所以要先拿中心点减宽高一半得到左上角,再加宽高得到右下角。另外 cv2.imread 读进来是 BGR 顺序,Matplotlib 按 RGB 显示,不转换的话整张图颜色会偏蓝偏橙,影响你判断害虫体色。我一般一次抽查 20 到 30 张,覆盖不同文件名开头的样本。如果发现某张图里的框整体偏左上或偏右下,优先怀疑 txt 里的坐标顺序不是x_center y_center width height,而是别的变体。
3. 用 YOLOv5 训练这份数据集:目录划分、data.yaml 与训练参数
3.1 先按 train/val 把 687 张图切好,别把验证集扔在一边不管
YOLOv5 和 YOLOv8 默认都要求数据按images/train、images/val、labels/train、labels/val分目录放。这份数据集只声明了 687 张训练图,没有给出官方验证集划分,所以我们要自己动手。划分的原则是随机,但随机前先确认图片之间没有同场景连续拍摄的“亲戚关系”,否则验证集会泄漏。
做个最简单的 85/15 划分:
import random from pathlib import Path random.seed(42) img_dir = Path("./images") label_dir = Path("./labels") img_files = sorted(img_dir.glob("*.jpg")) label_files = {p.stem: p for p in label_dir.glob("*.txt")} random.shuffle(img_files) val_count = int(len(img_files) * 0.15) val_files, train_files = img_files[:val_count], img_files[val_count:] for subset, files in [("train", train_files), ("val", val_files)]: img_out = Path("./dataset/images") / subset label_out = Path("./dataset/labels") / subset img_out.mkdir(parents=True, exist_ok=True) label_out.mkdir(parents=True, exist_ok=True) for img_path in files: label_path = label_files.get(img_path.stem) if label_path is None: print(f"缺少标注,跳过: {img_path.name}") continue img_path.rename(img_out / img_path.name) label_path.rename(label_out / label_path.name)这里的random.seed(42)是为了让每次划分结果一致,方便复现实验结果。哈希文件名本身没有语义,所以直接用随机打乱没问题。label_files先按文件名建索引,再通过img_path.stem去查,比在循环里拼路径再判存在要快,也避免因 hash 后缀不一致导致找不到标注。注意,如果运行后提示某个图片缺少标注,不要直接忽略。小数据集的每一张坏图都会影响最终精度,先回到第 2 章的检查脚本,确认是 txt 真的缺失,还是文件名前缀对不上。我见过最坑的情况是,图片名是09726_jpg.rf.xxx.jpg,而 txt 名是09726.txt,如果没有用 stem 而是简单 replace 后缀,就会漏掉一半样本。
3.2 data.yaml 怎么写:类别顺序、路径与中文名陷阱
训练前需要准备一个 data.yaml。单类数据集非常简单:
# dataset.yaml train: ./dataset/images/train val: ./dataset/images/val nc: 1 names: 0: pesttrain 和 val 的路径是相对你执行训练命令的目录的。如果开启了--cache,相对路径也没问题,但我更建议直接写绝对路径,尤其当你把数据集放在项目外目录时。路径里不要有空格和中文,否则 OpenCV 读取图片可能静默失败。nc必须等于 1,names列表的顺序要和 txt 里的类别 ID 一一对应。这份数据集只有 pest 一类,txt 第一位数固定为 0,所以 names 的第一项必须是 pest。如果你把 names 写成['pest', 'rice'],而 nc 还是 1,YOLO 不会立刻报错,但训练时类别标签矩阵尺寸对不上,mAP 会一直是 0,这种错最恶心。
另外,说明文档 docx 可能是中文写的,但不要因为“看起来方便”就把类别名写成中文。一方面 Matplotlib 在画混淆矩阵时对中文字体支持不好,轻则豆腐块,重则直接抛异常;另一方面,一些部署端对中文类别名支持不全。统一用 pest 这类英文 id,前端展示时再做映射。
3.3 训练命令:8G 显存、CPU 和显存卡脖子时的选择
YOLOv5 的 train.py 参数很多,我建议的第一版命令是:
python train.py \ --img 640 \ --batch 16 \ --epochs 100 \ --data dataset.yaml \ --weights yolov5s.pt \ --patience 20 \ --cache逐个说参数。--img 640是训练时把输入图缩放到 640x640。害虫在原始照片里可能很小,但如果直接怼到 1280,显存占用接近 4 倍,训练速度明显下降,所以先用 640 跑通。--batch 16在 8G 显存下比较稳,如果你的显卡只有 6G,降到 8;如果是 24G,可以提到 32。--epochs 100对小数据集够用,配合--patience 20,连续 20 轮验证集指标不涨就自动停止。--weights yolov5s.pt从 COCO 预训练权重继续训练,比从空白网络收敛快很多。--cache把图片一次性载入内存,687 张图大概几百 MB,完全能接受,可以省掉训练中的磁盘 IO。
如果只有 CPU,命令要改几个参数:
python train.py --img 640 --batch 4 --epochs 50 --data dataset.yaml --weights yolov5s.pt --device cpuCPU 训练不是不能跑,但 687 张图一个 epoch 可能要几分钟,50 个 epoch 已经需要好几个小时。不要用 yolov5x 这种大模型,CPU 上跑基本是自讨苦吃。先跑通流程,拿到一个能用的权重,再用 GPU 或云服务去精调。
3.4 训练输出怎么看:loss 曲线要分开看,P/R 比 mAP 更诚实
训练结束后,结果都在runs/train/exp/下。YOLOv5 会把每个 epoch 的指标写进 results.csv,文件头是 epoch、train/box_loss、train/obj_loss、metrics/precision、metrics/recall、metrics/mAP_0.5 等。用一段小脚本直接看最后一行:
import csv with open("runs/train/exp/results.csv") as f: rows = list(csv.DictReader(f)) last = rows[-1] print("epoch:", last["epoch"]) print("P:", last["metrics/precision"]) print("R:", last["metrics/recall"]) print("mAP50:", last["metrics/mAP_0.5"]) print("box_loss:", last["train/box_loss"])不要只盯 mAP。单类目标检测场景里,precision 高、recall 低,说明模型很保守,只有非常有把握的框才输出,这会漏掉很多小而模糊的害虫;recall 高、precision 低,说明模型把谷物碎粒、灰尘区域也当成 pest,误检一大堆。对应到部署,粮库告警系统在乎误报多少,所以 precision 更重要;而科研统计害虫密度,recall 更重要。你需要根据用途决定以哪个指标为主,而不是看到 mAP50 上 0.8 就觉得万事大吉。
如果发现 box_loss 降得很慢,先别急着加训练轮次,回去检查 data.yaml 和标注。就我的经验,YOLO 训练上 80% 的问题出在数据本身,只有 20% 出在参数。
4. 687 张图想跑出可用模型:数据增强、超参与过拟合控制
4.1 单类检测的真正难点:不是分错类,而是把杂物当害虫
很多做多类别检测的人刚转过来会不适应:单类模型没有“分错类别”的错误模式,所有输出框都叫 pest,所以它的错误只剩两种——该框的没框出来,和不该框的框出来了。谷物害虫场景里,背景里的谷壳、碎米粒、灰尘团,在 YOLO 特征层看来和害虫幼虫的形状高度相似,于是误检会特别多。
训练集只有 687 张,覆盖不了现场所有光线和背景,所以第一版模型大概率会在验证集上表现不错、在实拍画面上误检。这不一定是标注问题,而是正样本太少、背景多样性不够。常用的补救办法是数据增强和阈值控制,而不是立刻去标几千张新图。我的习惯是先用增强把模型本身压榨到位,再考虑半自动标新数据,这套流程留到第 6 章展开。
4.2 YOLOv5 增强超参:mosaic、HSV 与翻转怎么调
YOLOv5 在data/hyps/hyp.scratch-low.yaml里定义了一组增强超参,训练时用--hyp指定。针对谷物害虫这种小数据集,我通常会先维持默认,只重点关注下面几项:
mosaic: 0.8 hsv_h: 0.015 hsv_s: 0.4 hsv_v: 0.4 degrees: 0.0 translate: 0.1 scale: 0.3 fliplr: 0.5mosaic 是将四张训练图拼成一张再训练,等于把样本组合扩大了 4 倍,对小目标和小数据集都有帮助,我一般会保持 0.8 起步,不改成 0。hsv_h 是色相扰动,0.015 很小,因为米虫子颜色差异有限,调太大会让害虫变成蓝色;hsv_s 和 hsv_v 可以放大一点,模拟不同粮仓灯光下的饱和度和明暗变化。degrees 旋转增强我会保持 0.0,谷物害虫图片中摄像头安装方向相对固定,虫子姿势虽然乱,但训练数据本身已经包含了各种角度,额外旋转反而会让模型浪费参数去学“倒着的虫子”。fliplr 水平翻转 0.5 是安全的,虫子的左右没有物理意义。
如果想快速验证增强效果,可以单独复制一个 hyp 文件,改几个值再对比。常见做法是先把degrees: 0.0不动,把scale: 0.3改大,让模型见过更多尺度变化,因为仓储摄像头的安装高度在不同仓库不一样。但要注意,scale 调太大,小目标会被缩得更小,害虫可能直接消失,导致标注框在增强后几乎是空心的负样本,效果反而变差。
4.3 训练轮次、批次与早停:小数据集怎么防过拟合
687 张图跑 300 个 epoch 明显会过拟合。YOLOv5 默认 300 是给大数据集设计的,换成这份数据集,我建议用表里的配置起步。
| 参数 | 建议值 | 说明 |
|---|---|---|
| --img | 640 | 先用标准分辨率跑通,再看小目标情况 |
| --batch | 16 | 8G 显存稳定,6G 减半 |
| --epochs | 100 | 给足余量,配合早停 |
| --patience | 20 | 连续 20 轮验证集不上升就停 |
| --cos-lr | 开启 | 余弦退火,小数据集收敛更平滑 |
--patience 20有一个容易被忽略的作用:如果你忘了设 epochs,它会帮你兜底。开启--cos-lr后学习率会在训练后半段平滑下降,避免在极小数据集上来回震荡。还有一个常见选项是--multi-scale,让输入尺寸在 640 的 0.5 到 1.5 倍之间随机变化,等价于尺度增强。我一般在小目标项目里会开启,但它会拖慢训练速度,且需要更大的 batch 才稳定,第一版可以先不开。
如果训练到 30 个 epoch 时训练 loss 还在降、验证 loss 已经不降甚至上升,那就是过拟合开始了。此时不要盲目砍增强,先看是不是 mosaic 概率太低、或者是数据集里同一张图的重复变体太多。在 687 张图的小数据集上,把早停耐心值调小比硬调参数更节省时间。
5. 避坑指南:谷物害虫数据集从解压到部署的高频翻车现场
5.1 图片和 txt 对不上:hash 重命名导致匹配失败
现象:训练启动时,终端刷出一堆WARNING: Inferring label file from image或label file ... not exists,损失一直不降,或者明明有 687 张图,实际参与训练只有 400 多张。
原因:Roboflow 导出的图片名和 txt 名是根据同一个 hash 生成的,理论上一一对应,但如果你从网盘下载 zip 时文件名被截断,或者本地解压工具把某些特殊字符改掉,图片和 txt 的关联就断了。还有一种情况是第 2 章提过的,发布方只贴了图片清单,txt 在子目录里没被解压路径覆盖。
解决:先统计缺失,再决定是否手动配对。用 bash 一行命令就能查:
for f in images/*.jpg; do [ -f "labels/$(basename "$f" .jpg).txt" ] || echo "missing: $f" done如果缺失只有十几张,直接用第 2 章的脚本人工核对;如果缺失超过一半,就要怀疑数据集本身不完整。要知道,20% 的坏样本会让模型精度下降一个档次,所以在数据集阶段花半小时检查,比训练跑一夜后才发现白跑要划算。
5.2 训练时 loss 为 nan 或坐标越界:txt 里混进了逗号和空行
现象:训练启动后 loss 直接变nan,或者训练完成但可视化框全部堆在图片边缘,mAP 为 0。
原因:标注 txt 里有些行用逗号分隔,比如0,0.5,0.5,0.3,0.2,有些行坐标是像素值,有些行末尾带空行。YOLO 的数据加载器是按空格切词的,逗号行会被当成一个整体,坐标解析错位;空行虽然不会崩,但会让加载器困惑。像素坐标写进训练,框的自然分布和真实位置差很远。
解决:写一个清洗脚本,把逗号替换成空格、过滤空行、标记越界值:
from pathlib import Path for label_path in Path("labels").glob("*.txt"): lines = [] for raw in label_path.read_text().splitlines(): row = raw.replace(",", " ").strip() if not row: continue parts = row.split() if len(parts) != 5: print(f"坏行: {label_path.name}: {raw}") continue cls, xc, yc, w, h = map(float, parts) if not (0 <= xc <= 1 and 0 <= yc <= 1 and 0 <= w <= 1 and 0 <= h <= 1): print(f"坐标越界: {label_path.name}: {raw}") lines.append(" ".join(parts)) label_path.write_text("\n".join(lines) + "\n")清洗完之后再跑一遍第 2 章的统计脚本,确保每个 txt 都是合法五列。这里注意,w和h理论上可以大于 1 但绝不合法,因为边界框不可能比图还宽;如果你看到 width=0.5, x_center=0.75 的框,虽然数值合法,但框已经出右边界了,这种样本用于训练会抑制边框回归。极少数可以容忍,数量多了必须修。
5.3 验证集 mAP 很高,实拍画面一个都检不出来:验证集划分方式背锅
现象:训练日志里 mAP50 到 0.85,满心欢喜把 best.pt 接到摄像头测试,结果实际画面里害虫在眼前都不报警,或者报警全是误报。
原因:最常见的是验证集和训练集来自同一批图片的随机切分,特征分布高度重合。另一个原因是这张数据集的 hash 文件名没有场景信息,你无法保证验证集包含独立场景。模型在类似背景上见过目标,换个仓库灯光和背景就认不出了。
解决:如果有可能,按采集批次或拍摄条件分组划分,而不是随机划分。一个可行的做法是把文件名里的数字段取出来,按某种语义分组;但这份数据集的 hash 段没有语义,所以更稳妥的做法是准备一小批独立实拍图作为最终测试集。这个测试集不参与训练,也不参与验证集,只放在最后测试。每次训练完都拿它跑一轮,记录 P/R,而不是只看验证集指标。我在实际项目里的标准是:验证集 mAP50 至少 0.8,独立测试集 recall 至少 0.6,才允许考虑部署。
5.4 换成 YOLOv8 之后训练崩了:data.yaml 路径和类别顺序的坑
现象:同样的标注,YOLOv5 跑得好好的,换到 YOLOv8 训练,要么加载数据时提示 images not found,要么训练能跑但验证指标全是 0。
原因:YOLOv8 对 data.yaml 的解析方式和 YOLOv5 略有不同,它更严格地遵循相对路径基准,如果 yaml 里写train: ./dataset/images/train,而这个路径是相对你执行yolo命令的目录,换一个终端运行就找不到。类别顺序问题也一样,txt 里 class 0 对应 names 第一项,一旦 names 写错顺序,单类可能看不出来,多类扩展时直接炸。
解决:在 data.yaml 里写绝对路径,或者先cd到数据集所在目录再执行训练命令:
cd /path/to/yolov8 yolo detect train data=/absolute/path/dataset.yaml model=yolov8s.pt epochs=50 imgsz=640如果已经训练完但指标是 0,先用yolo detect predict model=best.pt source=test.jpg save=True看推理结果,而不是反复调超参。一张可视化输出就能告诉你,到底是模型没学进去还是标注压根没被读到。
5.5 害虫目标太小:640 分辨率下漏检严重,先别急着上大模型
现象:训练指标不错,但把权重部署到边缘设备后,小目标害虫在画面上只有 10 到 20 像素,模型经常漏检,尤其在画面远处。
原因:YOLOv5s 在 640 输入下,下采样到 20x20 的特征图负责大目标,害虫这种小目标主要靠 80x80 的特征图,但分辨率仍然有限。模型 depth 和 width 加大并不会自动解决小目标问题,反而可能让浅层特征被压缩。
解决:先把推理输入分辨率提到 960,代价是速度变慢、显存变高,但通常立竿见影:
python train.py --img 960 --batch 8 --epochs 100 --data dataset.yaml --weights yolov5s.pt如果分辨率已经顶到显存上限还是漏检,下一招是切图检测:把原图按 50% 重叠切成四块,分别送进模型,再把结果合并。这个做法在谷物害虫这种目标密度不高的场景里很实用,代价是推理耗时变成四倍,适合离线分析或低帧率巡检。更系统的做法是引入新的实拍数据做增量训练,下面这章说这个。
6. 进阶:用训练好的权重做半自动标注,扩充自己的实拍数据
6.1 预标注 + labelImg 人工修正
当你从自己的粮库或实验室拍回一批新照片后,最快的扩数据方式不是从零画框,而是让已经训好的模型先给出候选框。YOLOv8 的 predict 接口一次就能导出 YOLO 格式标注。举例:
from ultralytics import YOLO model = YOLO("runs/train/exp/weights/best.pt") model.predict(source="new_photos/", conf=0.6, save_txt=True, save_conf=False, imgsz=960)save_txt=True会把每个图片的预测结果写到runs/detect/predict/labels/下,文件名和图片同名,内容就是cls xc yc w h。因为模型是单类 pest,cls 永远是 0,这个 txt 可以直接拷到新数据的 labels 目录里。conf 设 0.6 是为了只输出高置信度框,宁可少预标也别给 labelImg 塞一堆假框。接着用 labelImg 打开图片,选择 YOLO 格式模式,会直接加载这些预标注框,你只需要修正漏掉的框和多余的误检。
6.2 增量训练与验证
标注修正完成后,把新数据按第 3 章的方法并入训练集,重新划分 train/val,再用上一轮 best.pt 做增量训练。重点是不能用 COCO 预训练权重从头来,因为那会丢掉已经学会的仓储害虫特征。
python train.py --weights runs/train/exp/weights/best.pt --data dataset2.yaml --epochs 30 --img 640 --batch 16 --patience 10epochs 30 就够,增量阶段数据量小,跑太多反而把旧知识覆盖。如果新数据里出现了新的害虫种类,比如从只有 pest 扩到 weevil 和 moth,就要修改 data.yaml 的 nc 和 names,同时检查新标注的类别 ID 从 1 开始,旧的 pest 保持 0。然后准备一份完全没参与过训练和验证的测试集,把增量前后的 P 和 R 打印出来对比,不要只看 mAP。
从那以后,我每接一个农业检测项目,都会强制自己先做两件事:第一步把标注文件全部扫一遍,确认没有坏行;第二步建一个独立场景测试集,跟训练集永远不沾边。这次跑谷物害虫数据集也一样,前几次翻车全是因为我跳过了这两步。这套流程看起来多花一两个小时,但后面省下来的返工时间不是以小时计的。希望帮到你。
本文还有配套的精品资源,点击获取