
简介本资源是一套面向计算机视觉方向本科毕业设计的完整小麦麦穗检测实战方案聚焦农业智能化场景为初学者与毕设学生提供从模型训练到Web部署的一站式实现。资源包含基于YOLOv5训练的小麦麦穗检测模型、Flask构建的轻量级Web服务后端及配套说明文档解决农作物图像识别与可视化交互的实际问题。压缩包共37个文件2.23MB涵盖14个Python核心模块含app.py、detect_utils.py等、7个YOLOv5配置yaml文件、12张测试与示例图像、以及HTML/CSS/Markdown等前端与说明文件结构清晰、模块解耦便于理解推理流程与二次开发。已有95人学习下载读者可直接运行服务上传图片获取检测结果同时掌握数据预处理、模型调参、Flask接口封装及异常处理等关键技能配套详细使用说明覆盖环境配置、参数调整与性能优化要点。 如果你正打算做图像识别方向的毕业设计或者单纯想接触一下目标检测从训练到部署的完整链路这套“基于yolov5flask的小麦麦穗检测”项目应该能帮上大忙。它不是一个只讲原理的Demo而是一套能直接运行的源码工程yolov5负责模型训练与推理flask把模型包装成Web服务你上传一张小麦田照片页面就能返回带检测框的结果图。这份工程尤其适合作为毕业设计的主框架也适合想快速上手“detectionweb部署”组合的开发者参考。这个项目解决的痛点很明确很多同学训练完模型就不知道下一步怎么展示了论文写完了但演示系统还空着。把yolov5训练好的权重塞进flask里做一个可视化页面出来既补全了系统设计又让答辩时有的演示。整个过程不需要你从头写神经网络也不需要你精通前后端工程化重点是掌握“调用预训练模型→编写推理接口→页面展示结果”这条主线。这篇文章我会从项目选型、模型原理、数据集准备、训练调参到flask部署的完整路径展开最后再整理我实际运行中踩过的一批坑。1. 项目整体设计与技术选型解析1.1 为什么选择yolov5作为检测核心做目标检测绕不开的几个选择是Faster R-CNN、SSD、EfficientDet和YOLO系列。这套麦穗检测项目选用yolov5在我看来是综合了三个维度的最优解。第一是精度与速度的平衡。小麦麦穗检测属于农业视觉里的典型场景现场拍摄的图像分辨率高、麦穗密度大如果模型太慢实时性跟不上如果模型太浅漏检率又压不下去。yolov5s这种轻量版本在GPU上单张推理可以到几毫秒在CPU上跑一张640x640的图也基本在几百毫秒以内精度还保持得不错。对于一个以毕业设计为目标的系统来说这个性能区间非常舒服。第二是生态成熟度。yolov5的社区活跃度太高了从数据标注、训练脚本到模型导出几乎每一步都有完善工具。你不光能跑通官方仓库还能很轻松找到各种改良版。更重要的是它对新手非常友好训练命令短、参数直观、日志清晰出问题的时候随便一搜就能找到答案。你不需要自己手写损失函数和anchor匹配逻辑这些在仓库里都已经实现好你的核心工作其实是准备数据和调参。第三是部署灵活。yolov5的模型可以导出为PyTorch、TorchScript、ONNX、TensorRT等多种格式这就让后续“接进flask”变得非常顺滑。训练是PyTorch推理也用PyTorch中间没有任何格式转换的额外负担。对比一下如果选EfficientDet或者Faster R-CNN虽然效果也可以但部署时你需要额外处理预处理和后处理代码量立刻大了一圈。从版本角度说我建议直接用yolov5官方仓库的v6.0或v7.0分支这两个版本结构稳定、文档齐全。初次跑项目不要用那些魔改版本等你自己把流程走通了再根据麦穗场景的特点做精度优化也不迟。1.2 用flask包一层Web服务到底解决什么问题很多人会问模型训练完直接在命令行里调用不就行了为什么非要用flask这要看使用场景。毕业设计里“系统演示”是硬性要求。你总不能答辩的时候在评委面前敲命令行、跑Python脚本然后贴一张命令行截图出来。一个浏览器打开的网页上传图片、点击检测、看到画好框的结果这种交互方式对非技术背景的老师来说非常直观能直接展示系统的可用性。而从工程角度来说flask把“模型”和“使用”解耦了。模型推理逻辑封装成接口前端不管你是用HTML还是小程序不管你是本地还是远程访问只要发一个HTTP请求就能拿结果。这也为后续扩展埋下伏笔——以后你想加一个Android端、加一个批量检测接口只需要改flask路由不用动模型代码。选flask而不是Django或FastAPI我个人的理由是flask足够轻。这个项目涉及的前端页面就两三个接口也就两三个用Django那种重型框架纯属杀鸡用牛刀。FastAPI性能虽好、自带文档但它的异步模型和yolov5这种同步推理代码配合起来反而要处理一些额外细节对新手不够友好。Flask的同步阻塞模型恰好适配“一张图片进去、一张图片出来”的场景而且flask的模板和静态文件组织方式非常直白几天就能上手。2. 麦穗检测的技术细节与难点拆解2.1 卷一卷模型结构yolov5是怎么把麦穗找出来的yolov5的结构主线是Backbone Neck Head我用自己的话翻译一下Backbone负责从原始图像里提取特征你可以想象成一个人先大致看一遍图片把麦穗的边缘、纹理、颜色这些线索抽出来Neck负责把不同尺度的特征融合相当于让人既看整体又看细节避免麦穗太小的时候被漏掉最后的Head则负责在特征图上预测目标的位置、大小和类别。这套结构里对麦穗检测影响最大的其实是Neck中的PANet结构。它能把高层的语义信息和低层的空间细节结合对中等大小目标的检测效果提升很明显。麦穗在田间图像里通常占地面积只有几十到一百多个像素属于中小目标如果只靠最后一层特征图小目标的特征早就被压缩没了。PANet相当于把小目标的“定位线索”一路传到了输出端这也是yolov5在麦穗这类密集小目标场景下表现不错的原因。另外需要知道的是anchor机制。yolov5在训练开始前会基于你的数据集重新聚类anchor尺寸每个尺度的特征图会匹配不同大小的真实框。默认的anchor是在COCO数据集聚类出来的偏通用目标直接用在麦穗上并不一定合适。所以训练自己的麦穗数据时我强烈建议让yolov5重新自动聚类anchor具体做法是在训练参数里把--noautoanchor去掉默认就是自动聚类的。这一步不少初学者会忽略导致最终模型的召回率上不去。2.2 小麦麦穗检测到底难在哪你如果以为麦穗检测和检测猫啊狗啊差不多那就低估这个任务了。田间环境下麦穗检测有四个非常突出的难点。第一是密集遮挡。小麦生长后期麦穗紧挨着麦穗边界互相重叠检测框之间的IoU很高NMS后处理稍微激进一点就会把正确的检测框滤掉。这也是为什么我在后面会提到训练时要把NMS阈值和置信度阈值调低一些不能照搬COCO的默认值。第二是外观差异大。不同品种、不同生育期的小麦麦穗的颜色、长度、芒的形态差异都很大。同一个模型要同时识别蜡熟期带着芒的麦穗和灌浆期还没完全变黄的麦穗对模型泛化能力是个考验。第三是背景干扰严重。麦穗和成熟叶片的颜色非常接近都是黄绿色系光线充足时尤其难区分。如果数据里没有足够多的不同光照条件下的样本模型很容易把朝某个方向弯的叶子误检成麦穗。第四是目标尺寸小。我用图像标注工具统计过在一张1920x1080的田间照片里单个麦穗的标注框通常只有50x15像素左右占整张图面积不到百分之一。这种尺寸对检测网络的底层特征提取能力要求很高。2.3 数据从哪来模型能不能跑通的关键这个项目的“源码模型”里通常已经包含一份训练好的权重文件但如果要训练自己的数据数据集的来源和格式必须搞清楚。目前最常用的公开数据集是Global Wheat Head DetectionGWHD2020年由全球多家机构联合发布原始版本包含超过4000张田间图像和超过19万个标注麦穗框图像覆盖了欧洲、亚洲、澳洲等多个小麦种植区外观多样性很好。如果你的项目是基于这个数据集训练出来的模型能直接用来做演示效果也还不错。数据格式上yolov5用的是YOLO txt格式每张图像对应一个同名txt文件每行内容是class x_center y_center width height坐标值统一归一化到0到1。比如图上某个麦穗框的中心点坐标是(100, 200)宽高是(40, 20)图像尺寸是1920x1080那一行就写成0 0.0521 0.1852 0.0208 0.0185。注意这里用的是相对坐标不是像素坐标写错会导致训练直接不收敛。数据集目录结构建议这样组织dataset/ images/ train/ val/ labels/ train/ val/images和labels下的train、val子目录要保持同名同数量训练时通过yaml文件指向这些路径。yolov5官方仓库里提供了train.py、val.py和detect.py脚本数据准备环节里还有一个coco128.yaml可以参考格式。3. 实操从环境搭建到Web部署全流程3.1 环境搭建先跑通官方demo再说拿到源码包第一件事不是急着训练而是把yolov5环境跑通用官方权重先检测几张图。这一步的关键是验证你的环境是健康的后续所有问题都能定位到具体环节。Python版本我建议3.8到3.10之间PyTorch用1.10以上的稳定版。如果你有NVIDIA显卡先装好CUDA和cuDNN再通过pytorch官网的安装命令安装GPU版PyTorch如果没显卡安装CPU版也能跑只是训练速度会比较煎熬。有个小技巧装完PyTorch后在环境里执行python -c import torch; print(torch.cuda.is_available())输出True说明GPU可用。接着克隆yolov5仓库进入目录后安装依赖git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt首次运行建议先下载官方预训练权重yolov5s.pt放到项目根目录然后执行python detect.py --source data/images/bus.jpg --weights yolov5s.pt如果能在runs/detect/exp下看到带检测框的输出图片说明你的yolov5环境是好的接下来训练自己的模型就不会被环境因素干扰。这里多说一句很多同学喜欢直接拿源码包里的模型去跑flask不先跑通yolov5官方的detect遇到奇怪报错往往分不清是模型问题还是部署代码问题。我的习惯永远是“先手动验证模型再接入Web”。3.2 训练麦穗模型参数怎么定才靠谱训练麦穗模型之前需要准备好两样东西数据集yaml文件和一个预训练权重。yaml文件内容非常直白train: dataset/images/train val: dataset/images/val nc: 1 names: [wheat_head]nc表示类别数小麦麦穗检测只有一个类别所以写1。names是类别名列表要和标注txt里的class id一一对应。预训练权重推荐直接用yolov5s.pt它是在COCO上训练过的通用特征提取器迁移到麦穗任务上能显著加快收敛速度。在麦穗数据规模不算特别大的情况下不建议从随机权重开始训练否则效果通常会差一大截。训练命令本身不复杂python train.py --data wheat.yaml --weights yolov5s.pt --img 640 --batch 16 --epochs 100一些值得注意的参数--img输入分辨率。640是默认值如果你觉得麦穗太小可以试试960或1280但显存占用会显著增加训练速度也会下降。我先用640跑通流程再根据效果决定要不要提分辨率。--batch一次喂给网络的图片数量。显存够就设16或32不够就降到8。batch太小会导致BN层统计不稳定loss曲线会抖动得很厉害。--epochs小数据集100轮足够了。我在GWHD子集上实验过一般40轮左右验证集mAP就已经接近稳定再往后边际收益很小。--patience早停机制的轮数比如设20意味着如果20轮验证集没有提升就自动停止避免白烧电。训练过程中建议盯着两个东西一是终端输出的loss和mAP二是项目生成的runs/train/exp/results.png里面积累了loss曲线、精确率、召回率、mAP的完整变化过程。如果看到loss在下降但mAP死活不涨优先怀疑数据集标注有没有错、anchor设得合不合理。如果显存不够可以顺手把--workers调低或者把图片裁切成小块再训练但不要一开始就想着改模型结构先保证流程能完整跑完。3.3 评估模型用数据说话训练得到的模型最终效果如何不能靠肉眼判断要靠指标评估。yolov5的val.py会自动帮你算好这些指标python val.py --data wheat.yaml --weights runs/train/exp/weights/best.pt --img 640跑完后会输出Precision精确率、Recall召回率、mAP0.5、mAP0.5:0.95这四个核心指标。麦穗检测场景里我个人更看重Recall因为漏检一个麦穗在农业统计里意味着产量估算偏差而误检通常可以通过置信度阈值过滤掉一部分。如果Recall偏低考虑降低检测置信度阈值或者提高输入分辨率或者在数据集里补一些难样本。这里要特别提醒一个误区很多人只看mAP0.5忽略mAP0.5:0.95。后者对框的位置精度要求更严格麦穗检测这种密集场景框偏几个像素可能就会把两个相邻麦穗误判成一个。如果你的框定位不准先想想是不是输入分辨率太低。3.4 Flask封装把模型变成Web服务模型训练好了接下来就是把best.pt装进flask做一个能接受图片上传并返回检测结果的Web服务。这是整个项目从“技术验证”变成“可用系统”的关键一步。我建议的Flask项目目录结构长这样wheat_detect_web/ app.py templates/ index.html static/ uploads/ # 存放上传的原始图片 results/ # 存放带检测结果的图片 models/ best.ptapp.py的核心逻辑分两步加载模型和定义路由。加载模型在全局作用域做一次就行千万别放在路由函数里反复加载否则每来一个请求都要把几百MB的权重重新读一遍响应时间直接爆炸。路由方面两个就够用一个是GET /渲染上传页面一个是POST /predict接收图片、检测并返回结果。返回结果我习惯直接返回一张画好框的图片base64编码前端用img标签展示简单直接不用额外搞JSON解析。如果你希望前端自己画框也可以返回JSON数组包含每个框的坐标和置信度前端用canvas再画一遍。一个最简单的app.py骨架如下import base64 import io import torch from flask import Flask, render_template, request, jsonify from PIL import Image app Flask(__name__) # 全局加载模型避免重复加载 model torch.hub.load(ultralytics/yolov5, custom, pathmodels/best.pt, force_reloadTrue) model.conf 0.25 # 置信度阈值 model.iou 0.45 # NMS的IoU阈值 app.route(/) def index(): return render_template(index.html) app.route(/predict, methods[POST]) def predict(): file request.files[image] img Image.open(file.stream).convert(RGB) results model(img) # 渲染带框图片 rendered results.render()[0] buf io.BytesIO() Image.fromarray(rendered).save(buf, formatJPEG) img_base64 base64.b64encode(buf.getvalue()).decode(utf-8) return jsonify({image_base64: img_base64}) if __name__ __main__: app.run(host0.0.0.0, port5000, debugFalse)前端页面不用复杂一个文件上传控件加一个展示区域就够了。如果你想让页面好看一点可以加一点CSS但这不是重点关键是先把数据流跑通。要注意torch.hub.load第一次运行会下载依赖建议第一次启动服务之前先在命令行跑一次把缓存预热好避免首次请求特别慢。model.conf和model.iou这两个参数在麦穗密集场景尤其值得调一下。实测下来田间照片里麦穗很密集置信度阈值设太高会丢掉很多真目标设太低又会出现大量误检。我一般先在0.25和0.45这个组合上跑如果效果不理想再微调。4. 常见问题与排查技巧实录4.1 环境安装阶段的高频报错安装依赖时最容易踩到的坑是版本冲突尤其是numpy和opencv。yolov5官方requirements里的版本号是经过验证的但如果你之前环境里已经有不同版本的numpypip install -r requirements.txt有时不会自动降级导致运行时出现np.float属性不存在的报错。我建议创建一个全新的conda环境来跑这个项目与系统其他项目隔离。还有一个很常见的情况是CUDA版本和PyTorch不匹配。import torch能成功不代表CUDA一定可用一定要执行torch.cuda.is_available()检查。如果返回False大概率是PyTorch装成了CPU版或者CUDA驱动和PyTorch要求的版本不一致。此时最简单的办法是去PyTorch官网按你的CUDA版本重新生成安装命令不要用pip默认源装的版本。4.2 训练阶段的老大难训练Loss一直居高不下最常见的两个原因数据格式错误和anchor不合适。我在前面的章节提过YOLO格式的坐标是归一化的如果你用LabelImg导出的VOC格式XML直接改名成txt坐标还是像素值那模型根本学不明白。一个一眼能看穿的办法就是检查标签文件里数字范围是不是都在0到1之间。模型训练好但检测效果还是差则要检查训练集是否太小导致过拟合。GWHD原始数据集有4000多张图我自己训练的时候裁出2000张做训练集前50轮loss下降飞快但验证集mAP后面就一直原地踏步这就是典型过拟合信号。解决方法一个是加数据增强另一个是换yolov5m这种大一点的模型或者直接增加训练集图片数量少用那些重复的相似图。4.3 Flask部署时出现的问题部署阶段最常遇到的Bug是模型路径写错。源码包解压后models目录和app.py的相对位置经常因为系统不同而错位尤其是Windows下用反斜杠路径Python里经常需要转义我建议一律用绝对路径或者用os.path.join拼接路径避免踩路径坑。还有显卡显存溢出问题。如果你的模型是在GPU上训练的部署时如果目标机器没显卡或者显存不足torch.load加载模型时会报显存相关错误。可以把模型加载时带上map_locationtorch.device(cpu)让代码自动使用CPU推理。代价是推理速度会慢但对演示系统来说完全能接受。另外就是端口占用。5000端口经常被其他程序占用如果启动报Address already in use换个端口就好。4.4 快速问题定位表我整理了一个速查表基本覆盖了这个项目从安装到运行的绝大多数问题你可以直接参考。现象可能原因解决办法训练loss不降标签坐标没归一化检查标签txt数字是否为0~1之间loss降但mAP不涨anchor尺寸与麦穗不匹配训练时去掉--noautoanchor让模型自动聚类检测框漏检严重置信度阈值太高把model.conf调到0.2以下检测框乱框背景训练数据缺少负样本增加无麦穗背景图或调高置信度阈值Flask启动报端口占用5000端口被占用换端口或释放进程首次请求特别慢torch.hub加载权重部署前先在命令行预热模型CPU上推理慢模型参数过多换yolov5s模型或缩小输入尺寸这个表不是标准答案但每一个都是实际发生的案例方向对了能省下不少排查时间。5. 源码包结构说明与二次扩展方向5.1 解压后你应该关注哪些文件这类毕业设计源码包解压后里面通常会包含三个关键内容源码文件夹、模型权重文件、说明文档。源码文件夹里最重要的是app.pyflask主程序、yolov5相关脚本train.py、val.py、detect.py等、数据集目录和前端模板。模型权重文件一般是best.pt。说明文档则要仔细阅读数据集的目录组织方式和启动命令。我见过很多同学拿到源码包后直接双击运行app.py结果报了一堆错。原因基本都一样权重文件放在错误的位置或者数据集路径与代码里写死的不一致。在动手之前先花十分钟把说明文档浏览一遍把目录结构理顺看起来多花了时间实际上省下的调试时间可能是几小时。使用说明里通常会有这样的启动流程先创建conda环境然后安装依赖接着把模型放到指定位置最后运行start脚本。不要跳步把每一步都做完整再启动。5.2 这套系统还能怎么玩如果你不满足于只做一个上传图片检测的Demo这套yolov5flask架构给后续扩展留了很大空间。一是接入摄像头或视频流。flask端添加一个接收视频帧的路由前端用JavaScript的getUserMedia获取摄像头画面定时抽帧发送到/predict接口就能实现视频流的实时检测。虽然Python端点对点的速度比不上原生C部署但作为毕设演示的实时检测功能体验已经完全足够了。二是给检测结果做可视化分析。比如统计一张图里麦穗的总数、分布密度甚至根据检测框的像素面积估算产量。这种从“检测”走向“分析”的功能在毕设答辩时非常加分。实现也不复杂把yolov5返回的检测框集合汇总统计一下就好。三是模型轻量化部署。把best.pt导出成ONNX再用ONNX Runtime推理部署时可以不依赖PyTorch模型文件也更小推理速度还有提升。导出命令很简单yolov5仓库里直接执行python export.py --weights best.pt --include onnx然后flask端换成onnxruntime加载模型。这条路特别适合介绍里写“边缘计算”或“轻量化模型”方向的同学。结尾碎碎念最后分享一点个人感受这类检测Web项目真正难的不是yolov5训练也不是flask接口而是你能不能在两天内把“数据集—训练—部署—演示”这条链路完整走通。第一次做的时候我卡在数据格式转换那里将近一个下午最后发现就是用LabelImg导出的时候选错了格式。这个项目好在起点足够低源码和模型都给你备齐了遇到问题还可以照着官方仓库的issue去搜。踩过几次坑之后你会发现所谓“会做毕设系统”本质上就是会跑通一条完整的工程链路而你跑通这一次后面再做别的检测项目都能省不少力。本文还有配套的精品资源点击获取