基于AC-YOLO的路面落叶检测:改进、训练与避坑指南 简介一份面向计算机科学与技术专业本科毕业设计的论文资源聚焦AC-YOLO算法在路面落叶检测中的应用。全文约一万字章节结构完整从第一章研究背景与意义到第二章目标检测综述、YOLO原理及AC-YOLO自适应聚类改进再到第三章路面落叶数据集采集、标注与预处理系统梳理了技术选型与数据准备过程。第四章详细设计了基于多尺度特征融合的网络模型、数据增强与损失函数第五章给出实验设置、结果对比与分析第六章总结结论并提出展望适合需要撰写目标检测方向毕业论文或希望借鉴改进型YOLO应用思路的读者。包内为1个docx文档压缩包仅33KB内容精炼且便于全文阅读。目前已有321人学习具有一定参考价值。通过这份论文读者可以掌握从问题定义、算法改进到实验验证的完整科研写作范式也可参考其中的章节组织与实验分析方式为自己的毕业设计或课题研究提供直接支撑。1. 路面落叶检测为什么难AC-YOLO要解决的不是「换个模型」这么简单秋天的城市道路上落叶不只是保洁问题更是行车安全里的一个隐患刹车打滑、遮挡路面积水、堵塞排水口。想用视觉模型自动检测落叶你会发现它比检测行人、车辆还要棘手——落叶和柏油路、水泥地、泥土的颜色高度接近树影和枯叶的纹理几乎无法区分再加上一天里光照角度不停变化同一个位置上午能检出下午就漏检。这种场景下直接拿通用YOLO跑一遍mAP往往很难看。于是很多本科毕设把方向定在「基于AC-YOLO的路面落叶检测」上核心思路不是在YOLO上乱加模块而是针对落叶小目标、背景杂乱这两个痛点把注意力机制和上下文特征融合引进来。这篇文章就沿着这个方向从网络结构怎么改、数据集怎么做一直写到训练参数和踩坑记录你可以直接照着复现。2. 看懂AC-YOLO的网络改动注意力模块放在哪、特征融合改什么2.1 从YOLOv8基线出发AC-YOLO的「AC」到底动了哪两个地方先明确一个背景AC-YOLO并不是某个官方发布的固定模型而是这类改进型YOLO的统称。在本科毕设论文里最常见的写法是取 Attention注意力和 Context上下文特征两个改进点合成“AC-YOLO”这个名字。也就是说你的网络结构里必须真实存在这两处改动而不是只改了个名字。路面落叶检测这个任务决定了这两个改进点其实是被场景逼出来的。落叶通常只有几十到上百像素在640×640的输入分辨率下属于中小目标YOLOv8原版的检测头主要在P3、P4、P5三层特征图上做预测最小的一层是80×80对应原图上大约8×8像素的感受野。一片落叶在这个尺度下只占几个格子特征信息非常弱。另一个麻烦是落叶和路面的纹理太像了模型很容易把注意力放在错误的区域上比如路面的裂缝、树影、井盖边缘。所以AC-YOLO的典型做法是两处改动第一在Backbone的特征提取末端加入注意力模块让网络更关注叶片和路面在颜色、纹理上的细微差异第二在Neck部分引入上下文特征融合或者增加一个更高分辨率的检测层让浅层细节信息能传递到检测头。我一般会建议先把这两个改动独立实现、分别做消融实验这样论文里能拿出三组对比数据而不是只给一个“我改了个模型”的结果。2.2 Backbone加入注意力SE与CBAM的取舍注意力模块的选择是第一个需要做决定的地方。常见的选项有SE、CBAM、ECA、CACoordinate Attention各有各的适用场景。SE模块只做通道注意力计算量最小对大目标效果明显但对落叶这种需要同时关注“位置在哪”和“长什么样”的任务来说缺少空间信息帮助有限。CBAM在SE的基础上加了空间注意力分支让网络知道该重点看哪些区域对背景杂乱的任务更友好。CA注意力则把空间坐标信息编码进通道注意力对小目标检测通常表现更好。我的建议是在这类毕设场景里优先用CBAM原因有三个一是实现代码短几行就能写进YOLOv8的C2f模块里不容易出错二是消融实验效果好解释你可以说SE只做了通道加权CBAM同时做了空间和通道的加权在落叶与路面难以区分的问题上更有效三是参数量增加不大训练起来不会明显变慢。具体落地时需要注意插入位置。常见做法是把手写的注意力模块放在Backbone的最后几层也就是SPPF模块的输出后面。这里有个很容易犯的错把注意力塞进C2f内部改动太大容易把YOLOv8原本的梯度流弄乱。稳妥的做法是先在主干网络的P3、P4、P5特征输出后各接一个注意力层然后观察这三个位置里哪个对mAP提升最大。一般来说P5层加注意力的效果最明显因为深层特征语义信息最丰富通道注意力在这里能够更好地分辨“落叶”和“其他路面目标”。在ultralytics框架里你只需要改models的yaml文件在Backbone部分增加一个attention层然后写一个CBAM类在train的时候传入模型构建函数即可。但如果是纯PyTorch手写网络那改动量会大很多提交论文代码时要把自己写的模型结构图、每个tensor的shape变化列清楚。2.3 Neck加P2小目标检测层落叶这种小目标靠什么找回很多同学训练AC-YOLO遇到漏检多的问题树荫下的落叶、远处小片的落叶经常框不出来这时候首先该怀疑的不是注意力加得不够而是检测层分辨率不够。YOLOv8的检测头在P3、P4、P5上输出80×80特征图对应的感受野对行人、汽车足够了对落叶来说还是偏大。解决思路是加P2层即把特征图分辨率提高到160×160。这相当于让模型在原图的4×4像素区域里搜索目标对一片横向只有30像素的落叶来说能分配的网格数量提升了一倍。P2层的实现思路也不复杂在Backbone的Stem部分把浅层特征引出来直接接到Neck的PAN结构里让检测头多一组160×160的输入。这样做带来两个代价。第一个是计算量明显增加显存占用跟着涨如果你的显卡只有6GB训练时batch size要从16降到8甚至4第二个是浅层特征包含大量背景噪声如果直接加P2层误检率可能不降反升。所以我在实际项目里的顺序是先用CBAM把注意力加上训练一轮看漏检情况再决定要不要加P2层。如果你用的是ultralytics YOLOv8的yaml文件修改方案加P2层需要在yaml的Neck部分增加一个来自Backbone第二层通常索引是-2的上采样连接并让检测头接收四个不同尺度的特征图。这个改动对新手来说容易出现维度不匹配的问题所以调试时建议每次改完yaml后先打印一次模型结构确认每个tensor的shape是正确的再开始训练。改进点解决什么问题代价加CBAM注意力P5后落叶与路面的纹理、颜色区分度低参数量略增训练时间5%左右加P2小目标检测层落叶目标尺寸小容易被下采样丢失显存占用20%以上需调低batch size两者同时加AC-YOLO兼顾特征区分和细节保留需要仔细调学习率和数据增强参数3. 准备路面落叶数据集采集、标注、格式转换脚本3.1 数据采集要求与负样本策略数据集的质量直接决定AC-YOLO能不能训练出来。常见做法是你自己用手机或相机拍摄选不同的路段、不同的时间、不同的天气每个场景拍几十张。几个采集要求我直接列出来路面种类要多样柏油路、水泥路、砖石路、人行道都要有否则模型容易记住路面纹理而不是落叶本身光照变化要覆盖早晨、中午、傍晚三个时段最好再加一组雨后反光的样本不然你会在晴天数据上训练得很好阴天测试时漏检一堆树叶种类最好也收集几种不同形状的落叶枫叶、梧桐叶、柳叶因为不同树种的落叶外观差异太大如果只拍一种模型很可能只认识了那一种。负样本同样不能忽略。这里的负样本不仅是没有落叶的干净路面图片更重要的是“看着像落叶但不是落叶”的图片——树影、井盖、路面裂缝、塑料袋、纸片。我之前训练时就是因为只拍了正样本结果模型在树影底下疯狂误检把每一片影子都当成落叶。所以采集时一定要留出20%左右的负样本图让模型学会“不要检测什么”。3.2 LabelImg标注成VOC格式的流程标注工具最常用的是LabelImg开源、轻量、不需要配置环境直接pip安装就能跑。打开图片后按键盘W键调出标注框框住每一片可见的落叶跟着标签名统一填leaf。注意一个细节标注框要紧贴树叶边缘不要把叶子周围的路面空隙框进去不然模型学的就是“一个带路面的彩色矩形”而不是落叶本身。标注数量上对于本科毕设来说800到1200张图片是一个比较合理的区间。每张图平均有5到15片落叶目标这样总标注框数量在5000个以上训练一个改进型YOLO基本够用。如果你只标了200张后期过拟合会很严重注意力模块的作用根本体现不出来。标注完成后LabelImg默认保存为VOC格式的XML文件。这里有一个很实际的问题需要提前处理你要在训练前把数据集划分成训练集、验证集、测试集比例一般按8:1:1并且每张图片对应的XML要跟着同步划分。很多新手栽在这里——图片分好了XML文件没跟上训练时读到一半报错找不到标注。3.3 VOC转YOLO格式的Python脚本YOLO系列训练需要的标注文件是一种纯文本格式每个txt文件对应一张图片文件里的每一行代表一个目标类别序号、中心点x坐标、中心点y坐标、目标宽度、目标高度前四个数字都是相对于图片宽高的归一化值范围在0到1之间。写一个转换脚本是很基础但很必要的步骤。import os import xml.etree.ElementTree as ET from PIL import Imagedef voc_to_yolo(xml_path, img_path, output_path, classes): # 解析XML标注文件 tree ET.parse(xml_path) root tree.getroot()# 读取图片宽高用于归一化坐标 img Image.open(img_path) img_width, img_height img.size # 获取所有目标框 labels [] for obj in root.iter(object): class_name obj.find(name).text if class_name not in classes: # 忽略未定义的类别 continue class_id classes.index(class_name) # 读取XML中的左上角坐标和右下角坐标 xmin float(obj.find(bndbox).find(xmin).text) ymin float(obj.find(bndbox).find(ymin).text) xmax float(obj.find(bndbox).find(xmax).text) ymax float(obj.find(bndbox).find(ymax).text) # 转换成YOLO格式中心点宽高全部归一化到0~1 x_center (xmin xmax) / 2.0 / img_width y_center (ymin ymax) / 2.0 / img_height box_width (xmax - xmin) / img_width box_height (ymax - ymin) / img_height labels.append(f{class_id} {x_center:.6f} {y_center:.6f} {box_width:.6f} {box_height:.6f}) # 写入对应的txt文件 base_name os.path.splitext(xml_path)[0] with open(base_name .txt, w) as f: f.write(\n.join(labels))ifname main: # 类别列表这里只有落叶一个类别 classes [leaf] xml_dir annotations/ for xml_file in os.listdir(xml_dir): if xml_file.endswith(.xml): xml_path os.path.join(xml_dir, xml_file) # 假设图片和XML在同目录且同名 img_path xml_path.replace(.xml, .jpg) voc_to_yolo(xml_path, img_path, labels/, classes)这段代码做的事情很直接读一个VOC的XML文件解析出每个目标的边界框按YOLO要求的格式写入txt文件。逻辑说明上有两点需要注意。第一xml.etree.ElementTree里找bndbox标签时如果你在数据里看到KeyError或者NoneType错误先用文本编辑器打开一个XML文件检查标签名不能用不一样的标签名。第二图片和XML文件的同名匹配依赖文件名一致所以我这里直接用replace来生成图片路径如果你的文件结构是images和annotations分开的目录需要自己改路径拼接。参数方面classes数组的顺序决定了类别序号一定要和训练时的data.yaml里的类别顺序保持一致。写完后跑一遍脚本打开几个生成的txt文件对照图片人工检查一下框的位置对不对。这一步不要省我见过转换脚本里坐标除错了分辨率导致模型训练了十几个小时全部白费的翻车案例。4. 训练AC-YOLO完整过程环境配置、训练命令与参数调法4.1 环境清单与依赖版本训练AC-YOLO要用到的基础环境如下Python 3.8以上PyTorch 1.8以上建议2.0以上CUDA 11.3以上显卡建议NVIDIA独立显卡显存至少6GB。如果你用的是ultralytics框架pip直接安装即可代码里要引入的包很少核心就是torch、ultralytics、opencv-python、numpy这几个。有一点需要提醒的是不要一上来就装最新版本。ultralytics的版本迭代很快有些版本对yaml文件格式的处理方式会有细微变化你从网上找的很多AC-YOLO代码如果发布得比较早拿到新版本上可能跑不通。稳妥做法是创建一个独立的环境锁一个已知能用的版本组合比如ultralytics 8.0.x配PyTorch 2.0.x这个组合下的yaml解析逻辑比较稳定。安装完环境之后先不要急着训练自己的数据集用官方自带的一个小数据集比如coco128跑一次训练命令确认整个链路是通的。这一步能帮你把环境问题和代码问题分开排查如果coco128能正常训练说明你的环境没问题数据集或yaml配置里的问题接着去查如果连coco128都报错那先解决环境问题。4.2 修改yaml文件与训练启动命令AC-YOLO的落地训练我一般建议基于YOLOv8来改因为它的代码结构清楚、文档多、遇到问题容易搜到解决方案。你需要准备两个yaml文件一个是数据集配置文件data.yaml里面写训练集、验证集图片路径和类别信息另一个是模型结构文件也就是定义AC-YOLO网络各层连接的yaml。data.yaml的写法是最容易踩坑的地方之一。注意路径要写绝对路径不要写相对路径。相对路径在训练脚本所在目录变化时很容易找不到文件然后报错说“No images found in train path”但这个报错信息并不会提示你是路径问题排查起来很恼火。dataset/data.yamltrain: /home/user/leaf_dataset/images/train val: /home/user/leaf_dataset/images/val test: /home/user/leaf_dataset/images/testnc: 1 names: [leaf]训练启动命令如下我用的是YOLOv8s作为基础配置然后修改其中的结构得到AC-YOLOyolo detect traindata/home/user/leaf_dataset/data.yamlmodel/home/user/leaf_dataset/ac_yolov8s.yamlepochs200batch8imgsz640optimizerAdamWlr00.001lrf0.01patience30seed42workers4projectruns/leaf_detectnameac_yolo_exp1这段命令里的关键参数说明如下。epochs设200是因为落叶数据集规模不大一两千张图训练轮次太少特征学不充分太多则浪费时间200是一个常见且稳妥的区间。batch8对应6GB显存加P2层的显存占用如果你不打算加P2层batch可以开到16训练速度能快不少。imgsz640是速度和精度的平衡点升到960对小目标检测有提升但显存占用和训练时间都会显著上涨建议先跑640。优化器和学习率这一组参数非常关键。我建议用AdamW替代YOLOv8默认的SGD因为注意力模块的加入会让网络训练对学习率更敏感AdamW的适应性学习率能减少调参压力。lr0设置为0.001是保险值如果你用的是SGD一般要设成0.01但配合CBAM这类注意力模块时0.01起步可能会导致前期震荡比较大。4.3 关键超参怎么调数据增强和早停策略训练过程中最有玄学感的部分就是数据增强参数了。ultralytics的默认增强对一般目标检测任务很友好但对落叶这种目标小、和背景相似度高的场景默认值不一定是好事。我一般会改动四个地方mosaic增强比例从默认的1.0降到0.5因为mosaic把四张图拼在一起会让一片落叶变得更小更模糊增强过度反而学不到特征hsv_h色调增强保持默认hsv_s和hsv_v可以提高一点因为在不同光照下落叶的颜色饱和度变化很大多一些色彩扰动能让模型更鲁棒旋转角度degrees设5到10度就够路面上的落叶没有明显的朝向规律转太多反而会引入不真实的形态此外scale增强的幅度要控制小一些本来落叶就小缩放太大容易把目标缩没了。早停策略也别忽略。我遇到过一种情况训练到120个epoch左右验证集的mAP突然开始下降但训练集的loss还在继续降低——这是典型的过拟合信号。ultralytics的patience参数就是用来干这个的设为30表示连续30个epoch验证集没有提升就自动终止训练。训练结束后模型会自动保存最后一轮的权重和最佳权重你只需要在训练日志里找到best.pt的保存路径即可。注意一个容易混淆的点patience触发后用哪个权重做测试我的习惯是直接用best.pt而不是last.pt。last.pt是训练结束时的状态如果训练后期发生过拟合性能反而不如中途的best.pt。参数推荐值说明imgsz640若漏检严重可试960显存会明显上涨batch8加P2层 / 16不加P2层根据显存动态调整optimizerAdamW配合注意力模块更稳定lr00.001AdamWSGD的话建议0.01mosaic0.5过高的mosaic对小目标训练不友好patience30防止验证集过拟合后继续空跑5. 避坑训练和推理阶段的五个常见问题5.1 现象落叶紧贴路面时模型什么都框不出来训练完模型后跑测试集发现一个问题落叶稍微多一点或者叶子叠在一起的时候模型一个框都画不出来。检查训练日志mAP看起来不算低但实际推理效果很差。这个现象通常是数据采样不均匀造成的。原因分析训练集里孤零零的一片落叶占大多数模型学到的特征是“单个叶片完整边缘”叠在一起的落叶形态完全不同边缘互相遮挡特征匹配不上。解决办法是数据清洗和增强两手抓训练前检查标注数据把叶子重叠较多的图片单独挑出来确保数据集中有20%以上的重叠样本同时在增强时加入小范围的剪切模拟叶片被遮挡的情况。5.2 现象训练Loss下降但mAP不动还有一个让人想砸键盘的情况训练曲线显示loss一路下降看起来学得很好但每轮的验证mAP几乎是一条水平线可能一直在30几徘徊。这个问题的本质往往是数据集划分或者标注出了问题。先排查train和val数据集里是否有重复图片。如果你划分数据集时没有按父目录整体移动而是复制图片后随机分配很容易出现同一张图片既在训练集又在验证集这样验证集的评估结果会偏乐观但反过来如果验证集里的图片和训练集差异过大比如训练集全是晴天数据验证集全是阴天数据mAP也会上不去。另一个常见原因是标注框质量不高有些框把落叶周围的土也圈进去了模型学到的目标边界是模糊的很难把mAP拉上去。我一般会先抽出几十张验证集图片用训练好的模型画出预测框人工对比一下预测和标注的差异定位问题在哪一侧。5.3 现象显存爆掉或训练中途卡死显存不够是最常见的环境问题。报错信息一般是CUDA out of memory。如果你加了P2层同时用大batch训练几乎一定会碰到这个。解决路径按优先级尝试最直接的是把batch减半从8降到4这能立刻减少一大半显存占用然后检查imgsz是否设得偏大如果设了960改回640能省很多显存最后检查代码里是否有一些不需要的组件在占用显存比如开了TensorBoard的graph记录功能。训练中途卡死不报错的情况更容易让人崩溃。特征是终端窗口整个冻结GPU利用率变成0。这个问题大概率出在数据加载上workers参数设置过高或者数据集里有一些损坏的图片比如标注文件里引用了不存在的图片会导致卡死。先把workers设为0看能否复现如果设为0以后正常了说明是DataLoader的问题。损坏图片可以用一个小脚本扫一遍数据集尝试用PIL打开所有图片遇到打不开的就删掉或重新导出。5.4 现象推理误检一堆把阴影和树叶当落叶误检率高和漏检是两个方向的问题原因也完全不同。模型把树影、路面裂缝甚至路边的绿色灌木当成落叶通常说明训练数据中负样本太少了模型学到的类间区分能力不足。这就是我在数据集准备时反复强调的负样本策略的原因。另一个容易忽略的因素是NMS的置信度阈值。YOLO默认的conf阈值是0.25如果你的模型在验证集上mAP还行但部署时误检多可以把conf调高到0.4甚至0.5试一下。这个参数不用重新训练直接在推理命令里加参数即可yolo detect predict modelruns/leaf_detect/ac_yolo_exp1/weights/best.ptsource/home/user/leaf_dataset/images/testconf0.35iou0.5saveTrue注意conf提高后漏检率也会上升所以这个参数需要在你的测试视频上多试几个值。我一般先跑一遍conf0.25看看情况再按0.05的步长往上调找到一个误检和漏检相对平衡的点。5.5 现象论文里mAP很高实际视频里却翻车最后一个问题最隐蔽验证集上mAP0.5刷到了90%以上但是把模型放到实拍的视频里跑帧率很低先不说检测结果可以说是惨不忍睹。这里要区分两个问题如果是速度问题是因为推理时imgsz设得太大或者在CPU上跑自然会卡如果是精度问题大概率是训练数据分布和实际场景差异太大。我遇到过最典型的情况是数据全部来自晴天早晨的拍摄测试时拿到下午树影很重的视频模型几乎失效。解决办法是不要只看mAP在训练完成后找一个实际场景的长视频做定性测试统计每一帧的检测结果看误检和漏检集中在什么光照条件下。如果发现某个时段特别差回到数据采集这一步补拍该时段的图片加入训练集。6. 收尾消融实验与注意力热力图可视化6.1 三组消融实验证明你的改动有效到这一步你的AC-YOLO已经能跑了但论文里还差最关键的一张表消融实验结果。评委老师和答辩委员会看的就是这一张表来判断你的工作有没有意义。我的建议是训练三组模型第一组是原始YOLOv8s作为基线第二组是YOLOv8s加CBAM注意力验证注意力模块的贡献第三组是完整的AC-YOLO也就是注意力加P2检测层验证整体方案的效果。训练这三组模型的时候必须保证除了网络结构以外所有条件完全一致包括随机种子、训练轮数、batch size、数据增强参数、数据集划分。这样对比出来的mAP、precision、recall差异才是可靠归因于你的改进的。为了方便对比记录每一组在第100轮和第200轮的mAP50、mAP50-95、F1、参数量、推理速度然后把它做成一张三行三列的表。6.2 Grad-CAM可视化给答辩老师看注意力消融实验表只能告诉别人你的模型“更强了”但不能直观解释为什么更强。这时候可以用Grad-CAM热力图生成一组可视化结果把AC-YOLO和原版YOLO在相同图片上的注意力分布画出来对比。常见做法是取Backbone最后一层卷积输出的梯度计算通道权重后叠加到原图上生成热力图。对落叶场景来说你希望在热力图上看到原版YOLO的注意力比较分散对整条路面都有响应而AC-YOLO的注意力应该集中在落叶区域周围形状和叶片轮廓有重叠。做Grad-CAM时需要注意一点——取哪一层的特征图很关键。取太深层的特征图热力图会非常模糊看不出细节取太浅层的特征图又缺乏语义信息。我一般取P5层后面那层或者SPPF的输出在这个位置上生成的注意力热力图最直观。如果跑出来的热力图和你预想的不一样不要强行解释先检查代码里梯度收集的方式是否正确。这一步很耗时但论文里的效果图就靠它撑场面了。最后还有一个小习惯想分享给你每次训练完不要只保存best.pt把训练曲线图、混淆矩阵、验证集的预测可视化图全都整理到同一个目录。答辩前把这些材料翻一翻你就能很自然地讲清楚“阴天漏检是怎么解决的、树影误检又是怎么压下去的”。做毕设这一年我自己的体会是踩坑不可怕可怕的是没有把每个坑的原因和解决过程记下来。希望这篇内容能帮你少走一些弯路把AC-YOLO真正跑通、把论文的数据做得扎实。本文还有配套的精品资源点击获取