
简介这份资源是一套基于YOLOv8的停车场违规占道车辆检测系统面向计算机视觉、人工智能方向的学生及开发者适用于毕设、课程设计或初期项目演示。系统可对停车场内违规占道车辆进行实时检测与识别覆盖从模型训练到可视化交互的完整流程。资源包共8个文件以3个Python脚本、3个模型权重文件及2个说明文档为主其中脚本分别承担模型训练、视频检测和可视化界面展示功能压缩包整体约15.91MB结构清晰、部署门槛低。目前已有58人学习下载。作者在备赛与答辩基础上对代码进行了完整测试包含数据集、可视化页面与部署说明运行后可直接产出混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果及标签分布图等关键评估指标便于论文配图与答辩展示。对希望快速落地目标检测项目或完善毕设成果的读者而言这是一份拿来即用的完整参考方案。1. 毕设里那种“能运行就行”的YOLOv8项目到底该怎么落地很多同学拿到这个标题的第一反应是又是一个打包好的“毕设全家桶”解压、跑通、截图、写论文四步走完。但真正动手时你会发现能双击运行的demo和能通过答辩、能讲清楚原理的系统中间隔着一条巨大的沟。这个项目标题里的关键词——YOLOv8、停车场、违规占道、可视化界面、完整数据集、部署教程——每一个都是可以单独写一篇文章的点合在一起就是一个完整的计算机视觉工程闭环。我的建议是不要把这份资料当成“答案”而是当成“骨架”。你需要在它的基础上自己把数据、训练、推理、界面、部署这条链路走一遍。这篇文章我会按我实际做这类系统的顺序从数据集处理讲到界面打包把每一步的参数、命令和坑位都铺开。哪怕你手头没有这份zip照着下面的方法也能从零搭出一套可用的停车场占道检测系统——因为核心不是那个压缩包而是YOLOv8这条技术链路本身。2. 从原始视频到训练数据集停车场场景的标注与格式转换2.1 停车场违规占道检测到底检测什么先想清楚业务定义。停车场里的“违规占道”通常指三类车辆压线停放、车辆停在消防通道或禁停区、车辆逆向驶入或堵塞通道。但在目标检测层面你不需要让模型直接理解“违规”这个词——模型只负责输出“车在哪里”违规判定交给后端的几何规则。所以数据集的标注类别不需要太多。常见做法是两类一类是car所有机动车另一类是专门标注出来的“禁停区域”或者“占道状态”。但实际项目中我一般只标注car然后手动在代码里画出禁停区多边形检测到car的中心点或IOU落在禁停区里就判定为违规占道。这样做的原因很实在标注“违规状态”这个属性太主观不同人标的边界不一致模型很难学而只标车标注一致性高模型精度容易做上去。如果你手头的项目数据集里已经带了“违规”这个类别那训练时要注意样本均衡。停车场视频里正常停车的画面远超违规画面一个epoch里模型看到100个正常样本才看到2个违规样本损失函数会被带偏。解决办法是用focal loss或者在数据加载时对违规样本做过采样。YOLOv8里没有内置的过采样参数我一般是在Dataset类里做让违规帧的采样概率乘一个系数比如2到3。2.2 用Labelme标注车辆JSON格式怎么转成YOLO的txt不管数据集是从网上下载的还是自己拍的最终进YOLOv8训练之前标签格式必须统一。YOLO系列要的是每个图像对应一个txt文件每行是class_id x_center y_center width height坐标全部归一化到0到1之间。如果你用的是Labelme标注标出来的是JSON文件里面存的是多边形点坐标需要自己写转换脚本。这里给一个我常用的转换脚本支持多边形转矩形框import json import os from PIL import Image def labelme_to_yolo(json_path, img_path, output_txt_path, class_names): with open(json_path, r, encodingutf-8) as f: data json.load(f) img Image.open(img_path) img_w, img_h img.size lines [] for shape in data[shapes]: label shape[label] if label not in class_names: continue class_id class_names.index(label) points shape[points] # 多边形顶点列表 # 取多边形外接矩形 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) # 转YOLO格式 x_center (x_min x_max) / 2 / img_w y_center (y_min y_max) / 2 / img_h box_w (x_max - x_min) / img_w box_h (y_max - y_min) / img_h lines.append(f{class_id} {x_center:.6f} {y_center:.6f} {box_w:.6f} {box_h:.6f}) with open(output_txt_path, w) as f: f.write(\n.join(lines)) if __name__ __main__: class_names [car] # 按你的类别顺序写 json_dir labels_json img_dir images out_dir labels_txt for jf in os.listdir(json_dir): if not jf.endswith(.json): continue base jf.replace(.json, ) img_file os.path.join(img_dir, base .jpg) if not os.path.exists(img_file): print(f跳过 {base}找不到对应图片) continue labelme_to_yolo( os.path.join(json_dir, jf), img_file, os.path.join(out_dir, base .txt), class_names )这段脚本的逻辑分三步先读JSON拿到多边形顶点再算外接矩形最后用图片宽高归一化。注意class_names的顺序必须和训练时的data.yaml完全一致否则类别就错位了。我踩过这个坑——换了类别顺序忘了改data.yaml模型训练完检测结果全错排查了半天才发现是索引对不上。2.3 要多少张图才够训——停车场场景的最小样本量停车场场景有一个优势场景结构高度固定。摄像头位置不变光照变化有限背景几乎静止。这种场景下YOLOv8n从头训练大约需要600到800张标注图就能跑到一个可用的mAP0.85以上。但如果你的数据是从公开数据集凑的比如用COCO里的car类图片拼那场景泛化能力会差——停车场的地面纹理、车位线、禁停标志这些特征COCO里没有。我的建议是优先自己从监控视频抽帧。抽帧不要按时间均等抽要按“画面变化”抽——停车场一天里光照变化剧烈早晨逆光、中午强光、晚上灯下每个时段都要有。一个简单的做法是每5秒抽一帧然后人工删掉连续重复帧。1000张图的工作量用Labelme标注熟练的话一天半能完成。不要觉得1000张多这比训练完发现场景不对再回头补数据要省太多时间。如果你拿到的项目自带数据集也要先做清洗。打开每张图看一眼删掉模糊的、目标被严重遮挡的、以及标注框和物体明显对不上的。数据清洗是这类项目里回报最高的一步比调任何训练参数都管用。3. 训练前的环境与配置YOLOv8的CPU/GPU环境搭建与参数选择3.1 环境搭建的两种典型路径YOLOv8跑起来的前提是环境干净。这里的环境指三件事Python版本、PyTorch版本、CUDA版本。三者必须对齐否则会出现CUDA error: no kernel image is available或者装上torch但torch.cuda.is_available()返回False。这种问题占了毕设排障的七成都是环境不一致导致的。如果你手头没有NVIDIA显卡用CPU跑也不是不行。Ultralytics官方对CPU的支持做得很完整YOLOv8n在CPU上推理一张640x640的图大约需要300到500毫秒训练的话就慢了——1000张图、100个epochi5处理器大概要跑10个小时以上。CPU版本安装时注意不要装CUDA版的torch直接pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu即可。GPU环境则要先确认驱动版本和CUDA版本我的习惯是用nvidia-smi看驱动支持的CUDA版本再装对应版本的PyTorch不要盲目装最新版。3.2 训练前的配置文件data.yaml与模型选择YOLOv8训练前要准备一个data.yaml指向你的数据集和类别信息。这个文件看似简单但路径写错是常见问题——明明数据集在本地训练却报File not found。我的建议是绝对路径不要用相对路径因为YOLOv8的相对路径基准跟你的工作目录有关换目录就翻车。data.yaml的写法如下# 数据集绝对路径 path: /home/user/parking_dataset train: images/train val: images/val # 类别名称顺序必须与标注txt中的class_id对应 names: 0: car模型选型上停车场这类单一类别任务YOLOv8n就足够了。n模型11M参数训练速度快推理速度快精度在单一类别场景下不会比s或m差太多。如果你要写论文拿更漂亮的mAP曲线可以选YOLOv8s代价是显存从4G涨到8G左右。我做过对比同样的停车场数据n和s的mAP差距通常在0.02以内但s的推理时间翻倍。考虑到毕设演示时可能用CPU跑选n会更稳妥。3.3 训练命令与关键参数从epoch到batch size的取舍训练命令本身不复杂但参数背后的含义要清楚。这里给出一个我常用的训练命令yolo detect train \ --model yolov8n.pt \ --data /home/user/parking_dataset/data.yaml \ --epochs 100 \ --batch 16 \ --imgsz 640 \ --device 0 \ --optimizer AdamW \ --lr0 0.001 \ --patience 15几个参数的取舍逻辑batch由显存决定。6G显存跑batch 16没问题4G显存降到8。batch越大收敛越稳定但显存不够会OOM报错。patience 15是早停参数——15个epoch内验证集mAP没有提升就自动停止。不要设太大防止过拟合。imgsz用640。停车场场景车辆较大不需要1280分辨率去捕捉小目标640省显存且够用。lr0的默认值就是0.01但我习惯降到0.001尤其是自定义小数据集上过大的学习率容易让loss曲线在前10个epoch震荡。训练过程中要盯两个东西一个是results.csv里的loss曲线另一个是验证集上的confusion_matrix。如果val loss出现拐点往上走说明开始过拟合早停会自动触发。如果训练结束后mAP很低先检查数据集别急着调参——多数时候是标注框有问题比如框没贴紧车身、类别标错这种低级错误。3.4 损失函数曲线图怎么画以及它说明了什么很多同学跑完训练直接拿results.png里的曲线放进论文但自己看不懂。其实YOLOv8训练完成后autosave目录下会生成results.csv你可以自己画更精细的曲线。这里给一个用matplotlib画loss曲线的脚本import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/detect/train/results.csv) # 列名中train/box_loss是边界框回归损失val/box_loss是验证集损失 plt.figure(figsize(10, 5)) plt.plot(df[epoch], df[train/box_loss], labeltrain box_loss) plt.plot(df[epoch], df[val/box_loss], labelval box_loss) plt.xlabel(epoch) plt.ylabel(loss) plt.legend() plt.grid(True) plt.savefig(box_loss_curve.png, dpi200)判断标准train/box_loss和val/box_loss都在下降且差距不大说明训练健康。如果train loss降但val loss不降是过拟合如果两个都不降先查学习率再查数据标注质量。这两个损失曲线是答辩时老师必问的点你要能指着曲线说清楚每一段的变化原因。4. 违规占道判定的核心逻辑用检测结果做业务规则4.1 从检测框到“是否违规”的几何判定训练好的模型只告诉你“这里有辆车、框在哪里”不会告诉你“这辆车违不违规”。判定逻辑要自己写。停车场最常见的违规是压线停车——车框和车位线或禁停区有交集。常见做法是预先在代码里定义禁停区多边形然后计算检测框和禁停区的交并比IOU。如果IOU超过一个阈值我一般设0.3判定为违规。这个阈值是有讲究的设太高车辆只压一点线会被漏掉设太低正常停在旁边的车会因为边缘触碰被误判。0.3这个值是针对“车辆中心或三分之一车身进入禁停区”经验性调出来的如果实际场景误报多可以往上调到0.4。4.2 一个可直接改的违规判定模块下面这段代码是我经常用在停车场项目里的判定模块可以直接嵌到推理脚本里import cv2 import numpy as np def polygon_contains_box(polygon, box): 判断检测框和禁停区多边形是否重叠 polygon: [(x1,y1), (x2,y2), ...] 禁停区顶点 box: [x1, y1, x2, y2] 检测框 # 检测框四个角 corners [ (box[0], box[1]), (box[2], box[1]), (box[2], box[3]), (box[0], box[3]) ] poly np.array(polygon, dtypenp.float32) # 统计落在多边形内的角点数 inside_count 0 for pt in corners: res cv2.pointPolygonTest(poly, pt, False) if res 0: inside_count 1 # 有两个以上角落在禁停区里判定为占道 return inside_count 2 def judge_violation(detections, forbidden_zones): detections: [[x1, y1, x2, y2, conf, cls], ...] forbidden_zones: [polygon1, polygon2, ...] return: 违规检测框列表 violations [] for det in detections: x1, y1, x2, y2 det[:4] for zone in forbidden_zones: if polygon_contains_box(zone, [x1, y1, x2, y2]): violations.append(det) break return violations这里的判断逻辑是“检测框两个以上角点落在禁停区多边形内”比起IOU计算更接近人对“压线”的直觉判断。注意pointPolygonTest传入的坐标是图像像素坐标所以检测框要乘回原图尺寸——YOLOv8默认输出的是640x640坐标系下的结果你需要用results[0].plot()拿到的还是带框的图但如果要自己画多边形必须做坐标缩放。4.3 为什么直接用模型输出“违规”类别是条弯路我之前提过数据集里标“违规”类别的做法但最后不建议走那条路。原因在于YOLOv8的检测框是学习“外观特征”的“车辆压线”是一个位置关系不是外观特征。模型能学到的是“这辆车旁边有黄线”这种伪特征而不是真正理解“压到了线”。换一个停车场、换一种地面颜色模型就失灵。用“检测车几何规则”的方案模型只负责它擅长的事找车违规判定交给确定性的几何计算。这样模型和规则可以分别迭代——模型精度不够就补数据重训规则误报多就调多边形的精确程度。解耦之后系统的可维护性和答辩时的可讲性都强很多。这个思路本身就是你在答辩时展示与现实接轨的加分点。5. 可视化界面的实现逻辑PyQt5做实时检测面板的思路5.1 界面该有哪些功能毕设系统的可视化界面不需要做得像商业软件那样花哨但三个核心功能必须有实时画面显示视频文件或摄像头、检测结果叠加框和标签、违规事件记录时间截图。再加一个阈值滑块置信度阈值就足够撑起“功能完善”的门面了。很多项目的界面问题不是功能少而是按钮堆了一堆没有一个能真正响应。从评审角度看功能闭环比功能数量重要得多。我用PyQt5比较多原因很简单OpenCV的图像格式可以直接转成QImage显示不需要额外学图形框架。YOLOv8的推理封装成一个类界面调用这个类的方法两边隔离——界面只负责显示和交互推理类只管返回结果。5.2 界面调用YOLOv8推理的核心代码下面这段是界面和YOLOv8推理之间的关键桥接代码它解决的是“视频每一帧怎么送进模型、结果怎么画回画面”import cv2 from PyQt5.QtGui import QImage, QPixmap from ultralytics import YOLO class Detector: def __init__(self, weights_path, conf_thres0.4): self.model YOLO(weights_path) self.conf_thres conf_thres def inference(self, frame): 输入BGR帧返回标注后的画布和检测框列表 # 保原始帧尺寸YOLOv8内部自己会做letterbox results self.model(frame, confself.conf_thres, verboseFalse) boxes results[0].boxes.xyxy.cpu().numpy() confs results[0].boxes.conf.cpu().numpy() # 绘制检测框 for box, conf in zip(boxes, confs): x1, y1, x2, y2 box.astype(int) cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(frame, fcar {conf:.2f}, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) return frame, boxes def cv2_to_qimage(frame): OpenCV的BGR帧转成Qt能显示的QImage rgb cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) h, w, ch rgb.shape bytes_per_line ch * w return QImage(rgb.data, w, h, bytes_per_line, QImage.Format_RGB888) # 使用示例在Qt的update槽里调用 # detector Detector(best.pt) # ret, frame cap.read() # frame_with_boxes, dets detector.inference(frame) # qimg cv2_to_qimage(frame_with_boxes) # label.setPixmap(QPixmap.fromImage(qimg))这段逻辑里有几个容易出问题的地方。一是results[0].boxes.xyxy是归一化前的像素坐标它和原图分辨率一致不需要缩放直接用就行——因为推理时传进去的就是原图YOLOv8返回的坐标也是该分辨率下的。二是cv2_to_qimage里用的Format_RGB888如果转出来画面色彩发蓝或发红说明BGR和RGB顺序搞反了检查一下这行。5.3 界面产品的“操作简单”体现在哪“操作简单”不是说按钮少而是让使用者不用看说明也能上手。我的一般做法主界面打开后自动加载模型和默认视频源点“开始检测”就进入实时推理右侧用表格实时刷新违规记录双击记录能跳转到对应帧的截图阈值滑块在运行时拖动立刻生效不用重启程序。这三件事做到位基本就是一个能上台演示的系统了。有一个细节值得强调模型加载放在程序启动时做一次不要放在视频播放的回调里。如果你的代码把model(frame)写在每一帧的循环里结果还慢得离谱多半是误把模型加载也写进了循环体——每帧重新读一次权重文件能不卡吗。YOLOv8的模型加载耗时约1秒初始化一次就够用了。6. 部署与打包阶段模型还是带不动五个必查的坑6.1 电脑没有NVIDIA显卡报错CUDA不可用怎么办现象训练或推理时报错AssertionError: CUDA unavailable。原因PyTorch默认安装的是CUDA版本没有NVIDIA显卡时就会触发这个错误。另一个可能是装了GPU版torch但驱动太老、显存不足以分配batch。解决先看有没有独立显卡。有的话用nvidia-smi确认驱动版本是能支持的CUDA版本再装对应的PyTorch。没有显卡的话直接卸载torch重装CPU版本pip uninstall torch torchvision然后pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu。重装完在Python里执行import torch; print(torch.cuda.is_available())输出False是正常的CPU模式也能跑的。YOLOv8在CPU上的推理速度大约每帧0.4秒演示时用视频文件而不是实时摄像头体验不会太差。6.2 训练时显存OOMbatch size和图片尺寸的取舍现象训练开始几秒后报RuntimeError: CUDA out of memory。原因batch size设太大或者显卡显存本身只有4G到6G装不下整个batch的数据。解决优先把batch调小比如从16降到8甚至降到4。如果batch已经调到4还是OOM把--imgsz从640降到480。这两步是正交的可以先固定batch调imgsz。我很少为了降低显存去改模型结构——YOLOv8n已经是轻量级了显存不足几乎都是batch和imgsz的锅。6.3 训练时loss为nan学习率过大或数据里有脏值现象训练日志里box_loss显示nanloss曲线断崖式跳到负值。原因学习率过大梯度更新越过最优解直接发散也可能是标注框坐标数据里有脏值——比如标注文件里出现了0宽度的框、坐标超出图片边界。解决第一件事把--lr0从0.01降到0.001重启训练。如果loss还是nan去检查标注txt——写一个检查脚本解析所有txt文件过滤出w或h小于等于0的行。标错的数据清理掉问题自然解决。这个脚本我每次训练前都会跑一遍当作数据清洗的固定步骤。6.4 换了电脑运行报错权重文件路径和Python环境迁移现象项目在自己电脑跑得好好的拷到另一台电脑上运行报ModuleNotFoundError: No module named ultralytics。原因YOLOv8的环境没有完整带过去另一台电脑缺少依赖包。解决不要手动复制site-packages用requirements.txt的方式装环境。在项目根目录执行pip freeze requirements.txt到了新机器上先建虚拟环境再pip install -r requirements.txt。如果对方电脑没有GPU需要在安装时把requirements里的torch替换成CPU版再装。这个操作不复杂但能省掉一晚上排障时间。6.5 中文路径导致的读取失败现象数据集或模型权重路径里带中文运行时抓狂地报错FileNotFoundError或者OpenCV读取不到图片。原因OpenCV的imread和PyTorch的某些文件读取函数对中文路径支持不好路径解析在上面就断了。解决根治办法是项目路径下不要出现任何中文——文件夹名用英文数据集也放英文路径。如果实在避免不了中文路径用cv2.imdecode(np.fromfile(img_path, dtypenp.uint8), cv2.IMREAD_COLOR)替代cv2.imread来读图片这个接口能正确处理中文路径。但YOLOv8训练时数据集加载是内部处理的所以最保险的还是在数据集和权重文件上彻底避开中文路径。7. 从能跑到能答辩验证系统的三个隐藏指标跑通demo只是起点答辩时老师问得最深的往往是“你怎么证明它有效”。除了mAP我建议你再准备三个数据它们才是区别“调包侠”和“真做过”的分水岭。第一个是误报率。从测试视频里统计1000帧画面人工数出模型误报了多少次违规。误报的常见来源是树影、车辆倒影、行人和禁停区边缘的抖动。把数据统计出来能说明你的违规阈值是否合理。第二个是单帧推理耗时。用time模块包住model(frame)调一次的时间在CPU和GPU上分别跑三组取平均值——这个数据回答“能否实时”的问题。第三个是夜间或雨天场景的单独表现。停车场监控最怕晚上灯光下的车辆检测和白天差异很大。如果测试集里有夜间帧单独统计这一组的precision和recall。如果你想在这个方向上继续往下做有两个小的进阶方向比较可行一个是把违规车辆的车牌用OCR接进来在界面里显示“车牌号违规时间截图”的完整记录这能让系统的完整度上一个档次另一个是把训练好的.pt模型用onnx导出加速推理速度。导出命令是from ultralytics import YOLO model YOLO(best.pt) model.export(formatonnx, imgsz640)导出后替换推理方式注意ONNX模型输入是RGB格式而不是BGR颜色通道顺序弄反会导致检测准确率骤降这是导出后最常见的翻车点。加速收益在CPU上通常是1.5到2倍——从0.4秒一帧提到0.2秒左右对实时演示意义很大。做这类毕设项目我的习惯是每改完一个环节就完整跑一遍全流程不要攒到最后一起验收。否则data.yaml改了一次、标注脚本改了一次、界面又改了一次最后合在一起跑不通根本不知道问题出在哪一环。这个习惯帮我省了很多通宵排障的时间希望也能帮到你。本文还有配套的精品资源点击获取