
简介一套基于YOLOv8的古建筑监测系统面向计算机相关专业学生、毕业设计开发者及深度学习初学者提供从模型训练到可视化交互的一站式目标检测方案。资源完整覆盖训练、推理与界面展示全流程包含Python源码、完整数据集、图形化操作界面和部署教程可输出核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果及标签分布图为毕业论文与答辩评审提供扎实的数据支撑。压缩包共97个文件以70个Python脚本为主体另含预训练权重pt、配置文件xml、演示视频mp4与说明文档txt总大小24.21MB目录按训练、检测、UI等模块划分便于快速定位与二次开发。项目经测试运行成功功能稳定既适合毕设答辩现场演示也适用于课程设计、大作业或项目初期立项参考。目前已有40人学习下载对需要快速落地YOLOv8检测应用的开发者颇具实用价值。1. 基于YOLOv8的古建筑监测系统毕设级项目怎么做到开箱即用做古建筑监测系统这类项目很多人第一版demo都是从“拿yolo跑通一个检测”开始的真正卡住的往往是后面几步数据集凑不齐、标注格式对不上、训练好的权重在界面里显示不出来。基于YOLOv8的古建筑监测系统把这条路压缩成“数据标注—训练—可视化界面—部署”四步跑通之后手上就有一套能演示、能截图、能写进毕业论文的完整作品。这篇笔记按我自己的落地顺序来写目标读者是想用这个方向做毕设或课程设计、又不想在环境配置上浪费一周的同学。文里所有命令都在CPU和一张普通游戏卡上验证过先讲透为什么这么选再给能直接抄的步骤。2. 先定义检测目标再谈数据古建筑监测的建模思路2.1 古建筑场景要检测什么三类目标是常规配置古建筑监测不等于“认出来这是故宫还是应县木塔”它要解决的是结构件是否完好、有没有病害、有没有异常行为。我经手的多数课程设计和毕设需求都会落到三类目标上第一类是结构件比如木柱、梁、斗拱、墙体这类目标尺寸大、形状规整标注最省力第二类是病害比如裂缝、表面剥落、水渍这类目标细长或者边缘模糊是模型最容易翻车的地方第三类是异常事件比如明火、烟雾、人员闯入这类目标在静态图像里不常见但演示时最能出效果。这三类目标混合在一个数据集里训练比单独训练一个“裂缝检测器”更贴近真实监测场景答辩时也更有话讲。选目标检测而不是实例分割主要考虑两点一是标注成本检测框在Labelme里拉一下就行分割得多边形绘制和修边时间翻倍二是推理速度可视化界面要实时预览检测方案在一张普通显卡上能跑到几十毫秒分割模型同分辨率下基本要翻倍。如果导师点名要“精细化监测裂缝走向”再考虑升级到YOLOv8-seg前提是先把检测版跑通。类别定义会直接影响后面的数据标注和loss表现。我的建议是控制在5到8类以内结构件和病害混着来。类别太少演示时画面里大部分目标都会被忽略效果单薄类别太多每类的样本数就被稀释小类别容易学不动。2.2 数据集从哪来自拍、公开集与“粘贴增强”混合古建筑数据不像COCO那样随手能下这是很多初学者第一个没想到的坑。常规做法是三路来源混着用。第一路是自采拿手机围绕校园古建、本地寺庙、仿古街区拍视频抽帧成图。抽帧时不要连续截取每隔10到20帧取一张保证姿态多样性。第二路是公开数据集和开源社区里挑古建筑、历史建筑相关的类别或者借用建筑裂缝数据集做补充。凡是公开数据都要先核对类别和标注质量裂缝数据集经常存在大量低对比度样本直接混进去会把模型带偏。第三路是半合成数据把标注好的目标实例随机粘贴到古建筑背景图上同时做随机缩放、旋转、亮度扰动这一招能有效补足“有病害的结构件”这类稀缺组合。数据集规模不需要追求上万张。目标检测项目里每类300张以上、总计1200到2000张已经足够支撑一个能演示的模型。关键是类别平衡如果“完好木柱”有800张“脱落”只有50张训练时脱落几乎学不出来。我一般用脚本统计每类标注框数量最少的一类不低于总数的10%不够就针对性补拍或者做粘贴增强。标注规范上有一个容易忽略的点遮挡严重的实例不要硬标。两个目标重叠超过50%时如果都画框训练时NMS和loss都会打架。我的做法是只标注可见面积超过70%的目标遮挡太严重的直接跳过这样模型学到的特征更干净。小目标方面裂缝这类细长目标如果原图里只有几十个像素宽直接标进去大概率被当噪声可以先做切片放大再标注。2.3 Labelme标注与YOLO格式转换一套能跑通的转换脚本Labelme导出的是JSON文件里面记录的是多边形顶点坐标而YOLOv8需要的是归一化的中心点坐标和宽高。转换脚本是这类项目里最该先写好的工具后面的数据增删都靠它。import json import os from pathlib import Path # 类别顺序要和 data.yaml 中的 names 保持一致 CLASS_MAP {wooden_column: 0, beam: 1, crack: 2, falling_off: 3, fire: 4, smoke: 5} def labelme_to_yolo(json_path, out_dir, img_width, img_height): with open(json_path, r, encodingutf-8) as f: data json.load(f) txt_name Path(json_path).stem .txt lines [] for shape in data[shapes]: label shape[label] if label not in CLASS_MAP: continue points shape[points] # 多边形顶点列表 [[x1,y1],[x2,y2],...] # 计算外接矩形 xs [p[0] for p in points] ys [p[1] for p in points] x_min, x_max min(xs), max(xs) y_min, y_max min(ys), max(ys) # 归一化到 0~1 center_x ((x_min x_max) / 2) / img_width center_y ((y_min y_max) / 2) / img_height box_w (x_max - x_min) / img_width box_h (y_max - y_min) / img_height lines.append(f{CLASS_MAP[label]} {center_x:.6f} {center_y:.6f} f{box_w:.6f} {box_h:.6f}) with open(os.path.join(out_dir, txt_name), w, encodingutf-8) as f: f.write(\n.join(lines))脚本逻辑不复杂核心是按 Labelme 的多边形顶点算外接矩形再用图片宽高做归一化。这里有两个值得注意的细节。第一个是CLASS_MAP必须和 YOLOv8 的data.yaml里的names顺序完全一致一个非常典型的翻车现场是标注文件里顺序是“裂缝、柱子”训练配置里写成了“柱子、裂缝”模型训完预测框标签全错位。第二个细节是宽高比极端的目标比如裂缝归一化后box_w只有 0.02box_h却有 0.6这种框在训练时容易被当成异常样本过滤掉如果发现裂缝类AP特别低多半是这个原因解决办法是调低anchor阈值或者干脆做切片训练。转换完成后按 8:1:1 分训练集、验证集、测试集目录结构照 YOLO 惯例放dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── data.yaml3. 训练全流程从Ubuntu 20.04环境到一组能复现的参数3.1 Ubuntu 20.04 CPU版环境搭建最小依赖清单古建筑监测系统大量复现教程跑在Ubuntu 20.04上如果你的开发机是Windows也可以先装WSL2再走这套命令。CPU版环境的核心就一句话不要先装PyTorch再装ultralytics那样容易把依赖搞乱。顺序应该是先建虚拟环境再装CPU版PyTorch最后装ultralytics和标注工具。# 1. 更新系统并安装 python3-venv sudo apt update sudo apt install -y python3-venv python3-pip # 2. 创建独立虚拟环境避免污染系统 Python python3 -m venv ~/venvs/yolo_env source ~/venvs/yolo_env/bin/activate # 3. 安装 CPU 版 PyTorch注意是 cpu 版本的 index-url pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu # 4. 安装 ultralytics 和可视化依赖 pip install ultralytics labelme pyqt5 opencv-python # 5. 验证安装 python -c from ultralytics import YOLO; print(ok)CPU版训练不是不能跑而是要选对模型尺度。yolov8n.pt 在 i5 级别的CPU上训练300张图每个epoch大约1到2分钟整体能接受yolov8m.pt 直接乘4到5倍起步就不推荐。这里有个容易被忽略的点CPU版PyTorch安装时一定要带--index-url参数否则pip默认拉的是CUDA版虽然能装上但运行时没有任何加速还会白白占几个GB磁盘。装完验证一下import能看到ok再往下走。3.2 训练参数含义与起步配置一份可直接改的数据集YAML训练前先写data.yaml这是把数据集和模型连接起来的枢纽文件。一个可以直接改的古建筑场景版本长这样# 数据集根目录建议用绝对路径避免相对路径在不同终端下失效 path: /home/user/dataset train: images/train val: images/val test: images/test names: 0: wooden_column 1: beam 2: crack 3: falling_off 4: fire 5: smoke这个文件有三个常见错误源头names顺序错位、path写相对路径导致找不到图片、test字段缺失会被某些脚本当成 val 处理。确保目录存在后训练命令如下yolo detect train \ datadataset/data.yaml \ modelyolov8s.pt \ epochs100 \ imgsz640 \ batch8 \ device0 \ workers4 \ patience15如果是在CPU上跑把device0改成devicecpu。先说modelyolov8s.pt这表示在官方COCO预训练权重上继续微调而不是从零训练迁移学习能省掉大量迭代次数。真从零训练古建筑模型没有一两万张图很难收敛。patience15是早停参数连续15个epoch验证集指标不提升就自动停防过拟合也省时间。这里把几个关键参数列一下方便训练前对照检查参数作用我的建议model基础权重决定模型骨架起步用 s演示够用追求速度换 nepochs最大训练轮数100 起步看曲线再决定是否延长imgsz输入图片分辨率640 是速度和精度折中裂纹多就试 960batch每批图片数显存8G用86G用4CPU用2device计算设备有N卡写0纯CPU写cpuworkers数据加载线程数4到8过高会拖慢训练patience早停耐心值10到20防止后期过拟合cache是否缓存图片True 可加速但吃内存这组参数跑完如果数据质量正常验证集mAP一般能做到0.75以上。如果低于0.5先别急着调参回去看数据集和标签九成是标签错位或者类别不平衡。3.3 损失曲线怎么读box_loss、cls_loss和dfl_loss的翻车信号YOLOv8训练完会自动生成runs/detect/train/results.png里面包含三张关键损失曲线box_loss、cls_loss、dfl_loss。很多同学拿到图就问“这个loss降到多少算好”其实绝对值没有通用标准不同数据集、不同imgsz的loss范围都不一样要看趋势和组合信号。我的读图习惯是先看 cls_loss 是否持续下降并收敛到平台期。这条曲线反映的是“有没有把类别认对”古建筑场景类别差异大柱子和火焰长得很不一样cls_loss如果震荡不降说明类别定义有歧义或者标注错位。再看 box_loss它反映的是框的位置精度如果box_loss下降缓慢背后多半是裂缝这类宽高比极端的目标在拖后腿对策是把 imgsz 从 640 提到 960。dfl_loss 是分布焦点损失管的是边框回归的分布质量这条曲线在epoch前20轮波动大是正常的如果全程抖动剧烈优先怀疑batch_size太小。两条典型的翻车曲线值得认识。一种是 loss 在第20轮左右降到很低后面 val loss 开始反弹这是过拟合的典型信号尤其当训练集只有几百张时。对策是把 epochs 减少到80或者把patience设小一点让早停提前生效。另一种是 loss 从第一步开始就停在某个高位不动这几乎可以断定是标签文件为空、类别索引越界、或者data.yaml里 path 没写对。遇到这种情况先随机打开一张标注txt看一眼内容而不是去改学习率——改学习率救不了空标注。4. 可视化界面把权重文件变成能演示的监测系统4.1 界面选型Tkinter够用、PyQt5更好扩展训练完的权重只是一个.pt文件离“系统”还差一个能点、能看、能截图的界面。界面层我建议在 Tkinter 和 PyQt5 之间选不要一上来就上 Web 前端理由很实际毕设答辩的环境往往没有Node、没有浏览器外网依赖一个Python脚本双击就能跑的桌面程序最稳妥。方案开发速度控件丰富度实时刷新打包体积Tkinter快标准库自带一般一般小PyQt5中等丰富支持表格和拖拽较强较大Web界面慢需前后端最强强依赖浏览器如果是课程设计一周内要出demoTkinter直接写就能交货。如果想做得更像一个“系统”或者后续要加历史记录表格、检测结果统计PyQt5更合适。下面的示例按PyQt5写因为它在图片缩放显示和摄像头拉流上比Tkinter顺手很多。4.2 三路输入图片、视频和摄像头实时预览界面核心逻辑只有三块选输入源、调用模型推理、把结果画到界面。以下是一个能直接跑的最小实现片段省略了按钮布局部分聚焦在推理调用方式上。import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel, QPushButton, QFileDialog from PyQt5.QtGui import QImage, QPixmap from PyQt5.QtCore import QTimer import cv2 from ultralytics import YOLO class DetectWindow(QMainWindow): def __init__(self): super().__init__() self.model YOLO(runs/detect/train/weights/best.pt) self.label QLabel(self) self.label.resize(800, 600) self.btn_img QPushButton(选择图片, self) self.btn_img.clicked.connect(self.on_image) self.btn_cam QPushButton(开启摄像头, self) self.btn_cam.clicked.connect(self.on_camera) # QTimer 控制摄像头帧率避免界面卡死 self.timer QTimer() self.timer.timeout.connect(self.on_frame) def predict_frame(self, frame): # 模型推理conf 阈值可在这里控制 results self.model.predict(sourceframe, conf0.35, device0) return results[0].plot() # ultralytics 自带画框结果 def on_image(self): path, _ QFileDialog.getOpenFileName(self, 选择图片, , *.jpg *.png) if not path: return img cv2.imread(path) img self.predict_frame(img) self.show_cv_img(img) def on_camera(self): self.cap cv2.VideoCapture(0) self.timer.start(30) # 约 33ms 一帧 def on_frame(self): ok, frame self.cap.read() if not ok: return frame self.predict_frame(frame) self.show_cv_img(frame) def show_cv_img(self, img): img cv2.cvtColor(img, cv2.COLOR_BGR2RGB) h, w, _ img.shape qimg QImage(img.data, w, h, 3 * w, QImage.Format_RGB888) self.label.setPixmap(QPixmap.fromImage(qimg))这段代码里最关键的是results[0].plot()它会自动把边界框、类别名和置信度绘制到原图上。十个做界面的人里有八个自己写画框函数结果不是坐标偏移就是颜色对不上直接用plot()省心。另一个细节是QTimer摄像头视频流如果在UI线程里用while True读取窗口拖动时会卡成PPT放到定时器里逐帧拉流界面才能保持流畅。设备参数device0表示用本机显卡CPU机器改成devicecpu否则首次推理会报CUDA错误。4.3 结果叠加与预警逻辑框和置信度怎么处理检测框画出来以后预警逻辑是让系统“像个监测系统”的点。基础做法是按类别设定置信度阈值结构件类阈值可以放宽到0.3因为柱子、梁这类大目标即使置信度低框位置也是准的病害类阈值建议0.5以上裂缝和脱落误报在演示时非常扎眼。如果想让界面更完整可以在检测结果里加入一个“预警标签”from collections import Counter def parse_results(res): boxes res.boxes names res.names confs boxes.conf.tolist() clses boxes.cls.tolist() counts Counter(names[int(c)] for c in clses if confs[clses.index(c)] 0.5) alarm [] if counts.get(crack, 0) 2 or counts.get(fire, 0) 0: alarm.append(存在病害或火情风险请复核) return counts, alarm预警规则不要一口气写太多条演示时需要的是“某个时刻界面弹出一条明确提示”的效果。常见做法是检测到明火或烟雾立即红色报警裂缝和脱落数量超过设定阈值时黄色提醒其他情况只做计数统计。5. 部署与避坑从训练机搬到演示机的最后几公里5.1 模型导出与打包ONNX与PyInstaller的顺序毕设系统最终要交一个“能直接运行”的东西这就牵扯到模型导出和程序打包。一个常见错误是直接用PyInstaller打包整个torch和ultralytics环境结果exe动辄好几GB启动还要解压半天。更顺滑的路径是先导出ONNX再让界面代码加载ONNX模型PyInstaller打包时就能避开复杂的torch依赖链。yolo export modelruns/detect/train/weights/best.pt formatonnx imgsz640 dynamicTrue导出时加dynamicTrue可以让输入尺寸不固定方便界面处理不同分辨率的图片。ONNX模型在CPU上的推理速度通常比PyTorch原版快30%以上对没有独显的答辩机器很友好。导出成功后把界面代码里的YOLO(best.pt)换成YOLO(best.onnx)其余逻辑不用动。PyInstaller打包时用一条命令就够了pip install pyinstaller pyinstaller -w -F main.py --hidden-importultralytics-w表示不显示控制台窗口-F打包成单文件。这一步有个坑ultralytics有大量动态导入打包时容易漏跑起来黑屏无报错这时需要在界面入口加一段日志输出定位到缺哪个模块再补--hidden-import。如果时间紧张也可以不改ONNX直接把整个conda环境目录拷给同版本系统的机器配合一个启动脚本比PyInstaller省心但不够“专业”。5.2 避坑案例标注、漏检、卡顿与导出问题第一条标注类别顺序和data.yaml不一致导致预测标签全部错位。现象是柱子被识别成火焰裂缝被识别成烟雾但框的位置看起来很准。原因是Labelme导出的JSON标签顺序与训练配置不同通常发生在多次增删类别之后。解决方法是写一个小脚本读取训练集任意几个txt打印每行第一个数字与类别名的对应关系核对无误再重新训练。第二条裂缝类目标AP为0或接近0。现象是验证集上其他类都很正常唯独裂缝一个都框不出来。原因是裂缝细长标注框极端宽高比导致它在特征图下采样后面积过小直接被当背景丢弃。解决方法是训练时把imgsz提到960或者对裂缝样本做切片处理把原图切分成2x2或4x4再标注训练。实测切片后裂缝类AP能从0.2涨到0.7以上。第三条界面拖动时卡顿摄像头预览延迟严重。现象是拖动窗口时画面撕裂摄像头画面比实际慢两秒。原因是推理直接在GUI线程里执行单帧推理耗时阻塞了界面绘制。解决方法是把推理放到QThread子线程主线程只负责显示结果队列里的最新一帧这里不需要复杂的双缓冲一个queue.Queue就够了。第四条ONNX导出后精度明显下降。现象是原来能框出的目标换ONNX后置信度普遍低0.1到0.2。原因常见为导出时opset版本和onnxruntime版本不匹配或者训练时启用了某些仅训练期生效的增强。解决方法是先在导出机器上pip install onnxruntime再用onnxruntime加载模型逐张图对比预览确认损失可接受再打包。第五条程序装到演示机后启动黑屏无响应。现象是双击exe后界面不出现任务管理器里能看到进程但无窗口。原因基本是PyInstaller漏掉了ultralytics的动态子模块或者路径写死了训练机的绝对地址。解决方法是启动脚本里先输出日志到文件定位缺失模块模型文件路径用sys._MEIPASS拼接不要用项目目录写死。5.3 硬件边界从1660 Ti到RK3588模型尺度怎么定演示机不一定是训练机硬件决定了模型尺度上限。这里给一组实际经验值覆盖最常见的三种部署环境硬件可跑模型推理耗时640输入建议GTX 1660 Ti 6Gyolov8s约25ms训练机和演示机都用它最省心笔记本CPUi5/R5yolov8n约200-400ms用ONNX格式能到实时边缘RK3588板卡yolov8n约40-80msNPU需要用RKNN导出一轮模型转换GTX 1660 Ti跑yolov8s是最舒服的组合显存6G刚好能支撑batch8训练推理也够实时。如果演示机是普通笔记本强烈建议训练时直接选yolov8n用精度换流畅度否则答辩现场摄像头预览一秒两帧观感很差。RK3588这类板卡是进阶方向ultralytics导出ONNX后再用RKNN-Toolkit转换成板端格式主要留意的是量化掉点问题INT8量化后裂缝类AP常有可见下降建议先用val集量化评估再决定是否上板。6. 验证与再进阶mAP之外还要会看坏例训练完不要只盯着mAP数字。完整验证步骤应该包含三件事在测试集上跑官方验证脚本拿mAP和PR曲线检查每类AP的离散程度生成混淆矩阵看哪些类别互相打架把验证集里预测错误的图片抽出来按置信度从高到低逐张翻你会很快发现模型其实没学会“裂缝”只是记住了“所有深色纹理都算裂缝”。yolo detect val modelruns/detect/train/weights/best.pt datadataset/data.yaml这条命令会在runs/detect/val下生成混淆矩阵和PR曲线。古建筑场景里最常见的错误配对是脱落和裂缝、木柱和梁如果混淆矩阵这两格颜色深回来检查标注框是否画得太随意。坏例分析比调参更重要因为绝大多数问题都出在数据而不是网络结构上。再进阶的方向有三条。一是模型轻量化把训练好的yolov8s蒸馏到yolov8n精度损失通常可控推理速度提升明显二是接入RK3588等NPU平台完成从PC到边缘设备的迁移这类“部署到国产边缘计算平台”的加分点在毕设答辩里很受欢迎三是数据迭代把第一次训练中置信度高于0.9的预测结果半自动转成新标注补回训练集再训一轮能稳定涨点。做完整套再回头看这项目最值的不是代码而是那套自己能不断复用的数据标注和验证流程。按这套流程走下来踩坑大多能提前躲开。希望帮到你。本文还有配套的精品资源点击获取