ARTICLE DETAIL

资讯详情

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

基于YOLOv11的鲜花识别检测系统:从数据集整理到训练部署全流程

基于YOLOv11的鲜花识别检测系统:从数据集整理到训练部署全流程 简介一份基于YOLOv11的106种鲜花识别检测系统完整资料包面向计算机视觉研究人员、软件工程师及园艺相关从业者可解决多类别花卉自动识别与检测需求既适合科研教学也可作为日常植物识别工具的参考实现。压缩包内含1个docx文档大小约40KB该文档完整记录项目开发全过程从环境搭建、数据集准备与配置文件编写到YOLOv11模型训练、ONNX模型导出、性能评估与指标曲线可视化再到Tkinter图形界面设计和完整代码整合。文档目录层次分明依次介绍项目背景、项目特点、参考资料、未来改进方向、注意事项与项目实施步骤并专门给出数据增强、超参数调优等提升模型精度的思路也提到后续可扩展视频流和实时摄像头检测功能。目前已吸引137人学习虽然资源以单个文档形式提供但内容详实完整既包含可复现的系统说明也涵盖模型配置、训练方法、性能评价指标等应用细节适合想快速上手YOLOv11落地流程的读者研读。1. 基于YOLOv11的鲜花识别检测系统开始前先想清楚这三点如果给你一桌混着月季、小雏菊、蒲公英和满天星的照片让你把每朵花的位置和类别都标出来传统图像处理会写到怀疑人生而检测模型只要训练数据够干净就能接住这个活。基于YOLOv11的鲜花识别检测系统核心是把标注好的鲜花图片集喂给 YOLOv11训练出一个能输出类别和框的权重文件再对单张图片、批量图片或摄像头画面做推理。标题里“完整的程序和数据”通常卡在三个点数据集格式不统一、训练环境没配顺、推理结果不知道存到哪里。我按实际落地的顺序讲一遍适合做课程设计、比赛演示或者要把检测功能接到现场项目里的人新手可以直接复制命令跑熟手重点看参数边界和避坑部分。2. 鲜花数据集整理成 YOLO 格式目录划分与标签检查不能偷懒很多项目死在第一步不是模型不行是图片和 txt 标签没有一一对应。YOLO 训练时要求每张图片有一个同名 txt 文件里面每行表示一个目标格式是class x_center y_center width height坐标全部归一化到 0 到 1。鲜花识别这种多类别检测任务只要标签文件里有一行坐标超出范围、类别 id 错位、或者图片和标签没配对训练时 loss 会异常甚至模型学出来全是错框。2.1 images 与 labels 一一对应先固定目录规范我一般先把数据集组织成下面的结构后面推理和部署都不用改路径。# 在工程根目录下执行创建 images 和 labels 对应的 train/val/test 目录 mkdir -p dataset/flowers/images/train mkdir -p dataset/flowers/images/val mkdir -p dataset/flowers/images/test mkdir -p dataset/flowers/labels/train mkdir -p dataset/flowers/labels/val mkdir -p dataset/flowers/labels/test这里的关键是images和labels两个主目录必须完全对称。训练时 Ultralytics 会根据图片路径自动去找同名的标签路径比如dataset/flowers/images/train/rose_001.jpg对应dataset/flowers/labels/train/rose_001.txt。如果有人在 labels 目录下又建了子目录或者把标签文件名字改成了rose_001_1.txt模型就会跳过这些样本而且不报错只会在日志里显示警告新手很容易忽略。2.2 用脚本划分训练集、验证集、测试集并自检标签如果原始图片和标签都在images_all和labels_all里建议用一个简单脚本按比例划分而不是手动拖拽。手动划分最大的问题是容易漏标、重名覆盖、导致训练集里某几类花特别多、另一类只有几十张。# split_dataset.py from pathlib import Path import random import shutil BASE Path(dataset/flowers) IMG_ALL BASE / images_all LAB_ALL BASE / labels_all RATIO {train: 0.7, val: 0.15, test: 0.15} for split in RATIO: (BASE / images / split).mkdir(parentsTrue, exist_okTrue) (BASE / labels / split).mkdir(parentsTrue, exist_okTrue) images list(IMG_ALL.glob(*.jpg)) list(IMG_ALL.glob(*.png)) random.seed(2026) # 固定随机种子后面复现结果时用 random.shuffle(images) train_cut int(len(images) * RATIO[train]) val_cut int(len(images) * (RATIO[train] RATIO[val])) for i, img_path in enumerate(images): label_path LAB_ALL / (img_path.stem .txt) if not label_path.exists(): print(f[warn] 缺标签: {img_path.name}) continue if i train_cut: split train elif i val_cut: split val else: split test shutil.copy2(img_path, BASE / images / split / img_path.name) shutil.copy2(label_path, BASE / labels / split / label_path.name)这段脚本用的是绝对路径从BASE出发所有目标目录会在执行前自动创建。random.seed(2026)是为了保证每次划分结果一致方便复现训练效果。train_cut和val_cut是两个切分点位置整数定位用的是下标判断不会重复读样本。缺标签的图片直接跳过不复制同时在终端打一个 warn这个机制非常关键。原作者复制代码时最容易漏掉的就是label_path.exists()这个判断没有它后面的归一化坐标检查会拿到空文件然后训练集里出现一批没有目标区域的坏样本。划分完之后我再加一段标签自检逻辑检查每个 txt 里的类别 id 是否落在预期的范围内。比如你的鲜花类别有月季、小雏菊、蒲公英、满天星四类合法类别 id 是 0、1、2、3。VALID_IDS {0, 1, 2, 3} for label_file in (BASE / labels / train).glob(*.txt): for line in label_file.read_text().strip().splitlines(): parts line.split() if not parts: continue if int(parts[0]) not in VALID_IDS: print(f[error] {label_file.name} 存在非法类别 id: {parts[0]}) x, y, w, h map(float, parts[1:]) if not (0 x 1 and 0 y 1 and 0 w 1 and 0 h 1): print(f[error] {label_file.name} 坐标越界: {line})这段代码的价值在于提前暴露“标签错位”问题。很多标注软件导出的类别 id 是从 1 开始的但 YOLO 要求从 0 开始如果没检查训练时会把第一类自动忽略表现为某一个类别完全不识别。坐标越界的情况更容易出现在手工改 txt 的时候数值大于 1 或小于 0模型训练时会计算出负数损失或者无边界的框直接让训练崩溃。2.3 data.yaml 与类别顺序识别不对多半是这里错位数据集准备好之后需要写data.yaml。这个文件告诉 YOLOv11 三件事训练集、验证集在哪、一共有几类、类别名字是什么。# dataset/flowers/data.yaml path: dataset/flowers train: images/train val: images/val test: images/test nc: 4 names: 0: rose 1: daisy 2: dandelion 3: gypsophilapath是相对于当前运行目录的根路径建议使用绝对路径否则在终端不同目录下执行训练命令时经常报找不到 images。train和val填相对路径即可YOLO 会把它们拼在path后面。names的索引必须和标签 txt 里的数字一致这是鲜花识别系统里最常见的错误来源之一。比如标注软件里把月季设成 1写成0: rose后面全部错位。数据量方面四类鲜花每类最少准备 150 到 300 张训练集做数据增强、验证集和测试集保持原图。如果某些类别只有几十张优先做法是从原始图片里裁剪出花朵区域做平移缩放而不是直接复制粘贴原图否则模型学到的是背景。更省事的方式是先用公开数据集里的花卉类别作为预训练基础再把自己的现场照片往里面混合着训练后面我会专门说参数怎么调。3. YOLOv11 环境配置与训练参数把训练跑通再看网络结构YOLOv11 这类检测框架在工程落地上最大的门槛不是算法而是环境依赖。PyTorch、CUDA、Ultralytics 这三个版本只要有一个对不上训练时就会出 CUDA error 或者训练中途被 kill。所以第一步是创建一个独立的 conda 环境不要直接往系统 Python 里塞包。3.1 conda 环境配置一个干净的执行环境节省三天排错conda create -n yolo11 python3.10 -y conda activate yolo11 pip install -U ultralytics创建环境时指定python3.10这个版本对多数预编译包兼容性最好。-y参数会自动确认创建。激活后pip install -U ultralytics会把 YOLO 训练、验证、预测的所有命令都装好。如果你在终端输入conda时报“conda 不是内部或外部命令”说明 conda 的 PATH 没配好建议直接用 Anaconda Prompt 进入这个坑我在第 5 章展开说。装完 Ultralytics 之后可以验证一下显卡是否被识别python -c import torch; print(torch.cuda.is_available())输出True说明 CUDA 环境正常输出False就先检查 CUDA 驱动不要急着训练。用 CPU 也能跑但 200 轮四类花的训练可能要十几个小时显卡是刚需。这里注意不要额外安装与系统 CUDA 版本不一致的 PyTorch一般用pip install ultralytics自动带的那版就没有问题。3.2 最小训练命令与参数表照抄也要知道为什么环境就绪后在工程根目录执行yolo detect train \ datadataset/flowers/data.yaml \ modelyolo11n.pt \ epochs200 \ imgsz640 \ batch16 \ optimizerauto \ device0 \ projectruns/flowers \ nametrainmodelyolo11n.pt表示从轻量级预训练权重开始微调。这里有一个容易被误解的点即使你的鲜花数据集和预训练数据集完全无关迁移学习仍然有效。因为预训练权重已经学会了边缘、纹理、形状这些底层特征只需要让模型把花的语义信息重新组织一遍。imgsz640是训练输入尺寸四类花如果画面里有大量小朵的雏菊和满天星建议直接提到960或者1280代价是训练耗时和显存上去了。batch16如果显存不够降低到8或4但要配合学习率变化后面会说。optimizerauto让框架自己选优化器省心。训练过程中的参数选择可以参考这个表参数作用我的建议值epochs训练轮数小数据集 150 起步200 比较稳imgsz输入图片尺寸640 起步具体看花朵在画面中的比例batch批次大小按显存来超内存优先降 batch 而不是降 imgszpatience早停轮数我一般设 20超过 20 轮没提升就停optimizer优化器选择auto 即可新手不要手动改workers数据加载线程0 或 2Windows 下不要设太高workers在 Windows 下建议设成 0。因为 Windows 多进程数据加载偶尔会报安全模式错误0 表示用主进程加载速度慢一点但稳定。训练日志里出现all image loads这种提示很正常不用管。下面这条命令把早停打开防止过度占用显卡资源yolo detect train \ datadataset/flowers/data.yaml \ modelyolo11n.pt \ epochs200 imgsz640 batch16 \ patience20 \ projectruns/flowers nametrain \ save_dirbest加了patience20后模型连续 20 轮验证指标没有提升训练就会提前结束同时只保留效果最好的权重best.pt。要注意save_dirbest这个参数会把模型权重复制到固定路径方便后面的推理脚本引用。3.3 YOLOv11 网络结构与可改位置先改输入再改分支网上搜“yolov11 网络结构”能搜到一大堆结构图核心组成一般包括 backbone 提取特征、neck 融合多尺度特征、decoupled head 输出分类和回归结果。对做鲜花识别系统来说结构上值得改的只有三个位置第一是输入分辨率。花是比较典型的“尺度敏感”目标同样一朵雏菊在近景里占半个画面在群体照片里可能只有乒乓球大小。把imgsz从 640 提高可以显著提升小目标召回率但对显卡的压力比较大。第二是模型体量。yolo11n是最轻量级适合嵌入式部署如果在本机训练且不缺显存换yolo11s或者yolo11m能多收获几个点的 mAP。第三是检测头输入。小目标优化有一个常见做法是给检测头增加高层特征输入但这需要改代码建议新手把精力放在数据和输入尺寸上改进网络结构放在最后。训练时特别关注验证集的mAP50-95曲线。如果这个曲线反复震荡不上升先去检查数据集是否干净而不是反复调整学习率。我见过很多人在参数上折腾两天最后发现是训练集里有几十张图片根本没标签。4. 保存推理结果与部署从本机批量预测到 Jetson 部署模型训练出来的最终目的是在照片或摄像头画面里把花识别出来并且把结果保存下来。这里就是热搜词里常见的问题“yolov11保存推理结果”很多新手把saveTrue加在训练命令上发现并没有保存预测图实际上推理保存的开关在predict子命令里。4.1 命令行推理保存推理结果到图片、txt 与标签文件yolo detect predict \ modelruns/flowers/train/weights/best.pt \ sourcetest_images \ saveTrue \ save_txtTrue \ save_confTrue \ conf0.25 \ iou0.45这个命令会把test_images目录下所有图片跑一遍。saveTrue表示把画了框的推理图片保存到runs/detect/predict目录save_txtTrue表示同时保存同名的 txt 文件里面是模型预测出的类别 id、归一化坐标和置信度save_confTrue会在 txt 里额外加一列置信度数值。conf0.25是置信度阈值低于这个值的预测框会被过滤掉对于鲜花任务 0.25 偏低容易框出一堆背景物体建议先用 0.35 跑一遍看效果。iou0.45是 NMS 的 IoU 阈值值越大抑制越强重复框越少。推理结果默认保存到runs/detect/predict如果多次执行不会覆盖会生成predict2、predict3等目录。写脚本读取结果时不要写死路径推荐用glob动态定位最新目录。4.2 批量推理脚本把结果整理成 CSV 再排查命令行方式适合简单验证但做系统交付时我需要把每个图片的识别结果汇总成一个表格方便统计准确率。下面这个脚本会遍历测试目录输出result.csv。# batch_predict.py from pathlib import Path from ultralytics import YOLO model YOLO(runs/flowers/train/weights/best.pt) src_dir Path(test_images) out_dir Path(runs/flowers_output) out_dir.mkdir(parentsTrue, exist_okTrue) records [] for img_path in sorted(src_dir.glob(*.jpg)): results model.predict(str(img_path), conf0.35, saveTrue) for box in results[0].boxes: cls_id int(box.cls[0]) conf float(box.conf[0]) records.append(f{img_path.name},{model.names[cls_id]},{conf:.3f}) (out_dir / result.csv).write_text(image,class,conf\n \n.join(records))这个脚本先加载best.pt然后遍历test_images下的所有 jpg 文件。results[0]是单张图片的推理结果boxes对象里装有每个预测框的分类 id、置信度。model.names会根据训练时的data.yaml自动映射出类别名字这样输出 CSV 里直接是“rose、daisy”这样的中文可读类别名而不是数字 id。这个脚本还能顺手统计每一类的平均置信度如果某类花朵置信度长期低于 0.3说明该类别的训练样本数量太少或特征区分度不够需要回到数据层面补充。4.3 Jetson Nano 部署 YOLOv11执行环境与训练环境分离把训练好的权重部署到 Jetson 系列边缘设备和本机推理最大区别是执行环境更小算力更弱。我会在板子上单独建一个部署环境不装 CUDA 训练相关的全家桶只保留推理所需的最小依赖。conda create -n yolo11-jetson python3.8 -y conda activate yolo11-jetson pip install ultralyticsJetson 上安装 PyTorch 时尽量使用设备官方提供的预编译包直接pip install torch容易拉错版本。装好之后把训练机上的best.pt文件拷贝到板子工程目录执行和上面一样的predict命令即可。部署时要注意 Jetson 的显存通常只有几 GB别把训练的imgsz1280原样搬过去建议推理尺寸降到 640。如果发现 Jetson 推理速度只有几帧每秒可以先把模型导出成 TensorRT 引擎但这个过程涉及量化小篇幅说不透。先说一句最关键的部署环境里千万不要再执行train命令否则内存直接被吃光推理延迟会成倍上升。训练和部署分开这是工程化的基本习惯。5. 鲜花识别常见问题排查现象、原因、解决这一章写几个我实际跑鲜花数据集时遇到的高频问题每条都按“现象-原因-解决”的方式记录方便你直接对照。5.1 conda 命令不识别环境激活不了现象在终端输入conda create或者conda activate系统提示“conda 不是内部或外部命令也不是可运行的程序或批处理文件”。这种情况在 Windows 上最常见明明安装了 Anaconda但终端里找不到 conda。原因Anaconda 安装时没有把 conda 所在的 Scripts 目录加入系统 PATH或者当前使用的终端窗口是在安装完成前打开的环境变量没有刷新。解决最简单的办法是打开 Anaconda Prompt 执行同样的命令它不是普通 cmd会自动定位 conda。更彻底的做法是把 conda 的 Scripts 路径手动加到系统环境变量 PATH 里然后重新打开终端。如果都不想做就每次都用 Anaconda Prompt 跑训练脚本。这个现象我在搭建检测环境时遇过好几回建议先确认 conda 能用再往下装包否则后面每个报错都不知道是哪一层的问题。5.2 训练损失很低验证集却漏检明显现象训练到 150 轮左右损失降到 0.05 以下验证集 mAP 看起来也不错但单独抽出某一张现场照片推理时模型对画面角落的小雏菊完全没有反应。如果只跑网上常用的测试图还挺难发现这个问题。原因损失低不直接等于检测准。验证集里的花朵通常主体居中、占画面比例较大但实际相机拍的群体花艺图里很多花在画面边缘、互相遮挡、占像素面积小。模型在图像金字塔的高层特征里对这类小目标响应偏弱于是漏检。解决先把验证集换成和真实场景一致的照片再跑predict saveTrue看保存的推理结果图。如果确实是小目标漏检优先提高训练输入尺寸到 960 或 1280同时把训练集中的花朵用小窗口裁切后重新标注一遍让模型见过足够多的局部近景。不要只动模型网络结构先解决数据尺度和标注问题。5.3 花朵类别互相错位置信度还很高现象模型把月季识别成玫瑰把蒲公英识别成雏菊并且每个错误框的置信度都高于 0.8。这种情况很迷惑因为置信度很高代表模型内部非常确信但它确实分错了。原因类别标签在数据集里发生了系统性错位。比如标注软件导出的类别 id 和data.yaml里的 names 顺序不一致。还有一种可能是在划分数据集时两个不同分类的图片混杂在同一个目录导致训练时模型把两者的特征学成了同一个类别。解决回到数据层面做两件事。第一用第 2.2 节的自检脚本遍历所有标签 txt确认类别 id 落在合法范围第二手动抽查每个类别目录下前十张图片看是否有明显不属于该类别的图。不要盲目加训练轮数错位问题不是欠拟合而是监督信号本身是错的模型学到了一个真实的错误映射。5.4 固定场景下训练后换背景就翻车现象训练集全是在同一张白色桌面拍的鲜花图验证集在实验室环境里测得很准但拿手机在户外草地一拍模型把叶子、背景里的塑料花全识别成目标误检率飙升。原因模型学到了背景信息而不是纯粹的目标特征。YOLO 的卷积感受野里天然包含目标周边的区域如果训练集中每张图的背景高度一致模型会把“白色桌面”作为判别特征之一参与预测。解决收集更多不同环境下的数据户外、室内、不同光照各拍一批在训练时开启随机颜色抖动、随机旋转和 Mosaic 增强减少模型对背景纹理的依赖。有一个偏方很管用把部分训练图片中的花朵抠出来贴到完全不相关的背景上用脚本自动合成一批混合样本能显著拉低误检率。5.5 显存不足或老 GPU 兼容性报错现象训练开始后不到一分钟终端报CUDA out of memory或者直接提示no kernel image is available for execution on the device。前者常见于 batch 设大后者常见于老显卡和过新的 CUDA 版本不兼容。原因batch16加上imgsz640的显存占用并不小如果是 4GB 显存显卡跑 200 轮中间很容易溢出兼容性报错是因为显卡的算力太老新版本 PyTorch 编译的 CUDA kernel 不支持。解决先把 batch 降到 4imgsz 降到 480 或 640跑通一次完整训练再说。老显卡要去找匹配的 PyTorch 版本搜索关键词就是你的显卡型号加 PyTorch 版本。实在没有对应版本就用 CPU 跑小批量验证流程虽然慢但能确认数据和程序本身没逻辑问题。不要第一次就把标准参数全套怼上去调参数的目标是让训练跑完而不是一轮就到最优。6. 用多尺度推理验证花识别模型小目标优化的两步检查最后分享一个我每次训练完都会做的验证习惯不直接看 mAP先做多尺度推理再把保存推理结果的图片单独过一遍。很多开发者在测试集上看到 mAP 0.9 就觉得万事大吉真实场景里换一个摄像头、换一个拍摄距离模型可能瞬间掉回 0.6。多尺度验证的做法很简单。拿同一张测试图分别用 416、640、960 三个尺寸跑推理然后对比三个结果的框是否一致。对鲜花这种目标大小跨度很大的场景这个动作能快速暴露模型的尺度敏感度。from ultralytics import YOLO model YOLO(runs/flowers/train/weights/best.pt) for size in (416, 640, 960): model.predict( test_images/bouquet_01.jpg, imgszsize, conf0.35, saveTrue, projectfruns/scale_check_{size}, )注意这里每次推理都保存到不同的project目录不会互相覆盖。我一般重点关注 416 和 960 之间的差异如果 416 漏掉了远处的小雏菊而 960 能框出来说明模型底子没问题只是输入分辨率限制了小目标如果 960 和 416 都在同一个位置漏掉那大概率是训练数据里这类样本本身就少或者遮挡太严重。前者可以通过提高推理尺寸解决后者需要补数据这正好对应“yolov11小目标优化”的核心思路先查分辨率再查数据。做完这一步再回头看训练时的 mAP 曲线心里才能踏实。我现在的习惯是每训一版模型先拿三五张现场实拍图跑一遍保存推理结果的流程确认大目标小目标都有框再去看验证集指标。这套流程救过我很多次也希望帮到你。本文还有配套的精品资源点击获取
返回列表