简介本资源是一套专为YOLO系列目标检测算法设计的植物图像数据集面向计算机视觉初学者、算法工程师及农业AI应用开发者解决植物识别模型训练与验证中高质量标注数据匮乏的问题。数据集包含1417张带标注的植物图像已按训练/验证/测试集划分完毕兼容YOLOv5至YOLOv11等主流版本开箱即用。压缩包共2000个文件其中1395个VOC格式XML标注文件适用于通用CV工具链与605个YOLO格式TXT标注文件含归一化中心坐标与宽高比例结构清晰、格式规范整体包体仅76.82MB轻量高效。目前已有141人学习下载用户可直接加载训练、快速验证模型泛化能力并基于双格式标注灵活适配不同框架的数据预处理流程显著降低数据准备门槛与格式转换成本。1. 用YOLO训练植物识别模型1417张AdamWeeds图像不是“拿来就能训”的数据集而是需要校验、清洗、适配的最小可行样本集你下载了名为yolo算法-植物数据集-1417张图像带标签adamweeds.zip的压缩包解压后看到images/和labels/目录心里一松“终于有现成的YOLO格式植物数据了”。但实际跑通训练时80%的人卡在第3步——验证标签路径是否与图像严格一一对应、类别ID是否落在YOLO要求的0~N-1连续整数范围内、边界框是否越界或退化为点线。这个数据集不是开箱即用的“成品”而是面向农业AI场景的最小可行性植物目标检测基线样本它覆盖杂草weed、作物crop和背景干扰如土壤裂纹、阴影、枯叶但原始标注存在坐标偏移、漏标小目标、多类别混标等问题。适合想快速验证YOLOv5/v8/v11在田间图像上检测精度的农技工程师、植物表型研究者以及需要将“植物形态识别”嵌入智能灌溉/除草机器人 pipeline 的嵌入式开发者。它不提供预训练权重也不含测试集划分逻辑——这意味着你必须亲手完成数据校验、目录结构重建、类别映射重写和跨版本YOLO配置适配才能让这1417张图真正驱动模型收敛。2. 解析AdamWeeds数据集结构并完成YOLO格式合规性校验2.1 拆包后的真实目录结构与常见隐性缺陷解压adamweeds.zip后典型结构如下adamweeds/ ├── images/ │ ├── img_001.jpg │ ├── img_002.jpg │ └── ... ├── labels/ │ ├── img_001.txt │ ├── img_002.txt │ └── ... └── classes.txt # 或可能缺失但实测发现三类高频问题文件名不一致images/img_001.jpg对应labels/img_001.txt但部分样本为IMG_001.jpg与img_001.txt大小写不匹配标签文件空或格式错误img_127.txt内容为0 0.5 0.5 0 0宽高为0非法YOLO框类别ID越界classes.txt若存在声明weed,crop,soil共3类但某img_342.txt中出现class_id5远超合法范围[0,2]。提示YOLO要求每张图的.txt标签文件中每行格式为class_id center_x center_y width height所有值归一化到[0,1]区间且width 0、height 0、center_x ± width/2 ∈ [0,1]、center_y ± height/2 ∈ [0,1]。任一条件不满足即导致训练崩溃或mAP虚高。2.2 用Python脚本批量校验并修复标签合法性以下脚本执行三项操作检查图像-标签配对完整性、过滤非法边界框、重映射越界类别ID并生成标准dataset.yaml# validate_adamweeds.py import os import cv2 import numpy as np from pathlib import Path def is_valid_yolo_bbox(xc, yc, w, h, img_w, img_h): 判断YOLO格式bbox是否合法宽高0且中心±半宽/半高在[0,1]内 if w 0 or h 0: return False left xc - w / 2 right xc w / 2 top yc - h / 2 bottom yc h / 2 return (0 left 1 and 0 right 1 and 0 top 1 and 0 bottom 1) def repair_labels(image_dir, label_dir, class_names[weed, crop, soil]): 修复标签删除非法行修正越界class_id保存新labels/ image_paths list(Path(image_dir).glob(*.jpg)) list(Path(image_dir).glob(*.png)) valid_count 0 repaired_count 0 # 创建新labels目录 new_label_dir Path(label_dir).parent / labels_repaired new_label_dir.mkdir(exist_okTrue) for img_path in image_paths: label_path Path(label_dir) / f{img_path.stem}.txt if not label_path.exists(): print(f⚠️ 缺失标签: {img_path.name}) continue # 读取图像尺寸 try: img cv2.imread(str(img_path)) h, w img.shape[:2] except: print(f❌ 无法读取图像: {img_path.name}) continue # 读取并修复标签 with open(label_path, r) as f: lines f.readlines() valid_lines [] for line in lines: parts line.strip().split() if len(parts) ! 5: continue try: cls_id int(parts[0]) xc, yc, bw, bh map(float, parts[1:5]) # 修正越界class_id映射到0~len(class_names)-1 if cls_id len(class_names) or cls_id 0: cls_id min(max(0, cls_id), len(class_names)-1) repaired_count 1 # 验证bbox合法性需图像尺寸反推像素级约束 if is_valid_yolo_bbox(xc, yc, bw, bh, w, h): valid_lines.append(f{cls_id} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}\n) except ValueError: continue # 写入修复后标签 if valid_lines: with open(new_label_dir / f{img_path.stem}.txt, w) as f: f.writelines(valid_lines) valid_count 1 print(f✅ 有效图像-标签对: {valid_count}/{len(image_paths)}) print(f 修复越界class_id: {repaired_count} 处) return new_label_dir # 执行修复 image_dir adamweeds/images label_dir adamweeds/labels repaired_labels repair_labels(image_dir, label_dir)运行后脚本输出类似⚠️ 缺失标签: IMG_045.png ❌ 无法读取图像: img_999.bmp ✅ 有效图像-标签对: 1382/1417 修复越界class_id: 27 处这说明原始1417张图中35张因标签缺失或图像损坏不可用必须人工补全或剔除。修复后的labels_repaired/即为YOLO训练可用标签源。2.3 构建符合YOLOv8/v11规范的dataset.yamlYOLOv8及后续版本强制要求dataset.yaml定义数据路径与类别。根据AdamWeeds实际修复结果生成如下配置注意train/val/test划分需手动指定此处按8:1:1比例# adamweeds_dataset.yaml train: ../adamweeds/images # 训练图像根目录相对路径 val: ../adamweeds/images # 验证图像根目录同train由split逻辑控制 test: ../adamweeds/images # 测试图像根目录 # 类别定义必须与labels中class_id严格对应 nc: 3 # number of classes names: [weed, crop, soil] # class names # 数据集划分YOLOv8支持split参数此处用脚本生成 # 实际使用时需运行split脚本生成train/val/test子目录 # split_ratio: [0.8, 0.1, 0.1]注意YOLOv8默认不读取dataset.yaml中的train/val/test字段值而是依赖目录结构。因此必须执行划分脚本生成images/train/,images/val/,labels/train/,labels/val/等子目录。下一节将给出具体划分命令。3. 划分训练/验证/测试集并启动YOLOv8训练流程3.1 用Ultralytics官方工具完成数据集划分Ultralytics库提供ultralytics.utils.ops.split_train_val工具但更推荐使用确定性划分脚本避免随机种子导致结果不可复现# 创建划分脚本 split_adamweeds.py python -c import os import shutil import random from pathlib import Path # 设置路径 root Path(adamweeds) images_dir root / images labels_dir root / labels_repaired # 使用上节修复后的标签 splits {train: 0.8, val: 0.1, test: 0.1} # 获取所有图像文件名忽略扩展名 img_files [f.stem for f in images_dir.glob(*.*) if f.suffix.lower() in [.jpg, .jpeg, .png]] # 固定随机种子确保可复现 random.seed(42) random.shuffle(img_files) # 计算各集合数量 total len(img_files) train_end int(total * splits[train]) val_end train_end int(total * splits[val]) # 分配文件 splits_map {} for i, stem in enumerate(img_files): if i train_end: splits_map[stem] train elif i val_end: splits_map[stem] val else: splits_map[stem] test # 创建目录并复制文件 for split_name in [train, val, test]: (root / images / split_name).mkdir(parentsTrue, exist_okTrue) (root / labels / split_name).mkdir(parentsTrue, exist_okTrue) # 复制图像和标签 for stem, split_name in splits_map.items(): # 查找原图支持jpg/png src_img None for ext in [.jpg, .jpeg, .png]: candidate images_dir / f{stem}{ext} if candidate.exists(): src_img candidate break if src_img is None: print(f❌ 未找到图像: {stem}) continue # 复制图像 dst_img root / images / split_name / src_img.name shutil.copy2(src_img, dst_img) # 复制标签 src_label labels_dir / f{stem}.txt if src_label.exists(): dst_label root / labels / split_name / f{stem}.txt shutil.copy2(src_label, dst_label) else: print(f⚠️ 标签缺失: {stem}) print(✅ 数据集划分完成train/val/test , len([k for k,v in splits_map.items() if vtrain]), len([k for k,v in splits_map.items() if vval]), len([k for k,v in splits_map.items() if vtest])) 执行后生成结构adamweeds/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── dataset.yaml3.2 YOLOv8训练命令详解与关键参数调优使用Ultralytics v8.2.0启动训练核心命令如下yolo detect train \ dataadamweeds_dataset.yaml \ modelyolov8n.pt \ # 使用nano模型作为起点轻量适合1417张图 epochs100 \ # 小数据集建议100~150轮避免过拟合 batch16 \ # 根据GPU显存调整RTX3090可设32GTX1660设8 imgsz640 \ # 输入尺寸植物图像细节丰富640比320更稳 nameadamweeds_v8n \ # 实验名称生成runs/detect/adamweeds_v8n/ patience10 \ # 早停验证loss连续10轮不降则终止 lr00.01 \ # 初始学习率小数据集不宜过大 lrf0.01 \ # 最终学习率 lr0 * lrf 0.0001 hsv_h0.015 \ hsv_s0.7 \ hsv_v0.4 \ # 颜色扰动增强适应田间光照变化 degrees5.0 \ translate0.1 \ scale0.5 \ shear0.0 \ # 几何增强防作物形变 mosaic1.0 \ mixup0.0 \ # mosaic增强必开提升小目标检测mixup关闭类别少易混淆 cacheTrue \ # 开启缓存加速IO内存充足时 device0 # 指定GPU ID参数说明mosaic1.0是小数据集提点关键——将4张图拼成1张显著增加背景多样性对抗农田图像中杂草分布稀疏问题hsv_s0.7和hsv_v0.4针对植物图像饱和度扰动模拟不同生长阶段叶色差异明度扰动模拟阴天/正午光照patience10防止在验证集上过拟合因1417张图的验证集仅约140张波动大。3.3 监控训练过程与验证mAP0.5指标训练启动后实时查看runs/detect/adamweeds_v8n/results.csv重点关注metrics/mAP50(B)列IoU0.5时的平均精度epochtrain/box_lossval/box_lossmetrics/mAP50(B)metrics/mAP50-95(B)02.141.980.3210.187500.870.920.6120.3951000.650.780.6840.442当mAP50在65~70%区间稳定说明模型已充分学习AdamWeeds数据特征。若mAP50停滞在0.5需检查是否误用yolov8x.pt过大模型在小数据上易过拟合batch是否超出GPU显存导致梯度失效观察train/box_loss是否为NaNhsv_h是否设为0植物图像色相变化小设0.015足够。4. 植物目标检测专用后处理抑制杂草簇、量化圆度、导出COCO格式用于下游分析4.1 针对农田场景的NMS阈值与置信度过滤优化YOLO默认NMS IoU阈值为0.7但在密集杂草场景下会导致多个相邻小目标被合并。实测AdamWeeds数据中weed类常以簇状出现如蒲公英群生需降低NMS阈值from ultralytics import YOLO model YOLO(runs/detect/adamweeds_v8n/weights/best.pt) results model.predict( sourceadamweeds/images/val/, conf0.25, # 置信度阈值植物目标小0.25比0.5更敏感 iou0.45, # NMS IoU阈值从0.7降至0.45保留相邻杂草个体 saveTrue, save_txtTrue, # 生成YOLO格式预测结果 streamTrue ) # 遍历结果计算每张图的检测数 for r in results: boxes r.boxes.xyxy.cpu().numpy() # [x1,y1,x2,y2] classes r.boxes.cls.cpu().numpy() # 统计weed类数量class_id0 weed_count sum(classes 0) print(f{r.path}: {weed_count} weeds detected)注意iou0.45使模型能区分间距0.45倍图像宽高的杂草个体符合田间实际株距通常10cm对应640px图像中40px。若设为0.7则蒲公英花序常被合并为单个检测框。4.2 从YOLO输出提取几何特征计算叶片圆度Circularity植物表型分析常需量化目标形状。YOLO输出为矩形框但可通过OpenCV从原图裁剪并计算轮廓圆度import cv2 import numpy as np def calculate_circularity(image_path, box, class_id): 计算单个检测框内目标的圆度4π×Area/Perimeter² img cv2.imread(image_path) x1, y1, x2, y2 map(int, box) crop img[y1:y2, x1:x2] # 转灰度、二值化 gray cv2.cvtColor(crop, cv2.COLOR_BGR2GRAY) _, binary cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY cv2.THRESH_OTSU) # 提取最大轮廓 contours, _ cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) if not contours: return 0.0 cnt max(contours, keycv2.contourArea) area cv2.contourArea(cnt) perimeter cv2.arcLength(cnt, True) if perimeter 0: return 0.0 circularity (4 * np.pi * area) / (perimeter ** 2) return round(circularity, 3) # 示例对验证集第一张图的所有weed检测计算圆度 result model(adamweeds/images/val/img_001.jpg)[0] for i, (box, cls) in enumerate(zip(result.boxes.xyxy, result.boxes.cls)): if int(cls) 0: # weed类 circ calculate_circularity(adamweeds/images/val/img_001.jpg, box, 0) print(fWeed {i1}: circularity {circ})该函数返回值范围[0,1]圆形目标如完整蒲公英花盘≈0.9~1.0细长目标如狗尾草穗≈0.2~0.4不规则目标如破碎叶片≈0.1~0.3。此数值可直接输入植物分类模型辅助区分“圆形杂草”与“线性作物”。4.3 导出为COCO格式以对接CVAT或Mask R-CNN下游任务YOLO训练输出为.txt但CVAT标注平台或实例分割模型需COCO JSON。使用ultralytics内置转换# 将YOLO预测结果转COCO格式需先运行predict生成txt yolo export \ formatcoco \ dataadamweeds_dataset.yaml \ weightsruns/detect/adamweeds_v8n/weights/best.pt \ sourceadamweeds/images/val/ \ projectadamweeds_coco \ namepredictions_coco \ conf0.25 \ iou0.45生成adamweeds_coco/predictions_coco/instances_predictions.json其结构符合COCO标准categories包含{id:0,name:weed},{id:1,name:crop}等annotations中每个对象含segmentationYOLO无分割此项为空、bbox:[x,y,w,h]像素坐标、area、iscrowd:0。此JSON可直传CVAT进行人工校验或作为Mask R-CNN微调的初始伪标签。5. AdamWeeds数据集在RK3588等边缘设备上的部署技巧量化、TensorRT加速与GUI集成5.1 用ONNX Runtime在ARM平台部署YOLOv8模型RK3588等国产SoC需ONNX格式模型。导出时禁用动态轴固定输入尺寸yolo export \ formatonnx \ dataadamweeds_dataset.yaml \ weightsruns/detect/adamweeds_v8n/weights/best.pt \ imgsz640 \ dynamicFalse \ # 关键禁用动态batch/size适配边缘推理 simplifyTrue \ # 启用ONNX简化减少算子数 opset12 \ # 兼容RKNN Toolkit 1.7 projectadamweeds_onnx \ namemodel.onnx生成adamweeds_onnx/model.onnx后在RK3588上用ONNX Runtime推理import onnxruntime as ort import numpy as np import cv2 # 加载ONNX模型需提前安装onnxruntime-genai或onnxruntime-gpu session ort.InferenceSession(adamweeds_onnx/model.onnx, providers[CPUExecutionProvider]) # RK3588用CPU provider def preprocess_image(img_path): img cv2.imread(img_path) img cv2.resize(img, (640, 640)) img img.astype(np.float32) / 255.0 img np.transpose(img, (2, 0, 1)) # HWC→CHW img np.expand_dims(img, 0) # 添加batch维度 return img input_data preprocess_image(adamweeds/images/val/img_001.jpg) outputs session.run(None, {images: input_data}) # outputs[0] shape: (1, 84, 8400) → 需解析为boxes/conf/cls注意RK3588的NPU对FP16支持有限建议保持FP32输入若需提速可对ONNX模型做INT8量化需校准数据集。5.2 使用PyQt6构建植物检测GUI实时显示检测框与圆度指标将YOLO推理封装为PyQt6窗口实现“拍照→检测→显示圆度”闭环# plant_gui.py import sys import cv2 from PyQt6.QtWidgets import QApplication, QMainWindow, QLabel, QVBoxLayout, QWidget, QPushButton from PyQt6.QtCore import QTimer, Qt from PyQt6.QtGui import QImage, QPixmap import numpy as np class PlantDetectorGUI(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle(AdamWeeds Plant Detector) self.setGeometry(100, 100, 1200, 800) # 初始化YOLO模型此处加载ONNX或PyTorch模型 self.model YOLO(runs/detect/adamweeds_v8n/weights/best.pt) # UI组件 self.central_widget QWidget() self.setCentralWidget(self.central_widget) layout QVBoxLayout(self.central_widget) self.label QLabel() self.label.setAlignment(Qt.AlignmentFlag.AlignCenter) layout.addWidget(self.label) self.btn_capture QPushButton(Capture Detect) self.btn_capture.clicked.connect(self.capture_and_detect) layout.addWidget(self.btn_capture) self.timer QTimer() self.timer.timeout.connect(self.update_frame) self.cap cv2.VideoCapture(0) def update_frame(self): ret, frame self.cap.read() if ret: rgb_frame cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) h, w rgb_frame.shape[:2] qt_image QImage(rgb_frame.data, w, h, w * 3, QImage.Format.Format_RGB888) self.label.setPixmap(QPixmap.fromImage(qt_image)) def capture_and_detect(self): ret, frame self.cap.read() if not ret: return # YOLO推理 results self.model(frame, conf0.25, iou0.45) annotated_frame results[0].plot() # 自动绘制检测框 # 计算并叠加圆度文本 for box, cls in zip(results[0].boxes.xyxy, results[0].boxes.cls): if int(cls) 0: # weed x1, y1, x2, y2 map(int, box) circ calculate_circularity_from_box(frame, [x1,y1,x2,y2]) cv2.putText(annotated_frame, fCirc: {circ}, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,255,0), 2) # 显示结果 rgb_result cv2.cvtColor(annotated_frame, cv2.COLOR_BGR2RGB) h, w rgb_result.shape[:2] qt_image QImage(rgb_result.data, w, h, w * 3, QImage.Format.Format_RGB888) self.label.setPixmap(QPixmap.fromImage(qt_image)) if __name__ __main__: app QApplication(sys.argv) window PlantDetectorGUI() window.show() window.timer.start(30) # 30ms刷新率 ≈33fps sys.exit(app.exec())运行python plant_gui.py后点击“Capture Detect”按钮即可在摄像头画面中实时显示杂草检测框及圆度数值。此GUI可部署至搭载RK3588的田间巡检机器人作为前端交互入口。5.3 AdamWeeds数据集在YOLOv11中的适配要点损失函数与Anchor-Free改进YOLOv112024年Ultralytics新版本采用Anchor-Free检测头不再依赖预设anchor尺寸。使用AdamWeeds训练时需修改配置# yolov11_adamweeds.yaml # 继承yolov11n.yaml仅覆盖关键项 model: yolov11n.yaml data: adamweeds_dataset.yaml epochs: 100 batch: 16 imgsz: 640 optimizer: auto # v11默认使用AdamW替代SGD lr0: 0.001 # Anchor-Free对学习率更敏感需降低10倍 box: 7.5 # v11的CIoU损失权重默认7.5无需调整 cls: 0.5 # 分类损失权重植物类别区分度高保持0.5 dfl: 1.5 # 分布焦点损失权重提升边界框回归精度关键变化YOLOv11取消anchors字段改用reg_max16表示边界框回归的离散化bins数因此无需为AdamWeeds数据重新聚类anchor尺寸。训练时box损失收敛更快但lr0必须从YOLOv8的0.01降至0.001否则初期梯度爆炸。本文还有配套的精品资源点击获取