YOLOv8路面裂缝检测系统:从数据标注到中英文部署全流程
做路面裂缝检测这个方向最容易踩的坑不是模型不会跑而是跑出来效果一言难尽或者模型指标很好看却没办法给别人演示。我最近整理完一套基于YOLOv8的路面裂缝检测系统从标注、训练到中英文双版界面的整条链路都走通了还配了完整源码和效果演示。这篇就从头讲一遍为什么选YOLOv8、数据怎么准备、训练参数怎么调、中英文双版怎么落地、实际效果到底如何、以及我踩过哪些坑。如果你是算法初学者、土木交通方向想做课程设计或毕业设计的同学或者正在把目标检测往工程应用落地这篇值得耐心看完。1. 路面裂缝检测系统为什么非要用YOLOv81.1 路面巡检的真实痛点人工检测为什么撑不住路面裂缝是公路和城市道路最常见的病害之一但它偏偏是养护部门最头疼的巡检对象。传统做法基本靠人工目测加记录表养护人员带着相机沿路走看到裂缝就停下来拍照、记录位置、目测宽度。一条几十公里的路段走下来体力消耗很大漏检率也完全取决于当天状态和经验。更麻烦的是纸质记录和照片档案很难二次利用想统计某条路段裂缝密度分布、对比不同时间段的变化基本要重新翻资料。自动化检测的价值就在这用行车记录仪或者巡查车上的相机持续采集路面影像让模型自动把裂缝位置圈出来输出类别、置信度和数量养护人员后期只需要抽查复核。这套逻辑听起来不复杂但落地时对模型的鲁棒性要求非常高——路面上有阴影、油渍、碎石、新旧接缝、轮胎磨损痕迹任何一个干扰项都可能让检测结果变成一场误报狂欢。我在做这套系统时把目标定得很明确不是做一个只能在几张demo图上跑出好结果的玩具而是让模型在多种路面条件、多种光照下都能稳定输出同时提供一套能直接给人看、给人点、能切换中英文的完整演示界面。交付形态不是一段训练代码而是一个能跑的闭环系统。1.2 模型选型YOLOv8对比Faster R-CNN、SSD、YOLOv5选模型是这类项目的第一步也是决定后面所有工作量的关键。我在这套系统之前先后试过传统图像处理、两阶段检测器和几代YOLO系列最后锁定了YOLOv8。简单说说对比过程给后来者一个参考。传统图像处理方法比如阈值分割、边缘检测、形态学操作在某些路面均匀、光照稳定的图片上效果还行但只要背景稍微复杂一点路面纹理就会被当成裂缝误报率高得没法用。这类方法适合做预处理不适合做核心检测。两阶段的Faster R-CNN精度确实高但推理速度太慢单张图片在CPU上动辄几秒甚至十几秒做成实时演示系统非常吃力。SSD这类早期单阶段检测器速度不错但对小目标召回率偏弱而裂缝恰恰是又细又长的小目标。YOLOv5已经很成熟社区资源也丰富但后续维护和新特性迭代不如YOLOv8积极。YOLOv8在结构上做了几处关键升级使用anchor-free的解耦检测头收敛更稳定骨干网络引入C2f模块特征提取能力更强自带训练、验证、推理、导出的完整命令行工具链省掉大量工程琐事。方案精度表现推理速度小目标能力工程易用性传统CV阈值/边缘低误报高快差一般Faster R-CNN高慢中低SSD中中弱低YOLOv5较高快中良好YOLOv8高快较强极高综合下来YOLOv8是性价比最高的选项。官方还提供了从n到x多个尺寸的预训练权重我最终选用了s尺寸作为主力后面会细说理由。1.3 中英文双版不是炫技而是交付需求很多同学做完模型就结束了代码全部堆在一个notebook里演示的时候还要现场敲命令行。我自己第一次做类似项目时就吃过这个亏项目评审的时候对方想看界面结果我只能把终端截图贴出来效果大打折扣。所以这套系统从设计之初就把给人看当成硬需求。中英文双版是怎么来的呢一方面是使用场景确实有需求——国内演示中文界面最直观但如果要做英文PPT、外文报告或者配合国际化评审一个英文界面能让项目专业度提升一个档次。另一方面如果做两套完整系统维护成本会翻倍所以我采用语言包配置方案同一套HTML和后端逻辑通过切换语言包渲染不同文字。代码维护量增加很少但系统的适应能力明显提升。2. 数据集和标注环节怎么准备才不容易翻车2.1 数据来源与清洗先把脏数据挡在门外模型效果的上限由数据决定这句话在裂缝检测项目里体现得尤其明显。我这次使用的数据集由两部分构成一部分来自公开渠道可获取的路面裂缝图像另一部分是自己用手机和行车记录仪补采的路面照片。为了叙述方便下面统一叫它RC-210数据集总共约2600张图片。这个量级对目标检测来说不算大但经过合理清洗和增强后训练一个可用的检测器足够了。拿到原始数据后我做的第一件事不是标注而是清洗。大约有15%的图片被我直接淘汰原因包括画面严重模糊导致裂缝边缘根本无法辨认、图片存在大量重复同一条裂缝被连拍了很多张、路面只占画面边缘导致主体内容偏离、以及光照极端的图片比如大逆光下路面完全过曝。这些脏数据如果混进训练集模型学到的就是噪声而不是裂缝特征。清洗时还有一个容易被忽略的点检查公开数据里的标注是否靠谱。有些数据集的标注框画得很大把裂缝周围的背景也包进去了有些则漏标了多条裂缝。我重新对RC-210做了全量标注力求每个框都紧贴裂缝实际范围。这一步很费时间但值得因为标注质量直接影响模型收敛速度和最终精度。2.2 单类别还是多类别裂缝标注的两种路线做裂缝检测时会遇到一个选择把裂缝统一标成一类还是细分成横向裂缝、纵向裂缝、网状裂缝等几类我第一版选择了单类别统一标注为crack。理由很实际裂缝的细分类别本身就存在标注歧义横和纵是相对行车方向而言的同一张图片不同标注员很可能给出不同结论而网状裂缝和其他类型差异较大混在一起会让类别边界更模糊。标注一致性差模型学起来就痛苦最终mAP反而会被拉低。单类别模型跑通之后如果想做细分可以在同一套数据上重新组织标签或者训练一个二级分类器对检测结果做后置分类。这个思路比一开始就强行分成多类更稳妥。我这里标注时只画矩形框因为裂缝虽然细长但单类别矩形框方案已经能覆盖核心需求。如果未来需要计算裂缝精确面积就得考虑分割模型我在第5节会展开说。2.3 裂缝是小目标重灾区滑窗切图与数据增强裂缝的形态很特殊细长、弯曲、占据面积小。一张1280x960的图里部分裂缝只有几个像素宽直接丢进640分辨率训练很多小裂缝在特征图上几乎只剩一个点。为了让模型能捕捉这些细节我做了两个关键处理。第一个是输入分辨率。训练时把imgsz设置为1280让模型在更大特征图上看到裂缝纹理。代价是显存占用和训练时间上升后面参数章节我会给具体方案。第二个是滑窗切图。把部分大图切成640x640的重叠切片这样原来很细的裂缝在切片中相对更大模型更容易学到完整特征。切图时需要设置重叠比例我用的是水平垂直各50像素的重叠避免裂缝恰好被切在边界上导致实例不完整。数据增强方面我用了翻转、旋转、亮度扰动、轻微模糊、Mosaic等方式。增强强度要克制裂缝是连续结构如果旋转角度过大或者加入过强模糊会破坏裂缝的原始形态模型学到的是残缺特征。我实测中把旋转限制在正负30度以内亮度扰动幅度控制在30%模糊概率设为0.2。加Mosaic增强是为了模拟多张图拼接场景提升模型对复杂背景的适应能力。2.4 数据划分与验证集设计数据划分这里有一个我踩过的坑随机划分。第一次做的时候直接按文件列表随机切分训练集和验证集结果验证集mAP很高一放到新场景就露馅。原因是同一段路面连续拍摄的图片太相似随机划分等于让验证集偷偷参与了训练。正确的做法是按拍摄场景或路段划分保证同一场景的图片不会同时出现在训练集和验证集里。我的划分比例是6:2:2训练集1560张、验证集520张、测试集520张划分前先按场景分组确保测试集里包含沥青路面、水泥路面、阴影遮挡、雨天痕迹等不同情况。验证集和测试集的场景分布尽量接近真实使用环境这样评估出来的指标才有参考价值。3. 训练配置与关键参数调优全过程记录3.1 环境配置记录版本组合直接影响训练稳定性先说环境我建议直接按这套组合来装兼容性最省心Python 3.10、PyTorch 2.0及以上、CUDA 11.8、官方YOLOv8工具包。安装主要依赖就一条命令pip install ultralytics torch torchvisionCUDA和PyTorch的版本匹配是新手最容易翻车的地方。如果显卡驱动版本旧、CUDA版本新训练时会出现CUDA error: no kernel image available这类报错。建议先确认自己的显卡驱动支持哪个CUDA版本再选定对应的PyTorch安装命令。没有本机GPU也没关系云端免费GPU平台可以完成训练本地只负责推理和界面演示。依赖版本方面记住一个原则不要图省事执行把所有包全部升级。我遇到过因为numpy升级到新版本导致某个图像库接口不兼容的问题排查了半天。把核心依赖版本固定下来其他包保持不动训练环境才稳定。3.2 输入分辨率的权衡用1280还是640训练时imgsz的选择直接影响检测效果和显存占用这组权衡我给一个实际参考用640输入显存压力小训练速度快但小裂缝漏检率明显偏高尤其遇到宽度只有几个像素的细裂缝时基本检不出来。用1280输入小裂缝召回率显著提升mAP50约能提高5到10个百分点代价是显存占用翻倍训练时间拉长。折中方案显存不足时用640输入配合滑窗切图在推理阶段对大图先切块预测再合并结果。我最终在训练阶段直接采用1280配合可用的batch大小把大图切成512x512的瓦片喂给模型。如果显存只有8GB开1280分辨率时batch设4到8比较稳再用梯度累积模拟更大的batch。推理阶段我同样切了瓦片避免超大图直接进模型导致显存溢出。3.3 训练参数选择与指令示例训练参数没有一套万能模板但有可以参考的起点。我的RC-210数据集上经过了十几轮对比实验最终采用的配置如下# roadcrack.yaml path: ./datasets/RC-210 train: images/train val: images/val nc: 1 names: [crack]训练命令yolo taskdetect modetrain modelyolov8s.pt \ dataroadcrack.yaml epochs300 imgsz1280 \ batch8 optimizerAdamW lr00.0005 \ weight_decay0.0005 patience30 device0几个关键参数的选择逻辑模型用yolov8s.pt而不是n或m。n太轻特征提取能力弱对细裂缝不友好m重一些但训练时间增加RC-210这个数据量下s已经够用。如果你的数据集更丰富可以尝试m获得更高精度。优化器选AdamW而不是默认的SGD。实验表明AdamW在裂缝这种小目标场景收敛更稳尤其是训练后期不容易震荡。学习率初始值0.0005比官方默认的0.01低很多因为1280高分辨率和较小的数据集下过大的学习率会让loss直接飞掉。patience30表示验证集指标连续30轮不上升就早停防止无效训练浪费时间。3.4 训练日志解读从loss曲线和mAP判断模型状态训练过程中不要只看终端输出的数字要会读曲线。我会同时看几个指标box_loss框回归损失、cls_loss分类损失、验证集mAP50和mAP50-95。正常状态下训练loss在前50轮快速下降之后进入缓慢下降通道验证集mAP50稳步上升mAP50-95跟随上升但波动更大。如果出现训练loss继续下降但验证集mAP开始下滑说明模型过拟合了此时早停会帮你抓住最佳权重。如果loss震荡剧烈大概率是学习率偏大或者数据里有太多脏样本建议调低lr0。训练结束后runs/train/exp/weights目录下会生成best.pt和last.pt两个权重。我直接采用best.pt它代表验证集上综合表现最优的一轮权重。last.pt只在你想继续训练时有用日常推理和部署都用best.pt。最终我在RC-210测试集上得到的结果是mAP50约0.91、mAP50-95约0.64、F1分数约0.88这个成绩对单类别裂缝检测是够用的。不过说句实在话公开测试集指标只能说明模型在见过的场景类型里表现好真到一个从没见过的路面环境下最好还是先拿少量现场图片验证一下。4. 中英文双版系统怎么设计和落地4.1 系统整体架构与运行流程模型训练好只是第一步把它变成能给人演示的系统才是重点。我的技术选型是Flask 轻量Web前端既可以在本机运行演示也可以部署到服务器上让其他人通过浏览器访问。为什么不用纯桌面GUI因为Web界面跨平台、不用装依赖评审现场只需要打开浏览器输入地址就能用。系统目录结构大致如下crack_detection_system/ ├── app.py # Flask主入口 ├── config/ │ ├── zh.json # 中文字典 │ └── en.json # 英文字典 ├── models/ │ └── best.pt # 训练好的权重 ├── predictor.py # 推理封装 ├── templates/ │ └── index.html # 前端页面 ├── static/ │ ├── css/ │ └── js/ └── uploads/ # 上传图片临时目录运行流程很简单用户在前端点上传图片Flask接收图片后保存到临时目录后端把图片路径交给推理模块推理模块返回检测结果框坐标、置信度、裂缝数量前端绘图并把结果展示在页面上。语言切换只需前端下拉框选择重新加载页面时带上lang参数后端根据参数返回对应语言包渲染。模型不能每次请求都加载否则显存会爆。我在predictor.py中把模型做成全局单例首次请求加载后一直常驻内存。如果同时用多个尺寸的模型建议按需要加载到独立显存区域避免互相挤占。4.2 核心推理模块实现推理模块是整个系统的核心代码很短但细节不少。这个函数逻辑我在多个项目里复用稳定可靠import cv2 from ultralytics import YOLO MODEL_PATH models/best.pt class CrackDetector: def __init__(self, model_pathMODEL_PATH): self.model YOLO(model_path) def predict(self, image_path, conf0.35, iou0.45, imgsz1280): img cv2.imread(image_path) results self.model.predict( sourceimg, confconf, iouiou, imgszimgsz, verboseFalse, ) boxes results[0].boxes detections [] if boxes is not None: xyxy boxes.xyxy.cpu().numpy() confs boxes.conf.cpu().numpy() clss boxes.cls.cpu().numpy() for x1, y1, x2, y2 in xyxy: detections.append({ bbox: [int(x1), int(y1), int(x2 - x1), int(y2 - y1)], confidence: float(confs[idx]), class_id: int(clss[idx]), }) return detections实际使用时的经验conf默认值是0.25但对裂缝这种背景干扰多的场景太低我把后端默认设为0.35如果检测结果里误报多就往上调。iou保持0.45就能有效抑制同一裂缝的重复框。绘制检测框时我建议不要再单独写一套画框逻辑直接复用这个函数返回的bbox和置信度在Flask接口里用OpenCV绘制即可。补充一个小技巧中文界面上显示置信度时格式化到小数点后两位界面看起来会清爽很多。4.3 中英文语言切换机制实现这套系统的亮点之一就是语言切换实现思路不复杂所有界面文字从JSON语言包读取前端下拉框选择语言后刷新并携带参数Flask根据参数挑选语言包渲染模板。语言包配置如下{ app_title: 路面裂缝检测系统, upload_btn: 上传图片, result_title: 检测结果, crack_count: 裂缝数量, confidence: 置信度, empty_hint: 请上传一张路面图片, switch_lang: 切换语言 }英文版对应{ app_title: Road Crack Detection System, upload_btn: Upload Image, result_title: Detection Result, crack_count: Crack Count, confidence: Confidence, empty_hint: Please upload a road image, switch_lang: Language }Flask路由里加载语言包from flask import Flask, request, render_template, json import os app Flask(__name__) def load_lang(lang): lang_file os.path.join(config, f{lang}.json) with open(lang_file, r, encodingutf-8) as f: return json.load(f) app.route(/) def index(): lang request.args.get(lang, zh) if lang not in (zh, en): lang zh return render_template(index.html, langlang, textsload_lang(lang))前端切换时重新导航到带上lang参数的新地址。注意一个小细节如果语言包缺了某个key页面可能显示空白或者保留上一次的旧文本。我在开发阶段写了一个简单脚本遍历中英文两个JSON逐个key校验两边都存在避免漏翻译。这个机制虽然简单但很值得在类似项目中复用。很多需要多语言展示的工具系统都可以用同一套配置映射运行时解析的思路来扩语言不必维护两套页面代码。4.4 Web界面功能说明这套系统在界面上实现了三个核心功能单张图片检测、批量图片检测和结果显示。单张检测是最常用的上传图片后页面立即展示原图和检测结果图右栏显示裂缝数量和各候选框的位置信息。批量检测针对文件夹场景后端一次性读取目录下所有图片循环调用推理然后把所有结果汇总到一个结果页支持按置信度排序。视频检测我用了另一个思路用OpenCV读取视频流每一帧喂给模型检测实时把结果绘制后写回输出视频。考虑到裂缝检测通常不需要实时帧率控制在每秒5到10帧的处理速度完全够用亲测对长视频更友好的是抽帧检测异常片段标记模式而不是逐帧全量检测。界面整体的用户体验上建议保留一个置信度阈值滑块参数因为不同场景下的最优阈值可能不同现场演示时可以实时调整感受效果。这个功能虽然只多了一小段代码但演示起来效果差异巨大。5. 实际检测效果与性能实测展示5.1 典型场景效果实录RC-210测试集上做了大量视觉检查我挑几类有代表性的场景说说实际表现。细小裂缝场景裂缝宽度很小、背景相对均匀这类是表现最好的场景。裂缝能被稳定框出置信度大多在0.75以上基本没有漏检。难点在于画面中有两条裂缝贴近时偶尔会出现两个框融合进同一个框的情况靠NMS把iou调到0.45能缓解。阴影遮挡场景树影、桥梁阴影投在路面上时阴影边缘和裂缝在灰度上非常接近误报会上升。经过后处理把置信度阈值提高到0.4后阴影造成的误报大幅减少但确实会牺牲一部分极暗处裂缝的召回。这个取舍根据使用场景来定我认为宁缺毋滥误报多了人眼复核成本反而更高。新旧接缝场景路面的施工接缝和裂缝形态相似度很高这是所有裂缝检测模型都难以绕开的问题。我的策略是在训练数据里加入大量接缝图片作为背景样本让模型学会将这些干扰项判定为低置信度。最终效果接缝偶尔会带一个0.3左右的弱框但置信度阈值一设高就被过滤了。水泥路面场景水泥路面纹理丰富特征噪声比沥青大误报率和漏检率都略高于沥青路面。如果项目主要面向水泥路面建议单独采集一批数据做二次训练或者调低阈值接受更多误报后再人工筛选。5.2 性能指标展示精度、召回、推理耗时模型的定量指标我用下面这张表来总结数据集就是前面提到的RC-210测试集约520张。注意这里所有数字只代表我这个数据分布下的表现不能直接挪用到其他场景当保证值。指标数值说明精确率(Precision)0.89检出的框里真正是裂缝的比例召回率(Recall)0.87真实裂缝中有多少被检出来mAP500.91IoU0.5下的平均精度均值mAP50-950.64严格IoU下的平均精度均值单张GPU推理耗时约12-15ms1280分辨率8GB显存消费级GPU单张CPU推理耗时约400-600ms纯CPU环境1280分辨率从表格能看出mAP50和mAP50-95之间差距明显。这意味着模型能定位裂缝的大致区域但精确的边界贴合度还有提升空间。如果项目对裂缝宽度测量有硬需求就得切换到分割模型或者做后处理细化。5.3 从检测到量化裂缝占比与长度的扩展思路检测框只是矩形包围盒它只能告诉你大概在这个位置有裂缝不能直接给出裂缝长度、面积、宽度这些量化数据。但实际养护场景中量化指标往往比有没有裂缝更有价值。我在这套系统里预留了一个扩展方向将检测结果送入一个裂缝分割网络或者直接用OpenCV在大致区域内做阈值细化然后计算裂缝像素面积。配合现场标定比如在路面放置已知宽度的标线可以换算出裂缝的实际宽度和长度。我这个版本先把检测做扎实量化的部分交给后续迭代。这类扩展的思路也很简单检测器负责找区域分割器负责扣细节。检测结果框内的像素再做二值分割比全图分割计算量小且更聚焦。如果你也在做类似系统建议按照先检测后分割的链路设计既有检测框的可解释性也有分割结果的量化能力。6. 训练和部署踩坑实录问题、原因、解决方案6.1 高频问题排查速查表整理这套系统的过程中我记录了大量调试日志下面这个速查表覆盖了训练和部署阶段的高频问题可以先收藏再对照排查。症状可能原因解决方案训练loss不降或震荡学习率偏大 / 数据太脏调低lr0到0.0001~0.0005清洗数据mAP50高但mAP50-95低预测框偏离裂缝实际边界提高输入分辨率检查标注框贴合程度误报多阈值太低 / 背景干扰提高conf到0.4以上收集负样本继续训练细小裂缝漏检输入分辨率不够 / 目标过小用1280输入或者滑窗切图后检测CPU推理太慢模型大 / 分辨率高换更小模型或转ONNX格式加速上传图片失败请求体超过Flask默认限制设置MAX_CONTENT_LENGTH并检查前端大小限制中文显示乱码缺少中文字体文件在代码中指定中文字体路径比如本机已有字体界面文案不更新语言包key缺失或缓存补齐语言包清理浏览器缓存6.2 训练阶段的三个典型坑先说第一个坑数据增强过强。我第一版训练时用了很大的随机旋转角度结果裂缝被旋转后形态断裂模型学到的特征是断开的碎片而不是完整裂缝导致推理时对斜向裂缝识别极差。修改方案是将旋转限制在正负30度并且只在部分样本上启用增强比例控制在0.5以下。第二个坑验证集和训练集太像。前文提到按场景划分后才解决但这里还有一个细节值得强调划分操作必须在任何数据增强之前完成。有些人先把增强扩出来的图片混在一起再划分会造成训练集和验证集之间出现重复样本评估结果虚高得可怕。第三个坑预训练权重和数据集不匹配。用COCO预训练权重能加速收敛但COCO里的裂缝类目标很少前几十轮模型其实在忘掉通用特征、学习裂缝特征。如果数据量很小不要一上来就用大模型很容易过拟合。我建议起步用s尺寸数据量超过3000张后再考虑m或l。6.3 部署运行阶段的三个典型坑部署阶段遇到的第一个坑是显存控制。检测长视频时如果逐帧调用模型而忘记释放中间结果显存占用会缓慢增长直至溢出。好在官方工具包会回收但如果我自己用Python脚本循环调用就要注意每帧处理完后清理cv2图像对象避免临时变量积压。第二个坑是模型预热。服务器刚启动时第一次推理特别慢因为模型初始化和CUDA上下文创建都在这一刻完成可能卡住几秒。我在Flask启动时就做了一次空推理预热之后每次请求的返回耗时就稳定下来了。如果未来GPU被其他任务占用可以用device参数固定显存避免显存不够用。第三个坑是CPU部署速度。在没有GPU的机器上1280分辨率的裂缝检测要跑半秒以上体验很差。我把模型导出成ONNX格式后推理延迟降低约30%到40%。转换命令一行就够yolo taskdetect modeexport modelmodels/best.pt formatonnx imgsz1280导出后在ONNX Runtime里做推理就不用依赖GPU了。如果还需要更极致的速度可以继续编译TensorRT版本不过工程复杂度会明显上升演示场景其实没这个必要。6.4 中英文界面的三个细节坑语言切换看似简单实际使用中还是遇到了一些琐碎但影响体验的问题。第一个问题语言包key漏配。加了一个新按钮中文JSON里写了对应文案英文JSON忘记补充结果英文界面显示空白。后来我写了本地校验脚本遍历两个JSON的key做差集每次上线前跑一下这个问题就绝迹了。第二个问题切换后动态内容不更新。检测结果中的置信度数字、裂缝数量这些内容是由前端JS动态生成的如果这些字符串也来自语言包切换语言后只能硬刷新页面看到新文案否则新生成的DOM节点还是旧文本。解决方案是切换语言时重新触发一次渲染结果区域的函数。第三个问题编码格式混乱。语言包文件必须统一用UTF-8编码打开Windows下用记事本新建JSON容易保存成GBKFlask读取时就会出现乱码。我后来统一用编辑器配置UTF-8编码并在打开文件时显式指定encodingutf-8。这类问题很恼人但解决方案确实就这么简单。这次项目做完我自己最大的感受是真正花时间的地方不在模型训练而在数据清洗和工程化。模型训练脚本本身是标准流程但把数据收拾干净、把系统做到别人能直接上手用才是一个项目能不能交付的分水岭。我后来回头看如果一开始就先用最小样本量跑通全流程而不是急着调参追求指标整个项目的推进速度会快很多。最后再分享一个小建议做这类视觉检测系统先在真实场景拍一批现场照片测一测测试集指标好看和现场效果可用之间往往隔着好几个晚上。希望这套YOLOv8路面裂缝检测系统的完整记录能帮你少走一点弯路。