基于YOLOv8的教室窗户破损识别系统:从数据集到可视化部署

发布时间:2026/8/31 16:25:57
基于YOLOv8的教室窗户破损识别系统:从数据集到可视化部署 简介本资源是一套基于YOLOv8的教室窗户破损识别系统完整实现面向计算机科学、人工智能、自动化等专业的在校学生及初学者解决教育场景中窗户安全状态智能巡检的实际问题适用于毕业设计、课程设计、大作业或项目原型开发。压缩包共8个文件3个Python主程序、3个PyTorch模型文件、2个说明文档总大小15.91MB涵盖训练、推理、可视化全流程包含可直接运行的图形化界面Visual_interface.py、预训练与最优权重模型yolov8n.pt、best.pt、视频检测脚本Detection_video.py及详细部署指南与README说明。已有40人学习下载所有代码均经实测验证支持一键启动并自动生成F1分数曲线、混淆矩阵、PR曲线、验证集预测图与标签分布图等核心评估结果结构清晰、注释完备无需调参即可获得可信检测效果是兼具工程完整性与教学实用性的高质量毕设级视觉识别方案。1. 项目选题与整体设计方案1.1 为什么选“教室窗户破损识别”这个方向每年到了毕业设计选题季我都会收到不少学弟学妹的咨询问到底选什么题目既好做、又能出成果、还不容易被导师卡住。说实话“教室窗户破损识别”这个方向在计算机视觉的众多题目里属于性价比很高的一类。它不像人脸识别、车牌识别那样被做烂了也不像医疗影像、遥感分析那样对数据量和算力要求极高但又确确实实是一个有明确落地场景的“视觉检测”任务。窗户破损检测为什么值得做往小了说它是校园设施巡检的刚性需求——老旧教学楼的外窗常年风吹日晒玻璃开裂、边角碎裂、密封条老化都是安全隐患靠人工巡检效率太低而且很多窗户位置较高肉眼很难看清。往大了说这套技术本质上是“缺陷检测”的通用范式换一个数据集就能迁移到厂房玻璃幕墙检测、温室大棚玻璃破损检测、公交站台玻璃破碎报警等场景。所以做这个选题你积累的不是“一个作业”而是一套可复用的目标检测流水线能力。我当时做这个项目最核心的技术选型就是YOLOv8。为什么不用Faster R-CNN也不用SSD因为YOLOv8在精度和速度之间平衡得非常好尤其适合毕设这种需要“快速出效果、还能跑得动”的场景。Faster R-CNN虽然精度天花板更高但训练和推理速度太慢你自己调参的迭代周期会非常痛苦。而YOLOv8在GTX 1660 Ti这种级别的显卡上就能流畅训练推理帧率更是实时级别做可视化界面演示的时候体验特别顺滑。1.2 系统整体架构与技术路线整套系统的架构并不复杂但模块划分很清晰。我把它拆成了四个部分数据层、训练层、推理层、展示层。数据层负责数据的采集与标注。这里不依赖任何现成的公开数据集因为“教室窗户破损”这种细粒度场景公开数据集里几乎找不到现成的标注。所以我采用的是自己拍摄网络爬取辅助扩充的方式再用LabelImg逐张标注最后做数据增强来扩充样本量。训练层基于Ultralytics官方提供的YOLOv8框架直接使用Python接口训练。训练过程中最关键的是数据集的YAML配置、超参数调整和训练日志监控。这一步做好了模型的mAP能达到比较理想的水准。推理层负责将训练好的模型权重加载进来对图片、视频或摄像头实时画面进行检测。这个环节的核心是封装一个推理类对外提供统一的接口方便可视化界面调用。展示层就是大家最关心的可视化界面我用PyQt5来做。界面包含图像显示区、检测设置区、结果统计区和日志输出区。用户可以通过界面上传图片、选择视频文件、打开摄像头检测结果实时显示在窗口中识别到的破损窗户会用边界框框出来并标注类别和置信度。技术栈总结下来就是YOLOv8 PyTorch PyQt5 OpenCV LabelImg PyInstaller。其中PyTorch负责模型训练OpenCV负责图像处理与摄像头采集PyQt5负责界面呈现PyInstaller负责最终的打包发布。注意如果你拿到的项目压缩包里自带了一个训练好的best.pt权重文件那我强烈建议你拿到手先别急着重新训练直接跑一遍推理demo确认流程通了之后再考虑要不要自己重新训练一轮。这样做的原因很朴实环境问题比模型问题更容易让你崩溃先通流程再调精度是最高效的路径。1.3 项目的难点与亮点分析这个项目真正的难点不在“训练模型”而在“数据”和“场景适配”。窗户破损的形态千差万别有的是整块玻璃碎裂成蜘蛛网状有的是边角缺了一小块有的是玻璃上出现了贯穿性的长裂纹还有的是窗框松动导致玻璃移位。这些形态差异非常大如果数据不够丰富模型很容易过拟合到某一种特定形态上。另一个难点是背景干扰。教室窗户后面往往有窗帘、黑板、桌椅、树木等复杂背景遮挡和反光也会对检测造成干扰。这要求我们在标注数据的时候就要有意识地让样本覆盖各种光线条件和遮挡情况。至于亮点我觉得有两个第一整个系统是一个“能演示、能落地、能答辩”的完整闭环从数据集到训练再到可视化界面全部打通这在毕设评分里非常有优势。第二我做了数据增强的多样化配置包括亮度调整、旋转、平移、缩放、翻转等大幅提升了模型在真实环境下的泛化能力。2. 数据集构建与标注实操2.1 数据从哪里来采集策略与数据规模很多同学做毕设的时候卡在第一步“我上哪儿找那么多窗户破损的图片” 我的经验是三步走。第一步自己拍。如果你所在的教学楼恰好有一些旧窗户、裂纹玻璃那就拿手机在不同时间段、不同角度多拍一些。白天拍逆光的傍晚拍顺光的晴天拍反射的阴天拍散射的。拍的时候注意覆盖不同楼层、不同教室、不同窗户样式。别小看自己拍的照片这些恰恰是最贴近实际部署场景的正样本。第二步网络获取。可以到开源图片网站搜索“broken window glass”“cracked window”等关键词用脚本批量下载。这样做的好处是快速扩充数据量但需要注意图片质量和版权问题——用于学术研究问题不大商用需要谨慎。下载之后要人工筛选一遍去掉低分辨率、严重模糊、纯示意图等干扰图片。第三步间接扩充。如果实在凑不够破损样本可以把“完好的窗户”也加入数据集作为背景负样本。虽然YOLO并不强制要求负样本但加入一定比例的负样本可以减少误检让模型明白“不是所有窗户都要框出来只有破损的才要框”。我最终的数据集规模是破损窗户图片约1800张负样本完好窗户约400张总计2200张。按7:2:1的比例划分训练集、验证集和测试集。这个规模对于单类别目标检测来说属于中等偏小但因为加了数据增强实际训练效果完全够用。2.2 标注工具与标注规范LabelImg实操指南标注工具我用的是LabelImg这是视觉检测入门最经典的标注工具纯图形界面安装简单导出的格式能直接转成YOLO需要的txt格式。安装LabelImg有两种方式。一种是pip安装pip install labelImg另一种是GitHub克隆源码后运行git clone https://github.com/HumanSignal/labelImg.git cd labelImg pyrcc5 -o libs/resources.py resources.qrc python labelImg.py推荐用第一种方式省事。标注过程有几个非常关键的细节直接决定模型好坏。首先是标注框的紧致度不要像画简笔画一样大概框个范围就完事而是要紧贴破损区域的边缘。YOLO的训练逻辑是将候选框与标注框计算IoU如果你的标注框比实际目标大一圈模型学出来的预测框也会偏大如果标注框只框住了破损的一部分模型学到的特征就不完整。其次是破损伤痕的标注策略一块大面积碎玻璃上有多条裂纹不要标注成多个小框而是用一个稍微大一点的框覆盖整个破损连通区域除非两条裂纹中间有明显的完好区域分隔。再有就是边界情况的处理如果窗框和玻璃同时出现在画面里只标注玻璃破损的部分不要把“窗户存在”本身误标成破损。我把标注要点整理成了一张速查表给当时一起做项目的小伙伴用情况标注策略整块玻璃大面积碎裂用一个大框覆盖整个碎裂区域边角缺块框住缺口边缘不要包含完好的窗框细长裂纹框住整条裂纹框边距裂纹边缘3到5像素玻璃表面反光严重标注前调整亮度确认破损区域避免把反光误判为裂纹多扇窗户同框只有可见破损的那扇标框完好窗户不标轻微破损、不确定是否标注宁缺毋滥删除该图或做负样本2.3 数据增强与格式转换从XML到YOLO的txtLabelImg默认导出的是Pascal VOC格式的XML文件YOLOv8需要的却是每个图片对应一个同名txt文件的格式内容为“类别编号 x_center y_center width height”其中x_center、y_center、width、height都是归一化到0到1之间的相对坐标。转换脚本其实不复杂核心代码如下import os import xml.etree.ElementTree as ET def convert_voc_to_yolo(xml_path, save_dir, classes): tree ET.parse(xml_path) root tree.getroot() img_w int(root.find(size/width).text) img_h int(root.find(size/height).text) out_lines [] for obj in root.findall(object): cls_name obj.find(name).text if cls_name not in classes: continue cls_id classes.index(cls_name) bbox obj.find(bndbox) xmin int(bbox.find(xmin).text) ymin int(bbox.find(ymin).text) xmax int(bbox.find(xmax).text) ymax int(bbox.find(ymax).text) x_center ((xmin xmax) / 2) / img_w y_center ((ymin ymax) / 2) / img_h width (xmax - xmin) / img_w height (ymax - ymin) / img_h out_lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {width:.6f} {height:.6f}) if out_lines: txt_name os.path.splitext(os.path.basename(xml_path))[0] .txt with open(os.path.join(save_dir, txt_name), w) as f: f.write(\n.join(out_lines))数据增强我用的不是自己手写的图像处理函数而是直接利用YOLOv8训练时自带的在线增强策略。Ultralytics框架在训练阶段默认会做马赛克增强mosaic、随机翻转、随机色彩抖动等操作这些不需要我们额外配置。不过如果你发现自己的数据集偏小可以在训练参数里把hsv_h、hsv_s、degrees这些增强强度调高一点。我当时把degrees设成了10即允许正负10度旋转把hsv_s从默认的0.7调到了0.9有效提升了模型对不同光线条件的适应能力。3. 模型训练与调试全流程3.1 环境配置从零到能跑通YOLOv8训练环境我是这么搭的操作系统Windows 11显卡GTX 1660 Ti显存6GB。这个配置属于学生党的经典配置性能不算强但跑YOLOv8n和YOLOv8s是绰绰有余的。Python环境管理我强烈建议用Anaconda专门为这个项目建一个独立的虚拟环境避免和日常开发环境互相污染。conda create -n yolo-window python3.9 conda activate yolo-window pip install ultralytics pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 pip install pyqt5 opencv-python pillow这里有一个非常容易踩的坑PyTorch和CUDA版本的匹配问题。如果你直接用pip install torch装的很可能是CPU版本训练速度慢到怀疑人生。正确的做法是先到PyTorch官网根据自己的CUDA版本选择对应的安装命令。GTX 1660 Ti的驱动支持CUDA 11.8所以用上面的命令装cu118版本是稳妥的。装完之后可以用下面的命令验证CUDA是否可用import torch print(torch.cuda.is_available()) # 输出True说明GPU可用 print(torch.cuda.get_device_name(0))如果输出True恭喜你GPU环境配好了。如果输出False大概率是PyTorch版本装错了回炉重装。3.2 数据集组织与YAML配置文件编写YOLOv8训练前需要把数据集按照固定的目录结构组织好datasets/ windows/ images/ train/ val/ test/ labels/ train/ val/ test/ data.yaml注意images和labels两个目录下的子目录名称必须完全对应——images/train里的每张图片必须在labels/train里有同名的txt标注文件。一个很常见的低级错误是图片缩略名和标注名对不上导致训练时报“Found no labels”的警告。data.yaml文件是训练的关键配置内容如下train: D:/yolov8-window/datasets/windows/images/train val: D:/yolov8-window/datasets/windows/images/val test: D:/yolov8-window/datasets/windows/images/test nc: 1 names: [broken_window]这里有两个坑。第一路径建议写绝对路径不要写相对路径。虽然Ultralytics支持相对路径但有时候工作目录切换会导致路径解析失败绝对路径最保险。第二nc即类别数量如果你的项目只有“破损窗户”一个类别那就是1如果你做了多类别比如“broken_window”“good_window”“cracked_frame”三个类别nc就要改成3names也要对应修改。3.3 训练参数选择与调优心得训练命令本身不复杂核心是参数的理解和选择。yolo detect train datadata.yaml modelyolov8n.pt epochs100 imgsz640 batch8 device0 projectruns nameexp1我第一次跑的时候用的是YOLOv8s预训练权重batch设为8epochs跑到80轮左右验证集mAP50大概在0.78左右。后来我换了YOLOv8n发现虽然参数量小了三分之一但在这个相对简单的单类别任务上mAP50居然还能保持在0.74以上而训练速度提升了很多。如果你拿到的显卡显存只有4GB建议直接用yolov8n.pt把batch降到4还是能顺利跑完的。几个重要的参数我展开讲一下imgsz是输入图像的尺寸默认640。在显存允许的情况下越大理论上精度越高但训练速度会变慢。如果图像里窗户本身很小、破损区域很细微可以考虑把imgsz设为800或者960但代价是显存占用大幅上升。batch是批大小受显存限制。6GB显存跑yolov8n、imgsz640时batch8比较稳batch16容易OOM。如果显存不够但你又不想降batch可以开启梯度累积——用ultralytics的nbs名义批大小参数设置nbs64它会自动在每积累到64张图后才更新一次权重。epochs是训练轮数。不要盲目追求大epochs尤其是数据量不大的情况下训练到后面会出现过拟合——训练集loss降得挺漂亮验证集mAP反而开始往下掉。我建议训练过程中密切关注val loss曲线的拐点在验证集性能不再提升的时候提前停止使用early-stopping机制Ultralytics默认开启patience默认100。训练完成后在runs/detect/exp*/weights/目录下会生成两个文件best.pt和last.pt。best.pt是验证集表现最好的权重last.pt是最后一轮的权重。部署和推理一律使用best.ptlast.pt只是用来断点续训的。3.4 训练日志分析与精度评估训练过程输出的日志信息很丰富但很多初学者看不懂。我挑几个关键指标解释一下box_loss边界框回归损失反映预测框与真实标注框的位置差异。这个值越低越好。cls_loss分类损失反映类别预测的对错。单类别分类一般不会太差。dfl_loss分布焦点损失是YOLOv8特有的一种边界框回归辅助损失。mAP50IoU阈值为0.5时的平均精度。这是最常看的指标0.5以上算及格0.7以上算表现不错。mAP50-95IoU从0.5到0.95的区间平均精度这个指标更严格通常比mAP50低不少。我当时最好的模型是YOLOv8s训练100轮后的结果mAP50约0.82mAP50-95约0.56精度precision约0.87召回recall约0.79。对于单类别窗户破损检测而言这个成绩已经能满足实际使用需求了。如果你训练完发现mAP50始终在0.5以下先别急着调网络结构检查一下数据集标注是否准确、数据量是否太少、学习率是否过大。大部分初学者模型效果差问题都出在数据上而不是网络上。3.5 模型改进思路轻量化与注意力机制如果你学有余力想把模型效果再往上提一档可以尝试两个方向。第一个方向是模型剪枝和轻量化。YOLOv8本身有n/s/m/l/x五个版本如果部署环境算力紧张可以用YOLOv8n作为baseline再做通道剪枝把不重要的卷积通道去掉模型大小可以再压缩30%左右。剪枝的工具可以用Ultralytics自带的prune功能也可以用torch.prune手动实现。第二个方向是引入注意力机制。比如在C2f模块中嵌入SE模块或CBAM模块让模型更加关注破损区域的特征而忽略背景干扰。这个操作需要修改YOLOv8的网络结构代码建议在修改前先备份原始模型定义文件。我试过在 backbone 的最后一个 C2f 模块后面加一个 SE 注意力模块mAP50约提升2到3个百分点代价是推理时间增加了约15%。对毕设来说这个精度的提升完全是收益大于成本。4. 可视化界面开发与部署打包4.1 界面功能规划与布局设计可视化界面是毕设答辩时候的“门面”一个操作顺畅、界面清爽的系统确实能给你的答辩表现加分不少。我当时用PyQt5做的界面整体布局是左右结构的左侧是图像显示区负责显示原始图像和检测后的结果图像占整个窗口大约70%的宽度。右侧是控制面板从上到下依次是模型加载按钮、图片检测按钮、视频检测按钮、摄像头检测按钮、置信度阈值滑块、检测类别选择下拉框、实时结果统计检测个数、处理耗时、日志输出框。窗口标题栏显示“教室窗户破损识别系统”底部状态栏显示当前使用的模型路径和推理设备。具体到PyQt5的组件选型图像显示用QLabel配合setPixmap显示QPixmap按钮用QPushButton滑条用QSlider下拉框用QComboBox日志输出用QTextEdit并设置为只读模式。整体代码量在600行左右工作量适中适合在答辩前集中时间完成。4.2 核心推理模块封装与集成界面写得再花哨如果推理模块耦合得乱七八糟后面调试的时候会非常痛苦。我的建议是单独写一个detector.py文件封装一个WindowDetector类对外提供简洁的接口。from ultralytics import YOLO import cv2 class WindowDetector: def __init__(self, model_path, conf_thres0.25): self.model YOLO(model_path) self.conf_thres conf_thres def detect_image(self, image_path, save_pathNone): results self.model.predict( sourceimage_path, confself.conf_thres, verboseFalse ) annotated results[0].plot() if save_path: cv2.imwrite(save_path, annotated) return annotated, len(results[0].boxes) def detect_frame(self, frame): results self.model.predict( sourceframe, confself.conf_thres, verboseFalse ) annotated results[0].plot() return annotated, len(results[0].boxes)detect_image接收图片路径返回标注后的图像和检测数量detect_frame接收一帧图像numpy数组返回标注帧和检测数量。界面线程只需要调用这两个方法就能完成所有检测逻辑完全不需要关心模型内部的实现细节。这里有一个多线程的问题必须注意PyQt5的主线程是GUI线程负责刷新界面。如果直接在按钮点击事件里调用模型推理推理过程会阻塞界面导致窗口卡死。正确做法是用QThread或者QThreadPool将推理任务放到子线程中执行推理完成后通过信号槽机制把结果传回主线程更新界面。我第一次写的时候偷懒没有用多线程结果在视频检测的时候窗口直接假死后来老老实实改成了线程池方案才解决这个问题。4.3 依赖打包与exe生成PyInstaller避坑实录打包是整个项目交付的最后一公里也是坑最多的一环。打包工具我用的是PyInstaller命令如下pip install pyinstaller pyinstaller -D -w main.py --name WindowDetector --icon icon.ico-D参数表示生成目录模式dist目录下会有整个文件夹-w表示不显示控制台窗口。如果你希望双击exe之后能看到控制台日志可以去掉-w调试阶段建议不要带-w方便看到报错信息。打包过程中我踩过几个印象很深的坑分享出来帮大家避雷第一个坑是模型路径问题。PyInstaller打包后的exe在运行时当前工作目录不一定是exe所在目录。如果你在代码里写了相对路径来加载模型很容易出现“文件找不到”的报错。解决方案是把模型文件放进资源目录或者用sys._MEIPASS来获取打包后的临时解包目录。更简单粗暴的方案是让程序启动时弹窗让用户手动选择模型路径虽然体验略差但最不容易出错。第二个坑是动态库丢失。PyQt5和OpenCV都有大量的C动态链接库PyInstaller默认会尝试自动收集但偶尔会漏掉一些。如果你遇到“DLL load failed”的报错可以用--collect-all参数强制收集pyinstaller -D -w main.py --name WindowDetector --collect-all ultralytics --collect-all cv2 --collect-all PyQt5第三个坑是打包体积过大。一个空白的PyQt5程序打包出来就有100多MB加上PyTorch库之后体积直奔1GB以上。这是因为PyTorch的CUDA运行库体积本身就很大。如果用户机器上没有NVIDIA显卡可以安装CPU版本的PyTorch再打包体积能省掉三四百MB但检测速度会慢一些。还能接受的话建议顺势把部署时的模型推理也切到CPU模式保证兼容性。4.4 完整部署流程与使用说明项目最终交付的时候我把整个部署流程整理成了一个文档确保一个从没接触过YOLO的用户也能看着文档跑起来。部署分两条路线源码运行和exe运行。源码运行适合有Python基础的用户步骤是安装Anaconda创建Python 3.9虚拟环境在虚拟环境中安装requirements.txt里的所有依赖将数据集目录放在项目根目录下或者直接使用训练好的权重运行main.py启动界面点击“加载模型”按钮选择best.pt文件点击“选择图片”或“选择视频”开始检测。exe运行适合完全不想碰代码的用户步骤更简单把dist/WindowDetector整个文件夹拷到目标机器双击WindowDetector.exe启动。注意要保证exe和模型文件在同一目录下并且目标机器上安装了VC运行库。4.5 常见问题快速排查表这部分是我觉得整个项目里最有价值的内容因为很多问题是只有真刀真枪跑过才发现得了的。我整理成了一个速查表现象可能原因解决方案训练时提示“Found no labels”标注txt文件和图片名称不对应检查labels目录下文件名是否与images一致检查转换脚本输出CUDA out of memorybatch过大或imgsz过大降低batch到4或2降低imgsz到480训练loss下不去数据标注错误过多学习率不合适抽样检查标注质量降低lr到0.001以下重训推理时误检率偏高置信度阈值过低将conf_thres从0.25提高到0.4到0.5界面点击检测卡死推理放在了主线程改成QThread子线程推理摄像头打开失败摄像头索引错误或被占用尝试cap cv2.VideoCapture(1)或释放其他占用程序PyInstaller打包后模型加载失败模型路径相对路径问题改用绝对路径或sys._MEIPASS方式加载视频检测帧率太低模型推理速度成为瓶颈换用yolov8n模型缩小imgsz开启half精度5. 项目验收要点与二次开发建议5.1 毕设答辩时的验收标准如果你把这个项目当毕设来推进答辩时老师最关心的几个点是数据集是否真实有效、模型是否自己训练过而不是只下载了个权重、系统演示是否流畅、对模型原理的理解是否到位。建议你提前准备好一份训练过程的截图记录包括每个阶段的loss曲线、验证集的mAP指标变化、以及几张典型图片的检测效果对比。这些材料不仅能证明工作量也能在答辩现场帮你有理有据地讲清楚技术细节。5.2 从“够用”到“好用”的扩展方向一个模型训出来只是开始要把系统做得更有应用价值还有很多方向可以扩展。比如把视频检测改造成实时监控模式接入RTSP流就能对教学楼进行7x24小时的不间断巡检比如给检测系统加上告警能力检测到破损窗户后自动调用短信或邮件接口通知后勤人员再比如用TensorRT对模型做量化加速让推理速度在嵌入式设备上也保持实时。这些都是可以在原创性说明里突出写的加分项。我在实际使用中还有一个体会如果你手头的数据集里完好窗户的照片特别多你可以顺手训练一个两分类模型完好的窗户 vs 破损的窗户然后在界面里增加一个下拉框让用户自由切换检测模式。这个功能做起来不复杂但演示效果会非常惊艳因为老师会看到你的系统不仅能“找出破损”还能“区分好坏”。最后再分享一个小技巧如果你拿到的压缩包里自带的模型在你自己拍摄的照片上效果不好不要全盘否定它先检查一下输入图像的分辨率。很多模型训练时的imgsz是640如果你的照片是4000x3000的检测小目标时容易丢失细节。在界面里做一次自适应缩放把长边缩放到1280再送入模型往往就能明显提升效果。这种工程细节虽然不起眼但恰恰是区分“会用模型”和“会做系统”的分水岭。本文还有配套的精品资源点击获取