YOLOv8吸烟检测系统:从数据标注到部署的全流程实践
在公共安全监控和智能安防场景中吸烟行为检测一直是个技术难点。传统人工巡查效率低、易遗漏而基于深度学习的自动化识别系统能实现7×24小时不间断监测。本文将手把手带你搭建一套完整的YOLOv8吸烟识别检测系统从环境配置、数据集制作到模型训练和UI界面开发提供全流程可落地的解决方案。无论你是刚接触目标检测的新手还是有一定深度学习基础的开发者都能通过本文掌握YOLOv8在实际项目中的应用技巧。学完后你将能够独立完成从数据准备到系统部署的完整流程并可根据实际需求调整检测类别。1. YOLOv8与吸烟检测背景介绍1.1 YOLOv8技术特点YOLOv8是Ultralytics公司推出的最新一代目标检测算法在YOLOv5的基础上进行了多项优化。相比前代版本YOLOv8在精度和速度上都有显著提升特别适合实时检测场景。其主要改进包括骨干网络优化使用更高效的CSP结构减少计算量的同时保持特征提取能力无锚点设计简化检测头结构降低模型复杂度损失函数改进采用TaskAlignedAssigner正样本分配策略提升训练稳定性多尺度训练支持不同分辨率输入适应各种检测场景1.2 吸烟检测的应用价值吸烟检测系统在多个领域具有重要应用价值公共场所监控医院、学校、商场等禁烟区域的智能监管安全生产化工、加油站等易燃易爆场所的安全预警智慧城市配合城市摄像头网络实现大范围吸烟行为监测办公环境企业园区内的无烟环境维护1.3 技术选型考量选择YOLOv8进行吸烟检测主要基于以下考虑吸烟目标通常较小YOLOv8的小目标检测能力较强推理速度快能满足实时监控需求社区活跃预训练模型丰富便于迁移学习支持多种部署方式包括ONNX、TensorRT等2. 环境准备与依赖配置2.1 硬件要求为保证模型训练和推理效率建议配置如下硬件环境GPUNVIDIA GTX 1060 6GB或更高推荐RTX 3060以上内存16GB以上存储至少50GB可用空间用于存放数据集和模型2.2 软件环境搭建本文使用Python 3.8环境以下是详细的环境配置步骤# 创建虚拟环境 conda create -n yolov8_smoke python3.8 conda activate yolov8_smoke # 安装PyTorch根据CUDA版本选择 pip install torch1.13.1cu116 torchvision0.14.1cu116 torchaudio0.13.1 --extra-index-url https://download.pytorch.org/whl/cu116 # 安装Ultralytics YOLOv8 pip install ultralytics # 安装其他依赖 pip install opencv-python pillow matplotlib seaborn pandas numpy scipy pip install streamlit # UI界面开发2.3 环境验证安装完成后通过以下代码验证环境是否正确配置import torch import ultralytics import cv2 print(fPyTorch版本: {torch.__version__}) print(fCUDA是否可用: {torch.cuda.is_available()}) print(fYOLOv8版本: {ultralytics.__version__}) print(fOpenCV版本: {cv2.__version__}) # 测试GPU if torch.cuda.is_available(): print(fGPU设备: {torch.cuda.get_device_name(0)})3. 数据集准备与标注3.1 数据收集策略吸烟检测数据集可以通过多种方式获取公开数据集如Kaggle、Roboflow等平台的相关数据集网络爬取使用合规方式获取吸烟相关图片实际拍摄在合规前提下采集真实场景数据数据增强通过对现有图片进行变换扩充数据集3.2 数据标注规范使用LabelImg或CVAT等工具进行标注标注时注意以下要点# 标注文件示例YOLO格式 # class x_center y_center width height 0 0.512 0.634 0.125 0.234标注规范要求只标注清晰可见的吸烟行为确保吸烟动作明显手持香烟、吸烟动作标注框要紧贴目标边缘不同角度、光照条件都要覆盖3.3 数据集结构组织正确的数据集结构对训练至关重要smoke_detection/ ├── images/ │ ├── train/ │ │ ├── image1.jpg │ │ └── image2.jpg │ └── val/ │ ├── image101.jpg │ └── image102.jpg └── labels/ ├── train/ │ ├── image1.txt │ └── image2.txt └── val/ ├── image101.txt └── image102.txt3.4 数据预处理代码以下代码实现数据集的自动划分和预处理import os import shutil from sklearn.model_selection import train_test_split import cv2 def prepare_dataset(raw_data_path, output_path): 准备YOLOv8格式的数据集 # 创建目录结构 os.makedirs(os.path.join(output_path, images/train), exist_okTrue) os.makedirs(os.path.join(output_path, images/val), exist_okTrue) os.makedirs(os.path.join(output_path, labels/train), exist_okTrue) os.makedirs(os.path.join(output_path, labels/val), exist_okTrue) # 获取所有图片文件 image_files [f for f in os.listdir(raw_data_path) if f.endswith((.jpg, .png, .jpeg))] # 划分训练集和验证集 train_files, val_files train_test_split(image_files, test_size0.2, random_state42) # 复制文件到对应目录 for file in train_files: # 复制图片 shutil.copy(os.path.join(raw_data_path, file), os.path.join(output_path, images/train, file)) # 复制对应的标注文件 label_file os.path.splitext(file)[0] .txt if os.path.exists(os.path.join(raw_data_path, label_file)): shutil.copy(os.path.join(raw_data_path, label_file), os.path.join(output_path, labels/train, label_file)) # 同样的操作处理验证集... print(f数据集准备完成: 训练集{len(train_files)}张, 验证集{len(val_files)}张) # 使用示例 prepare_dataset(raw_data/, smoke_detection/)4. YOLOv8模型训练4.1 配置文件准备创建数据集配置文件smoke.yaml# smoke.yaml path: /path/to/smoke_detection # 数据集根目录 train: images/train # 训练集路径 val: images/val # 验证集路径 # 类别数量 nc: 1 # 类别名称 names: [smoking] # 下载地址/说明 # 将此文件放在数据集根目录下4.2 模型训练代码使用YOLOv8进行模型训练的完整代码from ultralytics import YOLO import os def train_smoke_detector(): 训练吸烟检测模型 # 加载预训练模型 model YOLO(yolov8n.pt) # 可以选择yolov8s.pt、yolov8m.pt等 # 训练参数配置 training_results model.train( datasmoke.yaml, # 数据集配置文件 epochs100, # 训练轮数 imgsz640, # 输入图像尺寸 batch16, # 批次大小 device0, # 使用GPU 0如果是CPU则设为cpu workers4, # 数据加载线程数 patience10, # 早停耐心值 lr00.01, # 初始学习率 weight_decay0.0005, # 权重衰减 saveTrue, # 保存模型 projectruns/detect, # 项目保存路径 namesmoke_detection, # 实验名称 exist_okTrue # 覆盖现有实验 ) return training_results # 开始训练 if __name__ __main__: results train_smoke_detector() print(训练完成)4.3 训练过程监控训练过程中可以实时监控各项指标import matplotlib.pyplot as plt from ultralytics.utils.plots import plot_results # 绘制训练结果 def plot_training_results(results_path): 绘制训练过程中的指标变化 # 读取训练结果 results plot_results(fileresults_path, dir) # 创建监控图表 fig, axes plt.subplots(2, 2, figsize(15, 10)) # 损失函数变化 axes[0, 0].plot(results[train/box_loss], labelBox Loss) axes[0, 0].plot(results[train/cls_loss], labelCls Loss) axes[0, 0].set_title(Training Loss) axes[0, 0].legend() # 精度指标 axes[0, 1].plot(results[metrics/precision(B)], labelPrecision) axes[0, 1].plot(results[metrics/recall(B)], labelRecall) axes[0, 1].set_title(Precision Recall) axes[0, 1].legend() # mAP指标 axes[1, 0].plot(results[metrics/mAP50(B)], labelmAP0.5) axes[1, 0].plot(results[metrics/mAP50-95(B)], labelmAP0.5:0.95) axes[1, 0].set_title(mAP Metrics) axes[1, 0].legend() plt.tight_layout() plt.savefig(training_metrics.png, dpi300, bbox_inchestight) plt.show() # 使用示例 plot_training_results(runs/detect/smoke_detection/results.csv)4.4 模型评估与验证训练完成后对模型进行全面评估from ultralytics import YOLO import cv2 def evaluate_model(model_path, val_path): 评估模型性能 # 加载训练好的模型 model YOLO(model_path) # 在验证集上评估 metrics model.val( datasmoke.yaml, imgsz640, batch16, conf0.25, # 置信度阈值 iou0.45, # IoU阈值 device0 ) print(fmAP50: {metrics.box.map50:.4f}) print(fmAP50-95: {metrics.box.map:.4f}) print(fPrecision: {metrics.box.precision:.4f}) print(fRecall: {metrics.box.recall:.4f}) return metrics # 模型评估 best_model_path runs/detect/smoke_detection/weights/best.pt evaluate_model(best_model_path, smoke_detection/images/val/)5. 吸烟检测系统UI界面开发5.1 Streamlit界面设计使用Streamlit构建用户友好的检测界面import streamlit as st import cv2 import numpy as np from PIL import Image import tempfile import os from ultralytics import YOLO # 页面配置 st.set_page_config( page_title吸烟行为检测系统, page_icon, layoutwide ) # 标题和说明 st.title( YOLOv8吸烟行为检测系统) st.markdown( 基于YOLOv8的实时吸烟行为检测系统支持图片和视频检测。 ) # 侧边栏配置 st.sidebar.title(配置选项) confidence st.sidebar.slider(置信度阈值, 0.1, 1.0, 0.5, 0.05) iou_threshold st.sidebar.slider(IoU阈值, 0.1, 1.0, 0.45, 0.05) # 模型加载 st.cache_resource def load_model(): return YOLO(runs/detect/smoke_detection/weights/best.pt) model load_model() # 文件上传 uploaded_file st.file_uploader( 选择图片或视频文件, type[jpg, jpeg, png, mp4, avi] ) if uploaded_file is not None: # 临时保存文件 with tempfile.NamedTemporaryFile(deleteFalse) as tmp_file: tmp_file.write(uploaded_file.read()) file_path tmp_file.name # 检测文件类型 if uploaded_file.type.startswith(image): # 图片检测 image Image.open(file_path) st.image(image, caption原始图片, use_column_widthTrue) # 执行检测 if st.button(开始检测): results model.predict( sourcefile_path, confconfidence, iouiou_threshold, imgsz640 ) # 显示结果 for r in results: im_array r.plot() # 绘制检测结果 im Image.fromarray(im_array[..., ::-1]) # BGR to RGB st.image(im, caption检测结果, use_column_widthTrue) # 显示统计信息 st.info(f检测到 {len(r.boxes)} 个吸烟行为) elif uploaded_file.type.startswith(video): # 视频检测 st.video(file_path) if st.button(开始视频检测): # 视频处理逻辑 cap cv2.VideoCapture(file_path) stframe st.empty() while cap.isOpened(): ret, frame cap.read() if not ret: break # 执行检测 results model.predict( sourceframe, confconfidence, iouiou_threshold, imgsz640 ) # 绘制结果 annotated_frame results[0].plot() stframe.image(annotated_frame, channelsBGR, use_column_widthTrue) cap.release() # 清理临时文件 os.unlink(file_path) # 实时摄像头检测选项 if st.sidebar.checkbox(启用实时摄像头检测): st.sidebar.warning(实时检测功能需要摄像头权限) run_camera st.sidebar.button(开启摄像头) if run_camera: # 摄像头检测逻辑 pass5.2 检测结果可视化增强对检测结果进行更友好的可视化展示import plotly.graph_objects as go from plotly.subplots import make_subplots def create_detection_report(results): 创建详细的检测报告 fig make_subplots( rows2, cols2, subplot_titles(检测统计, 置信度分布, 目标大小分布, 检测时间线), specs[[{type: bar}, {type: histogram}], [{type: scatter}, {type: scatter}]] ) # 检测统计 detection_count len(results[0].boxes) fig.add_trace(go.Bar(x[吸烟行为], y[detection_count]), row1, col1) # 置信度分布 if detection_count 0: confidences [box.conf.item() for box in results[0].boxes] fig.add_trace(go.Histogram(xconfidences, nbinsx10), row1, col2) st.plotly_chart(fig, use_container_widthTrue) # 在Streamlit应用中调用 if results in locals(): create_detection_report(results)6. 系统部署与优化6.1 模型导出与优化将训练好的模型导出为不同格式以适应各种部署场景from ultralytics import YOLO def export_model(model_path): 导出模型为不同格式 model YOLO(model_path) # 导出为ONNX格式推荐 model.export(formatonnx, imgsz640, simplifyTrue) # 导出为TensorRT格式高性能 model.export(formatengine, imgsz640, device0) # 导出为OpenVINO格式 model.export(formatopenvino, imgsz640) print(模型导出完成) # 导出最佳模型 export_model(runs/detect/smoke_detection/weights/best.pt)6.2 性能优化技巧提升系统推理速度的实用技巧import time from ultralytics import YOLO class OptimizedDetector: 优化后的检测器类 def __init__(self, model_path, use_gpuTrue): self.model YOLO(model_path) self.use_gpu use_gpu self.warmup_model() def warmup_model(self): 模型预热避免首次推理延迟 dummy_input np.random.rand(640, 640, 3).astype(np.uint8) self.model.predict(sourcedummy_input, verboseFalse) def batch_detect(self, images, batch_size4): 批量检测优化 results [] for i in range(0, len(images), batch_size): batch images[i:ibatch_size] batch_results self.model.predict( sourcebatch, conf0.3, iou0.45, imgsz640, verboseFalse ) results.extend(batch_results) return results # 使用优化后的检测器 detector OptimizedDetector(runs/detect/smoke_detection/weights/best.pt)6.3 系统部署方案提供多种部署方案以适应不同需求# 方案1本地Web服务部署 from flask import Flask, request, jsonify import base64 import cv2 import numpy as np app Flask(__name__) model YOLO(runs/detect/smoke_detection/weights/best.pt) app.route(/detect, methods[POST]) def detect_smoking(): 吸烟检测API接口 try: # 接收base64编码的图片 image_data request.json[image] image_bytes base64.b64decode(image_data) image_array np.frombuffer(image_bytes, dtypenp.uint8) image cv2.imdecode(image_array, cv2.IMREAD_COLOR) # 执行检测 results model.predict(sourceimage, conf0.5) # 处理结果 detections [] for box in results[0].boxes: detection { confidence: float(box.conf), bbox: box.xywh[0].tolist(), class: smoking } detections.append(detection) return jsonify({ success: True, detections: detections, count: len(detections) }) except Exception as e: return jsonify({success: False, error: str(e)}) if __name__ __main__: app.run(host0.0.0.0, port5000, debugFalse)7. 常见问题与解决方案7.1 训练过程中的常见问题问题现象可能原因解决方案损失不下降学习率过高/过低调整lr0参数尝试0.01-0.001过拟合严重训练数据不足增加数据增强使用早停策略内存不足批次大小过大减小batch size使用梯度累积检测漏检多置信度阈值过高降低conf参数调整IoU阈值7.2 部署运行问题排查def diagnose_issues(): 系统问题诊断工具 issues [] # 检查GPU可用性 if not torch.cuda.is_available(): issues.append(警告未检测到GPU将使用CPU模式运行) # 检查模型文件 model_path runs/detect/smoke_detection/weights/best.pt if not os.path.exists(model_path): issues.append(f错误模型文件不存在 - {model_path}) # 检查依赖包版本 try: import ultralytics assert ultralytics.__version__ 8.0.0 except: issues.append(Ultralytics版本过低请升级到8.0.0以上) return issues # 运行诊断 issues diagnose_issues() if issues: for issue in issues: print(f⚠️ {issue}) else: print(✅ 系统检查通过)7.3 性能优化建议针对不同场景的性能调优策略实时检测场景使用TensorRT加速降低输入分辨率高精度场景使用更大的模型yolov8x提高输入分辨率边缘设备使用量化技术模型剪枝优化大规模部署使用模型服务化架构负载均衡8. 最佳实践与工程建议8.1 数据质量保证高质量的数据集是模型性能的基础def validate_dataset(dataset_path): 验证数据集质量 issues [] # 检查标注文件完整性 image_dir os.path.join(dataset_path, images/train) label_dir os.path.join(dataset_path, labels/train) for image_file in os.listdir(image_dir): image_path os.path.join(image_dir, image_file) label_file os.path.splitext(image_file)[0] .txt label_path os.path.join(label_dir, label_file) # 检查标注文件是否存在 if not os.path.exists(label_path): issues.append(f缺失标注文件: {label_file}) # 检查图片是否能正常读取 try: img cv2.imread(image_path) if img is None: issues.append(f图片损坏: {image_file}) except: issues.append(f图片读取失败: {image_file}) return issues8.2 模型版本管理建立规范的模型管理流程import json from datetime import datetime class ModelVersionManager: 模型版本管理器 def __init__(self, model_dir): self.model_dir model_dir self.version_file os.path.join(model_dir, versions.json) def save_version_info(self, model_path, metrics): 保存模型版本信息 version_info { timestamp: datetime.now().isoformat(), model_path: model_path, metrics: { map50: metrics.box.map50, map: metrics.box.map, precision: metrics.box.precision, recall: metrics.box.recall }, dataset_info: { train_size: len(os.listdir(smoke_detection/images/train)), val_size: len(os.listdir(smoke_detection/images/val)) } } # 读取现有版本信息 if os.path.exists(self.version_file): with open(self.version_file, r) as f: versions json.load(f) else: versions [] versions.append(version_info) # 保存更新后的版本信息 with open(self.version_file, w) as f: json.dump(versions, f, indent2)8.3 生产环境部署 checklist部署前的完整性检查清单[ ] 模型文件完整性验证[ ] 依赖包版本兼容性检查[ ] 硬件资源需求评估[ ] 网络带宽和延迟测试[ ] 安全权限配置[ ] 日志和监控系统集成[ ] 备份和恢复方案[ ] 性能压力测试通过本文的完整实践你已经掌握了从零开始构建YOLOv8吸烟检测系统的全流程技术要点。在实际项目中建议先从小规模试点开始逐步优化模型性能最后再扩展到大规模生产环境。记得定期更新训练数据以适应新的场景变化保持模型的检测准确性。