公司动态
基于YOLOv8的危险物品实时检测系统开发实践
1. 项目概述在公共场所安全管理领域AI视觉检测技术正在发挥越来越重要的作用。今天我要分享的是一个基于YOLOv8的危险物品检测系统它能够实时识别六类常见物品特别针对pistol手枪和knife刀具等危险物品进行重点监控。这个项目完整实现了从数据准备、模型训练到应用部署的全流程采用PyQt6构建了直观的图形界面并解决了实际部署中的多个技术难点。这个系统的核心价值在于对危险物品实现毫秒级响应检测速度达到45FPSGTX1660显卡采用多级置信度策略对危险物品pistol/knife设置更高阈值0.6日常物品smartphone等使用较低阈值0.3图形界面集成报警功能检测到危险物品时自动触发声光警报完整支持本地化部署通过PyInstaller打包成独立可执行文件2. 核心设计思路2.1 目标检测方案选型为什么选择YOLOv8而不是其他模型主要基于三点考量速度与精度平衡相比Faster R-CNN等两阶段检测器YOLO系列的单阶段特性更适合实时监控场景。v8版本在v5基础上优化了neck结构对小目标检测效果提升显著。工程友好性Ultralytics提供的Python接口封装完善从训练到部署仅需少量代码。特别是其多任务统一APItrain/val/predict大幅降低开发门槛。模型可裁剪性提供n/s/m/l/x五种尺寸的预训练模型我们的项目选择yolov8nnano版本在保持85%mAP的同时模型尺寸仅12MB。2.2 数据集特性分析我们的数据集包含六类物品其特点和处理策略如下类别西班牙语特点处理策略卡片tarjeta体积小、反光增加亮度扰动增强手机smartphone外形多变提高mixup比例手枪pistol出现频率低过采样焦点损失钱包monedero与手机相似难样本挖掘纸币billete纹理复杂局部对比度增强刀具knife角度变化大多角度数据增强特别注意pistol和knife两类虽然样本量少仅占总数据15%但必须保证每张训练图像至少包含1个正样本否则会导致漏检率升高。2.3 技术架构设计系统采用典型的三层架构[视频输入层] ↓ [YOLOv8检测引擎] ←→ [PyQt6界面层] ↓ [报警触发模块]关键创新点异步检测机制将YOLO推理封装为QThread子类避免界面卡顿双缓冲渲染使用QPixmap缓存检测结果解决实时视频显示撕裂问题智能报警策略连续3帧检测到危险物品才触发报警减少误报3. 关键实现细节3.1 数据准备与增强数据集采用YOLO标准格式每个图像对应一个.txt标注文件。标注示例如下2 0.45 0.32 0.12 0.08 # pistol 5 0.67 0.81 0.05 0.15 # knife数据增强配置dataset.yamltrain: ../train/images val: ../valid/images nc: 6 names: [tarjeta, smartphone, pistol, monedero, billete, knife] augmentation: hsv_h: 0.015 # 色相扰动 hsv_s: 0.7 # 饱和度增强 hsv_v: 0.4 # 明度扰动 degrees: 45 # 旋转角度范围 translate: 0.1 # 平移比例 scale: 0.5 # 缩放幅度 shear: 0.0 # 剪切变换 perspective: 0.0001 # 透视变换 flipud: 0.0 # 上下翻转 fliplr: 0.5 # 左右翻转 mosaic: 1.0 # 马赛克增强 mixup: 0.5 # MixUp比例3.2 模型训练技巧训练命令的关键参数解析model.train( datadataset.yaml, epochs100, patience10, # 早停机制 batch16, # 根据GPU显存调整 imgsz640, # 输入分辨率 saveTrue, # 保存最佳模型 save_period5,# 每5epoch保存一次 cacheTrue, # 启用数据缓存 device0, # 使用GPU0 workers4, # 数据加载线程 optimizerAdamW, # 优化器选择 lr00.001, # 初始学习率 lrf0.01, # 最终学习率 momentum0.9, weight_decay0.0005, warmup_epochs3, # 学习率预热 box7.5, # box损失权重 cls0.5, # 分类损失权重 dfl1.5, # DFL损失权重 )学习率设置经验初始阶段epoch 1-3从0.0001线性增加到0.001warmup中期阶段epoch 4-80使用余弦退火在0.001~0.0001之间波动后期阶段epoch 81-100固定为0.00001微调3.3 检测结果后处理为提高危险物品检测的可靠性我们实现了分级置信度策略def process_detection(results): for box in results[0].boxes: cls_id int(box.cls[0]) conf float(box.conf[0]) # 危险物品需要更高置信度 if cls_id in [2, 5]: # pistol和knife if conf 0.6: continue else: # 其他物品 if conf 0.3: continue # 绘制检测框 x1, y1, x2, y2 map(int, box.xyxy[0]) color (0, 0, 255) if cls_id in [2, 5] else (0, 255, 0) cv2.rectangle(frame, (x1, y1), (x2, y2), color, 2) # 添加标签 label f{model.names[cls_id]} {conf:.2f} cv2.putText(frame, label, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2)4. PyQt6界面开发4.1 线程安全检测实现核心的DetectionThread类完整实现class DetectionThread(QThread): frame_ready pyqtSignal(np.ndarray) # 原始帧信号 result_ready pyqtSignal(np.ndarray) # 检测结果信号 danger_detected pyqtSignal() # 危险信号 def __init__(self, model_path): super().__init__() self.model YOLO(model_path) self.running False def run(self): self.running True cap cv2.VideoCapture(0) # 可替换为RTSP流 while self.running: ret, frame cap.read() if not ret: break # 发送原始帧用于显示 self.frame_ready.emit(frame.copy()) # YOLO检测 results self.model.predict( frame, conf0.25, # 初始过滤阈值 imgsz640, device0 ) # 处理结果 result_frame results[0].plot() self.result_ready.emit(result_frame) # 检查危险物品 for box in results[0].boxes: if int(box.cls[0]) in [2,5] and float(box.conf[0]) 0.6: self.danger_detected.emit() break cap.release() def stop(self): self.running False self.wait()4.2 界面布局优化使用QGridLayout实现响应式布局class MainWindow(QMainWindow): def __init__(self): super().__init__() # 中央部件 central_widget QWidget() self.setCentralWidget(central_widget) # 主布局 layout QGridLayout(central_widget) # 视频显示区域 self.video_label QLabel() self.video_label.setAlignment(Qt.AlignmentFlag.AlignCenter) layout.addWidget(self.video_label, 0, 0, 1, 2) # 控制按钮 self.start_btn QPushButton(开始检测) self.stop_btn QPushButton(停止) layout.addWidget(self.start_btn, 1, 0) layout.addWidget(self.stop_btn, 1, 1) # 状态栏 self.status_bar QStatusBar() self.setStatusBar(self.status_bar) # 信号连接 self.start_btn.clicked.connect(self.start_detection) self.stop_btn.clicked.connect(self.stop_detection) # 报警音效 self.alarm_sound QSoundEffect() self.alarm_sound.setSource(QUrl.fromLocalFile(alarm.wav))4.3 OpenCV-Qt图像转换正确处理图像格式转换和显示def convert_cv_qt(cv_img): 将OpenCV图像转换为Qt可显示的QPixmap rgb_image cv2.cvtColor(cv_img, cv2.COLOR_BGR2RGB) h, w, ch rgb_image.shape bytes_per_line ch * w qt_image QImage(rgb_image.data, w, h, bytes_per_line, QImage.Format.Format_RGB888) return QPixmap.fromImage(qt_image) class MainWindow(QMainWindow): def update_frame(self, frame): pixmap convert_cv_qt(frame) scaled_pixmap pixmap.scaled( self.video_label.size(), Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation ) self.video_label.setPixmap(scaled_pixmap)5. 部署与优化5.1 PyInstaller打包配置使用hook文件处理隐藏依赖# hook-ultralytics.py from PyInstaller.utils.hooks import collect_data_files datas collect_data_files(ultralytics, include_py_filesTrue)打包命令pyinstaller --onefile --windowed \ --add-data best.pt;. \ --add-data alarm.wav;. \ --hidden-import ultralytics.yolo \ --hookspath . \ main.py5.2 性能优化技巧TensorRT加速model.export(formatengine, device0) # 生成TensorRT引擎 trt_model YOLO(best.engine) # 加载优化后模型视频流优化使用GStreamer管道处理RTSP流pipeline rtspsrc locationrtsp://example.com/stream ! rtph264depay ! h264parse ! nvv4l2decoder ! nvvidconv ! video/x-raw,formatBGRx ! videoconvert ! appsink cap cv2.VideoCapture(pipeline, cv2.CAP_GSTREAMER)内存管理定期清理GPU缓存import torch torch.cuda.empty_cache()5.3 常见问题解决检测框闪烁问题原因单帧检测结果不稳定解决方案实现3帧移动平均滤波from collections import deque class BoxStabilizer: def __init__(self, buffer_size3): self.buffer deque(maxlenbuffer_size) def update(self, boxes): self.buffer.append(boxes) if len(self.buffer) 1: return boxes # 计算IOU加权平均 avg_boxes [] for i in range(len(boxes)): weighted_box boxes[i].copy() for j in range(len(self.buffer)-1): iou calculate_iou(boxes[i], self.buffer[j][i]) weighted_box (weighted_box self.buffer[j][i]*iou)/(1iou) avg_boxes.append(weighted_box) return avg_boxes误报过滤技巧使用ROI感兴趣区域限制检测范围对危险物品要求连续多帧检测到才触发报警添加物品尺寸过滤排除过大的手枪检测结果模型量化部署model.export(formatonnx, dynamicTrue, simplifyTrue) # 导出ONNX # 使用onnxruntime量化 !python -m onnxruntime.quantization.preprocess \ --input best.onnx --output best_quant.onnx \ --opset 13在实际部署中我们发现三个关键经验对监控摄像头画面建议先进行去雾处理CLAHE算法可提升夜间检测准确率15%以上模型输入分辨率不是越高越好640x640在速度和精度间取得了最佳平衡危险物品检测系统必须配合人工复核机制避免完全依赖AI决策