简介:面向计算机相关专业学生与开发者,这是一套基于YOLOv8的工地深基坑变形监测完整项目。内含可直接运行的Python源码、可视化界面、标注数据集与部署教程,覆盖模型训练、视频检测与界面展示等环节,可输出混淆矩阵、F1曲线、PR曲线、验证集预测结果及标签分布图,适合用于毕设、课程设计或初期项目演示。资源包共8个文件,压缩包15.91MB,其中3个py脚本分别对应可视化界面、模型训练与视频推理,3个pt权重文件包含yolov8n与yolo11n等模型,2个txt文件为说明文档与部署备忘,整体结构清晰,便于快速上手。已有66人学习下载,代码经测试运行成功,下载后按README说明即可复现,适合希望直接借鉴完整流程的计算机视觉学习者。
1. 基坑监测为什么要用YOLOv8:给“面监测”补上一块拼图
我见过不少基坑项目,测斜数据曲线平稳,但腰梁上的裂缝已经明显张开了一条口子——因为测点不在裂缝边上。深基坑变形监测如果只看测斜仪、沉降标和水位计,你监测到的只是整面基坑护壁上的几个点,面上的变化全凭人工巡检。基于YOLOv8的工地深基坑变形监测,思路就是把摄像头对准坑壁、支撑梁和坑边堆载区,用目标检测持续识别裂缝、渗漏水、混凝土剥落、违规堆载这四类表观异常。它不是去测毫米级位移,那个交给传感器;它管的是传感器测不到、巡检又容易漏的视觉异常。对毕设或课程设计来说,这个方向链路完整:数据集可以自己拍,训练和可视化界面有成熟套路,部署教程也透明,答辩时能讲清楚“解决什么问题、怎么解决、效果如何验证”。
2. 深基坑变形监测的数据集:四类目标、标注规范与样本平衡
2.1 视觉能测什么:裂缝、渗漏水、剥落与堆载
先定边界:YOLOv8是目标检测模型,不是变形测量仪。它能做的是“表观异常检测”,不是给你一个毫米级的沉降曲线。根据基坑现场能稳定拍到、又能用矩形框表达的目标,我一般固定成四类,类别名直接用英文,后面训练时才不会遇到中文标签乱码。
| 类别名 | 现场现象 | 典型位置 | 标注要点 |
|---|---|---|---|
| crack | 混凝土表面线状裂缝 | 支护桩、腰梁、截水沟 | 框整段裂缝,细裂缝也要框,框内可以有空隙 |
| leakage | 渗漏水迹、水渍 | 桩间土、连续墙接缝 | 框水痕整体,不要只框滴水点 |
| spalling | 混凝土剥落掉块 | 支撑梁、冠梁边角 | 剥落区域外扩一点,不要只框深坑 |
| stack | 基坑边缘堆土堆料 | 坑边安全距离以内 | 框堆体整体,不要拆成小框 |
这四类不是拍脑袋定的。测斜、水位计管“里”,视觉管“表”;stack则是人为风险,摄像头最容易抓到证据。从检测难度看,stack最好做,leakage最难做,因为阴影和水渍的颜色分布太接近,YOLOv8很容易把阴影误报成渗漏水。对毕设而言,这个难度梯度反而是好事,写结论时能拿出“stack类mAP高、leakage类需要更多数据”这样具体的分析,比笼统说“模型准确率95%”有价值得多。
2.2 用Labelme做YOLO格式数据集:转换脚本与标注规范
现场照片要用Labelme画框,画完保存的是JSON文件。YOLOv8训练要的是TXT标注,所以中间需要一步格式转换。我一般直接写脚本批量处理,不用Labelme自带的导出功能,因为批处理时能看到每张图的坐标范围是否合理。
# labelme转yolo:json -> txt import json import os from glob import glob class_names = ['crack', 'leakage', 'spalling', 'stack'] # 顺序决定类别id def convert(json_path, output_dir): with open(json_path, 'r', encoding='utf-8') as f: data = json.load(f) width = data['imageWidth'] height = data['imageHeight'] base = os.path.splitext(os.path.basename(json_path))[0] with open(os.path.join(output_dir, base + '.txt'), 'w') as out: for shape in data['shapes']: label = shape['label'] if label not in class_names: continue points = shape['points'] # 矩形两个点或自由多边形多个点 x_min = min(p[0] for p in points) y_min = min(p[1] for p in points) x_max = max(p[0] for p in points) y_max = max(p[1] for p in points) # yolo格式:类别id 中心x 中心y 宽 高,全部归一化 x_center = (x_min + x_max) / 2.0 / width y_center = (y_min + y_max) / 2.0 / height w = (x_max - x_min) / width h = (y_max - y_min) / height out.write(f"{class_names.index(label)} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}\n") if __name__ == '__main__': os.makedirs('labels/train', exist_ok=True) for json_path in glob('labelme_json/train/*.json'): convert(json_path, 'labels/train')这个脚本的核心是归一化。YOLOv8的坐标都是0到1之间的比例值,不是像素值,直接拿像素坐标训练会出大问题。另一个细节是shape里的points:如果标注时画的是矩形,只有两个点;如果用了多边形,可能有七八个点,所以代码里取所有点的min/max,这样两种标注方式都能兼容。
配套的data.yaml长这样,注意train和val的路径指向图片目录,而TXT标注要放在与图片同名的目录下。ultralytics会自动去找“图片同路径下同名的txt文件”,所以目录结构要提前摆好。
# data.yaml 示例 train: images/train val: images/val nc: 4 names: ['crack', 'leakage', 'spalling', 'stack']标注规范里最容易翻车的一点:同类目标重叠时一定分开框,不要一个大框套住两个裂缝。检测模型学的是“每个框里有一个完整目标”,你把两个裂缝框成一个框,模型预测时就会拼命找“一整根长裂缝”,反而漏掉单根短裂缝。另外裂缝即使很细,也要框住整段,不要为了省事只框最粗的一段——训练数据里框的形态方差越大,模型泛化越稳。
2.3 数据增强与样本失衡:Mosaic不是保险箱
做完标注要分训练集和验证集,常见做法是8:1:1,但这里有个容易忽略的坑:数据泄漏。同一天同一机位连拍的照片,一张进train、一张进val,模型在val上会“见过”几乎一样的画面,验证指标虚高。正确做法是按采集批次划分,比如周一拍的都进train,周二拍的都进val,这样val里是模型没见过的现场条件。做监测项目时,这个数据泄漏比任何参数都更容易让指标失真。
数据增强方面,YOLOv8默认开Mosaic。但裂缝是细条目标,Mosaic拼接时很容易把裂缝切成两段,标签落在拼缝上,等于给模型喂错误样本。我的习惯是第一阶段开Mosaic跑,第二阶段载入上一轮的best.pt,把Mosaic降到0.2再微调几个epoch,专门纠正拼接造成的定位抖动。如果嫌麻烦,全程0.4到0.5保平安,不要一直开1.0。
样本失衡是监测场景的家常便饭:stack好拍,leakage难拍,一个数据集里可能stack有300个框,leakage只有40个框。常见做法是先写个统计脚本数各类别框数,然后对少样本类别做重采样——把漏水图片复制几份,每份做不同的亮度、对比度扰动。这里注意:单纯复制粘贴会导致模型过拟合那几张图,复制时必须配合光度扰动。另一种做法是提高分类损失权重,在train参数里设置cls=1.5甚至2.0,让分类分支更重视少数类,但效果不如数据重采样来得直接。
3. YOLOv8训练:环境配置、参数选择与损失曲线
3.1 Ubuntu 20.04搭建YOLOv8环境(CPU版本)
很多课程设计和毕设的机器没有独立显卡,CPU环境也能把YOLOv8n训练跑起来,只是慢,所以要先做冒烟测试再全量训练。Ubuntu 20.04上最常见的安装路子是用pip装ultralytics,它会把依赖的PyTorch CPU版一起拉下来。
# Ubuntu 20.04 CPU环境安装 sudo apt update sudo apt install -y python3-pip pip install ultralytics onnxruntime # 验证环境是否正常 yolo predict model=yolov8n.pt source=https://ultralytics.com/images/bus.jpg这里要说明:yolo命令是ultralytics包提供的命令行入口,predict时会自动下载yolov8n.pt官方预训练权重,第一次运行需要联网。CPU版本安装后默认走CPUExecutionProvider,不需要装CUDA。如果你机器上之前装过GPU版PyTorch,又装了一个CPU版,版本冲突会让人头疼,我一般建议用虚拟环境隔离。
CPU上训练yolov8n、640分辨率、几十张图,单epoch可能要几分钟到十几分钟,这取决于CPU核心数和内存带宽。所以训练前先跑冒烟测试:
# 冒烟测试:只训练1个epoch,验证数据流水线没有问题 yolo train data=data.yaml model=yolov8n.pt epochs=1 imgsz=640 device=cpu batch=2冒烟测试能暴露大部分路径问题:data.yaml路径写错、标注txt与图片对不上、类别数不匹配等。这些问题在1个epoch里就会以报错或训练中断的形式出现,不要等全量训练跑了一小时才翻车。
3.2 影响精度的五个参数:imgsz、batch、epochs、mosaic、cls
训练自己的数据集,YOLOv8并不是装上就能出好结果。下面五个参数我每次都会重新调,按影响程度排序。
| 参数 | 我的常用值 | 作用与原因 |
|---|---|---|
| imgsz | 640起步,有条件上1280 | 裂缝是小目标,分辨率不够直接糊掉;CPU跑不动1280就减batch |
| batch | CPU用2到4,GPU看显存 | 基坑图片分辨率高,显存不够时降低batch,不要降低imgsz |
| epochs + patience | 150 + patience=20 | 监测数据量小,150轮足够收敛;patience防过拟合 |
| mosaic | 第一段1.0,第二段0.2 | 裂缝细条目标怕拼接切断,后期关掉让模型稳定收边 |
| cls | 1.2到1.5 | 分类损失权重,缓解leakage等少数类漏检 |
代码里我倾向于直接写在Python脚本里,而不是用yolo命令行,因为参数多、方便统一管理。
# train_pit.py from ultralytics import YOLO # 第一段训练:开mosaic,用预训练权重冷启动 model = YOLO('yolov8n.pt') model.train( data='data.yaml', epochs=80, imgsz=640, batch=8, mosaic=1.0, cls=1.2, device='cpu', # 无GPU就写cpu,有GPU可写0 patience=20, name='pit_stage1' ) # 第二段训练:关mosaic,用stage1最佳权重微调收边 model = YOLO('runs/detect/pit_stage1/weights/best.pt') model.train( data='data.yaml', epochs=40, imgsz=640, batch=8, mosaic=0.2, cls=1.2, device='cpu', patience=15, name='pit_stage2' )这段代码的意图是分阶段训练。第一段让模型快速学到四类目标的粗轮廓,Mosaic的多样性能帮助泛化;第二段把Mosaic关小,让预测框能稳定贴合裂缝这种细长目标。batch参数在CPU上不要贪大,CPU内存带宽会拖慢速度,2和8之间差别不大,但内存不够时会直接OOM。
模型选型上,yolov8n是默认选择,CPU推理快,精度在交叉场景够用;如果验证集mAP差5个点以上,换yolov8s试一下,但CPU推理帧率会明显下降。yolov8m及以上在CPU上做实时监测就比较吃力了,除非你只是做离线分析。GTX 1660 Ti这类6G显存的卡跑yolov8n很轻松,batch可以开到16甚至32。
3.3 损失曲线怎么读:从results.csv里看训练是否翻车
训练结束后,ultralytics会在runs/detect/xxx/目录下生成results.csv、results.png、confusion_matrix.png等。不要只截一张results.png放进论文,要学会自己看曲线判断模型状态。YOLOv8有三个损失:box_loss、cls_loss、dfl_loss,分别管定位、分类和边框回归。我习惯把train和val的cls_loss单独拉出来画一张图,判断标准很简单:train_loss一直降、val_loss降不下去或者反弹,就是过拟合;两条线都锯齿状震荡,说明batch太小或Mosaic在后期搞乱标签。
# 画损失曲线 import pandas as pd import matplotlib.pyplot as plt df = pd.read_csv('runs/detect/pit_stage2/results.csv') plt.figure(figsize=(10, 4)) plt.plot(df['epoch'], df['train/cls_loss'], label='train_cls') plt.plot(df['epoch'], df['val/cls_loss'], label='val_cls') plt.xlabel('epoch') plt.ylabel('cls_loss') plt.title('Train/Val Classification Loss') plt.legend() plt.grid(True) plt.savefig('loss_curve.png', dpi=200)读曲线时注意,val_loss不是越低越好,要看它和train_loss之间的距离。如果val_cls_loss在第60个epoch开始往上翘,而train_cls_loss还在往下走,说明模型开始死记训练图。这时候不要继续加epoch,而是去看patience有没有触发,没触发就手动提前结束。
更关键的是看confusion_matrix.png。基坑场景里leakage和spalling容易互相混淆,混淆矩阵能告诉你错误具体发生在哪两个类之间。还有一个容易被忽略的指标:PR曲线在低置信度时的表现。如果precision在0.8就断崖下跌,说明模型误报多;如果recall到0.7就上不去,说明漏检多。工程上我只看IoU=0.5的mAP,不用去追mAP95——基坑目标的框本身就不需要精确到像素级,框住裂缝位置才是核心。
4. 可视化界面:PyQt5 + OnnxRuntime搭建监测面板
4.1 界面布局与模块拆分
标题里说“可视化界面”,拿到源码包后先别急着跑,先看它的模块划分。我一般会把界面项目拆成三个部分:数据读取(图片、视频、RTSP流)、模型推理(ONNX或PyTorch)、业务逻辑(报警记录、结果显示)。PyQt5做桌面界面最稳,推理部分用OnnxRuntime而不是直接跑PyTorch,原因有二:一是OnnxRuntime部署时不用装整个PyTorch,现场机器干净;二是CPU上OnnxRuntime比PyTorch的推理快一截。
界面布局建议如下表,这个布局能兼顾展示和操作:
| 区域 | 组件 | 功能 |
|---|---|---|
| 左侧主画布 | QLabel + 绘图 | 显示检测结果帧 |
| 右侧结果列表 | QTableWidget | 当前帧所有目标:类别、置信度、坐标 |
| 顶部配置栏 | QComboBox / QDoubleSpinBox | 选择输入源、调置信度阈值 |
| 底部状态栏 | QLabel | 帧率、累计报警数、当前时间 |
一个原则:推理绝不能放在UI主线程。PyQt的界面刷新是事件循环驱动的,你在主线程里跑一个while循环读视频,窗口会直接假死,点什么都无响应。正确做法是开一个QThread专门做推理,通过信号把结果帧传回UI线程刷新。
4.2 模型导出为ONNX:让界面不依赖PyTorch
训练完的best.pt是PyTorch权重,界面里直接用要依赖torch库,部署机器上还得装对应版本,麻烦。常见的做法是导出ONNX格式,然后界面里只依赖onnxruntime。
# 导出ONNX,opset不要乱改,默认即可 yolo export model=runs/detect/pit_stage2/weights/best.pt format=onnx opset=12导出后在同目录会生成best.onnx。下面是一个OnnxRuntime推理类的最小实现,包含letterbox预处理和后处理的关键步骤。预处理必须和训练时一致,否则检测框会整体偏移。
# detector.py import cv2 import numpy as np import onnxruntime as ort class Detector: def __init__(self, onnx_path, conf_thres=0.35): self.session = ort.InferenceSession(onnx_path, providers=['CPUExecutionProvider']) self.input_name = self.session.get_inputs()[0].name self.conf_thres = conf_thres def letterbox(self, img, size=640): # 保持纵横比,填充灰色边(114),和训练时一致 h, w = img.shape[:2] r = min(size / h, size / w) new_w, new_h = int(w * r), int(h * r) resized = cv2.resize(img, (new_w, new_h)) canvas = np.full((size, size, 3), 114, dtype=np.uint8) dw, dh = (size - new_w) // 2, (size - new_h) // 2 canvas[dh:dh + new_h, dw:dw + new_w] = resized return canvas, r, dw, dh def detect(self, frame): canvas, r, dw, dh = self.letterbox(frame) blob = canvas[:, :, ::-1].transpose(2, 0, 1).astype(np.float32) / 255.0 blob = np.expand_dims(blob, 0) outputs = self.session.run(None, {self.input_name: blob})[0] # [1, 84, 8400] preds = outputs[0].T # [8400, 84] boxes = [] for p in preds: scores = p[4:] cls_id = int(scores.argmax()) conf = float(scores[cls_id]) if conf < self.conf_thres: continue # 坐标是letterbox后的坐标,要映射回原图 x1 = (p[0] - dw) / r y1 = (p[1] - dh) / r x2 = (p[2] - dw) / r y2 = (p[3] - dh) / r boxes.append((x1, y1, x2, y2, conf, cls_id)) return boxesletterbox是YOLOv8系列最容易踩坑的地方。训练时输入是640x640的方形图,推理时如果你的图片是1920x1080,直接resize会压扁目标;不resize又进不了模型。letterbox的做法是等比缩放,短边不足的地方用灰色114填充。推理得到的框坐标是在缩放后坐标系里的,所以要逆运算回原图坐标,否则画框位置会偏。
后处理里有个细节:YOLOv8的输出形状是[1, 84, 8400],84=4个坐标+80个COCO类别。如果你训练的是4类,这个维度是[1, 8, 数量],所以不要写死。我上面的代码用scores.argmax()拿到类别id,这么做对自定义类别数也通用。
4.3 视频流接入与报警记录
界面部署在工地,输入源多半是网络摄像头,RTSP流是标配。cv2.VideoCapture可以直接支持rtsp地址,但要注意响应延迟和断线重连。我的习惯是把采集和推理放到同一个线程,检测完再发信号给UI。
# cap_thread.py from PyQt5.QtCore import QThread, pyqtSignal import cv2 import numpy as np class CaptureThread(QThread): frame_ready = pyqtSignal(np.ndarray) alarm_triggered = pyqtSignal(dict) def __init__(self, detector, source, parent=None): super().__init__(parent) self.detector = detector self.source = source self.running = True def run(self): cap = cv2.VideoCapture(self.source) # RTSP地址形如 rtsp://user:pass@ip:554/stream1 # 设置缓冲小一点,降低延迟 cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) while self.running: ok, frame = cap.read() if not ok: continue boxes = self.detector.detect(frame) for b in boxes: x1, y1, x2, y2, conf, cls_id = b cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), (0, 0, 255), 2) self.frame_ready.emit(frame) cap.release()报警逻辑要有消抖。单帧检测到leakage不报警,连续N帧都检测到同一个位置才触发,否则树叶影子晃动一下就会产生几十条误报记录。我一般用IoU来判断是不是同一个目标:当前帧某个框与上一帧某个框的IoU大于0.7,就认为还是同一个目标,累计计数达到3帧再写报警记录。
报警记录写什么?常见做法是存一张截图加一段JSON。截图用于事后人工复核,JSON里记录类别、置信度、时间戳、原始坐标。这一套下来,界面才不是“能画框”,而是真的能当监测工具用。
5. 部署和避坑排查:从CPU主机到RK3588边缘盒子
5.1 部署环境对比与选型
部署教程是标题里的重头戏,但先别跳进代码,先想清楚部署到哪。三种常见环境各有边界:
| 部署环境 | 优势 | 劣势 | 适合场景 |
|---|---|---|---|
| CPU主机 | 环境好搭、调试方便、成本低 | 帧率个位数到十几FPS | 课程设计、离线分析、原型验证 |
| NVIDIA GPU | 帧率高、可跑多路视频 | 功耗高、现场取电麻烦 | 监控室集中处理 |
| RK3588等NPU板卡 | 低功耗、体积小、可挂现场 | 转换流程复杂、算子兼容性要试 | 边缘现场实时监测 |
CPU主机做毕设演示完全够用,PPT上放帧率数据就够了。RK3588部署的意义是“能挂到工地现场”,但你要有心理准备,从pt到rknn的转换链路会消耗大量时间,特别是写自定义后处理时,YOLOv8的Dfl结构在转RKNN时偶尔会掉精度。
转换流程一般是先导出ONNX,再用rknn-toolkit2在PC上将ONNX转成RKNN格式,最后把RKNN模型拷贝到板端推理。
# pt转onnx(前面已做过) yolo export model=best.pt format=onnx opset=12 # onnx转rknn需要单独的工具链,不是pip直接装 # 转换时注意量化数据集要用训练集里的真实样本图片,不要用网上随便拉的照片CPU环境下,onnxruntime的部署相对丝滑。唯一要注意的是ONNX版本和opset的对应关系,opset=12是兼容性最好的选择。rk3588上如果遇到某个算子不支持,常见的兜底方案是把模型导出成opset=11,或者把Dfl结构单独拆出来放到板端用C++实现。
5.2 部署必看的五个坑:现象、原因、解决
先亮结论:坑都是踩出来的,我已经对着这几个问题翻过几次车。
坑一:中文标签全部变成乱码框
现象:用Labelme标注时用了“裂缝”“漏水”等中文名,训练时显示正常,推理时结果类名在界面里显示成乱码,或者直接训练中断报错“class names contain non-ASCII characters”。
原因:ultralytics底层对类别名的编码处理不一致,中文在多进程dataloader下容易踩到编码坑。
解决:别和编码过不去,labelme标注和data.yaml里的names全部用英文或拼音。界面显示时再单独维护一份中英文映射表,比如crack显示为“裂缝”。这是最省事的做法,不要指望框架修好编码。
坑二:检测框整体偏移,目标在框外
现象:画出来的框比真实目标偏左上或者偏右下,置信度还不低。
原因:推理预处理用了普通resize,没做letterbox;或者做了letterbox但坐标逆运算时忘了减掉填充边dw/dh。YOLOv8训练时强制letterbox,推理不一致,框必然飘。
解决:复现训练时的预处理,检测线程里的letterbox函数参数必须和训练时一致。逆运算公式就是x=(pred_x - dw)/ratio、y=(pred_y - dh)/ratio。
坑三:CPU推理只有2FPS,界面一卡一卡
现象:读RTSP流,帧率只有2帧左右,界面明显掉帧。
原因:模型用的是yolov8m或yolov8x;或者输入分辨率设成1280且batch=8;或者使用了GPU版Torch但没GPU,导致CPU推理。
解决:推理部署统一用yolov8n+onnxruntime,分辨率压到640,CPU上能跑到个位数到十几FPS。如果还想快,把输入分辨率降到480试一下,裂缝这种目标480仍然可检测,但对非常细的裂缝会漏。
坑四:渗漏水识别被阴影干扰,误报刷屏
现象:晴天下午,支护桩的阴影一移动就会触发leakage报警,一天报了两百多次。
原因:阴影和水渍在颜色空间上太接近,模型学到的是“暗色斑块”,不是“水迹纹理”。单一摄像头视角下两者本来就难分。
解决:从两个方向下手。训练层面,数据增强里加强亮度扰动,让阴影的形态更多样;推理层面,引入帧间差分——水迹是静态的,阴影是移动的,同一位置连续多帧框置信度均高才报警,阴影晃过一两帧就消失。这个消抖逻辑比换模型更有效。
坑五:Mosaic增强导致裂缝一半有标签一半没标签
现象:训练loss曲线正常,但验证集mAP持续偏低,可视化预测时发现模型漏检拼接缝附近的裂缝。
原因:Mosaic拼接时把裂缝裁到两张图交界的灰边上,标签没跟着切过去,模型学到“半个裂缝”的负样本。
解决:第二段微调时mosaic降到0.2以下;或者自定义Mosaic时把目标完全落到某一象限再做变换,但工程上直接调参更现实。
5.3 排查问题的顺序
模型部署出问题,很多人上来就怀疑代码,其实先排查数据更高效。我的排查顺序:先用单张图片跑通整个推理链路,确认预处理后处理没毛病;再用一段固定视频反复测试,对比PyTorch权重和ONNX权重的输出差异;最后才怀疑现场环境。
快速定位手段是让ultralytics把每张预测图保存下来,带上类别和置信度信息:
# 在测试集上预测并保存结果 yolo predict model=best.pt source=test_images/ save_txt=True save_conf=Truesave_txt=True会输出每个框的类别和坐标,和界面推理的结果对比,就能知道是不是界面代码的问题。如果两者一致但界面画框位置错,回坑二查坐标逆运算;如果界面结果稳定优于现场视频,回坑四查报警消抖。
6. 用连续监测数据验证:别让模型只活在训练集里
6.1 统计误报率与漏报率
很多毕设演示用的是挑好的几张照片,测出来准确率95%。但这没有说服力——真正检验监测模型的是连续视频流里的误报率和漏报率。我建议你把验证集按时间顺序重排,模拟真实监测场景,统计三个指标:误报次数(不是目标被框出来)、漏报次数(真目标没框出来)、平均响应帧数(目标出现第几帧开始被连续检测到)。
这三个指标直接对应工程价值:误报太多没人信系统,漏报太多系统没意义。我做基坑监测项目时有一周的工作就是坐在屏幕前把误报一条条标出来,看是阴影、雨滴还是灯光反光。这个过程很枯燥,但比调参有用。
6.2 和传统传感器数据对齐
最后给课程设计或毕设加分的一步:把视觉报警的时间戳和测斜仪、水位计的数据对齐。基坑变形是缓慢过程,视觉异常往往比位移曲线拐点早几天出现。哪怕只是把你标注的裂缝发现时间点和测斜累计位移画在一张图上,也能讲出“视觉监测具备早期预警潜力”这种有分量的结论。
我现在做这个方向有个习惯:拿到新现场,先固定机位拍一周视频,把视频里的目标分布、光线变化、天气影响摸清楚,再回头调模型。数据质量差的时候,调任何参数都是玄学;数据质量扎实,模型参数反而不需要反复折腾。可视化界面是给答辩和业主看的,真正检验模型的是连续七天不重样的误报记录。希望帮到你。
本文还有配套的精品资源,点击获取