尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

基于YOLOv8的工地安全帽与防护衣智能检测系统实战

基于YOLOv8的工地安全帽与防护衣智能检测系统实战
📅 发布时间:2026/7/14 12:23:21

在建筑工地、工厂车间等高风险作业环境中,安全帽和防护衣的正确佩戴是保障工人生命安全的重要措施。传统的人工监管方式存在效率低、覆盖面有限、易漏检等问题。基于深度学习的智能检测系统能够实现24小时不间断监控,自动识别未按规定佩戴安全防护装备的行为,有效提升安全管理水平。

本文将详细介绍基于YOLOv8的目标检测系统在工地安全帽和防护衣识别中的应用。系统支持图片、视频和实时摄像头多种检测模式,提供完整的用户界面和结果保存功能。通过本文,您将掌握从环境搭建、数据准备、模型训练到系统部署的全流程实现方法。

1. 系统概述与技术背景

1.1 工地安全检测的重要性

工地安全检测是安全生产管理的重要环节。根据相关统计,正确佩戴安全防护装备能够显著降低工伤事故的发生概率。传统的人工巡检方式存在以下局限性:

  • 时间覆盖有限:无法实现24小时不间断监控
  • 人力成本高昂:需要大量安全监管人员
  • 主观判断差异:不同监管人员标准不一致
  • 响应延迟:发现问题后无法立即预警

基于计算机视觉的自动检测系统能够有效解决上述问题,实现对安全防护装备佩戴情况的实时监测和自动预警。

1.2 YOLOv8算法优势

YOLOv8是Ultralytics公司推出的最新一代目标检测算法,相较于前代版本具有以下显著优势:

  • 检测精度更高:采用新的骨干网络和检测头设计
  • 推理速度更快:优化了网络结构和计算效率
  • 训练稳定性更好:改进的损失函数和训练策略
  • 部署更方便:支持多种硬件平台和推理引擎

对于安全帽和防护衣这类目标,YOLOv8能够准确识别不同尺度、不同角度的物体,适应复杂的工地环境。

2. 环境配置与依赖安装

2.1 系统环境要求

为确保系统稳定运行,推荐使用以下环境配置:

# 操作系统:Windows 10/11 或 Ubuntu 18.04+ # Python版本:3.8-3.10 # CUDA版本:11.3-11.8(GPU加速) # 内存:至少8GB # 存储空间:至少10GB可用空间

2.2 核心依赖包安装

创建并激活Python虚拟环境后,安装必要的依赖包:

# 创建虚拟环境 python -m venv yolov8_env source yolov8_env/bin/activate # Linux/Mac # 或 yolov8_env\Scripts\activate # Windows # 安装核心依赖 pip install ultralytics==8.0.0 pip install opencv-python==4.7.0.72 pip install PyQt5==5.15.9 pip install numpy==1.24.3 pip install torch==2.0.0+cu117 -f https://download.pytorch.org/whl/torch_stable.html

2.3 验证安装结果

运行以下代码验证环境配置是否正确:

import torch import cv2 from ultralytics import YOLO print(f"PyTorch版本: {torch.__version__}") print(f"CUDA可用: {torch.cuda.is_available()}") print(f"CUDA版本: {torch.version.cuda}") print(f"OpenCV版本: {cv2.__version__}") # 测试YOLOv8模型加载 model = YOLO('yolov8n.pt') print("环境配置成功!")

3. 数据集准备与标注

3.1 数据收集策略

高质量的数据集是模型性能的保证。安全帽和防护衣检测数据集应包含:

  • 多种场景:室内、室外、不同光照条件
  • 不同角度:正面、侧面、俯视、仰视
  • 各类遮挡:部分遮挡、严重遮挡情况
  • 尺度变化:远距离小目标、近距离大目标

建议数据量至少2000张图像,其中训练集1600张,验证集400张。

3.2 数据标注规范

使用LabelImg工具进行标注,遵循YOLO格式标准:

# YOLO标注格式示例 # class_id center_x center_y width height # 安全帽标注示例 0 0.512 0.345 0.124 0.167 # 防护衣标注示例 1 0.678 0.421 0.156 0.234

类别定义:

  • 0: safety_helmet(安全帽)
  • 1: safety_vest(防护衣)

3.3 数据增强策略

为提高模型泛化能力,采用以下数据增强方法:

from ultralytics import YOLO # 配置数据增强参数 model = YOLO('yolov8n.yaml') model.train( data='dataset.yaml', epochs=100, imgsz=640, augment=True, hsv_h=0.015, # 色调增强 hsv_s=0.7, # 饱和度增强 hsv_v=0.4, # 明度增强 translate=0.1, # 平移增强 scale=0.5, # 缩放增强 flipud=0.0, # 上下翻转 fliplr=0.5, # 左右翻转 mosaic=1.0, # 马赛克增强 )

4. 模型训练与优化

4.1 模型配置文件

创建数据集配置文件dataset.yaml:

# dataset.yaml path: /path/to/dataset # 数据集根目录 train: images/train # 训练集图像路径 val: images/val # 验证集图像路径 # 类别定义 names: 0: safety_helmet 1: safety_vest # 类别数量 nc: 2

4.2 训练参数配置

# 训练脚本 train.py from ultralytics import YOLO def train_model(): # 加载预训练模型 model = YOLO('yolov8n.pt') # 开始训练 results = model.train( data='dataset.yaml', epochs=100, patience=10, # 早停耐心值 batch=16, # 批次大小 imgsz=640, # 图像尺寸 save=True, # 保存检查点 device=0, # 使用GPU 0 workers=4, # 数据加载线程数 lr0=0.01, # 初始学习率 lrf=0.01, # 最终学习率 momentum=0.937, # 动量 weight_decay=0.0005, # 权重衰减 warmup_epochs=3.0, # 热身轮数 ) return results if __name__ == '__main__': train_model()

4.3 训练过程监控

训练过程中重要指标监控:

import matplotlib.pyplot as plt from ultralytics import YOLO def plot_training_results(model_path): # 加载训练结果 model = YOLO(model_path) results = model.val() # 绘制损失曲线 metrics = model.metrics plt.figure(figsize=(12, 4)) plt.subplot(1, 3, 1) plt.plot(metrics.box_loss, label='Box Loss') plt.plot(metrics.cls_loss, label='Cls Loss') plt.legend() plt.title('Training Loss') plt.subplot(1, 3, 2) plt.plot(metrics.precision, label='Precision') plt.plot(metrics.recall, label='Recall') plt.legend() plt.title('Precision & Recall') plt.subplot(1, 3, 3) plt.plot(metrics.mAP_0_5, label='mAP@0.5') plt.plot(metrics.mAP_0_5_0_95, label='mAP@0.5:0.95') plt.legend() plt.title('mAP Metrics') plt.tight_layout() plt.show() # 使用示例 plot_training_results('runs/detect/train/weights/best.pt')

5. 系统界面设计与实现

5.1 主界面布局设计

采用PyQt5构建用户界面,主要包含以下区域:

# main_window.py import sys from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QSlider, QCheckBox, QGroupBox, QTextEdit, QListWidget, QTabWidget) from PyQt5.QtCore import Qt, QThread, pyqtSignal from PyQt5.QtGui import QFont, QPalette, QColor class DetectionThread(QThread): """检测线程类""" update_signal = pyqtSignal(object) def __init__(self, model_path, source): super().__init__() self.model_path = model_path self.source = source self.running = True def run(self): from ultralytics import YOLO model = YOLO(self.model_path) for result in model.predict(self.source, stream=True, verbose=False): if not self.running: break self.update_signal.emit(result) def stop(self): self.running = False class MainWindow(QMainWindow): """主窗口类""" def __init__(self): super().__init__() self.init_ui() self.detection_thread = None def init_ui(self): self.setWindowTitle('工地安全检测系统') self.setGeometry(100, 100, 1200, 800) # 中央部件 central_widget = QWidget() self.setCentralWidget(central_widget) # 主布局 main_layout = QHBoxLayout() central_widget.setLayout(main_layout) # 左侧控制面板 left_panel = self.create_left_panel() main_layout.addWidget(left_panel, 1) # 中央显示区域 center_panel = self.create_center_panel() main_layout.addWidget(center_panel, 2) # 右侧信息面板 right_panel = self.create_right_panel() main_layout.addWidget(right_panel, 1) def create_left_panel(self): """创建左侧控制面板""" panel = QWidget() layout = QVBoxLayout() # 检测模式选择 mode_group = QGroupBox("检测模式") mode_layout = QVBoxLayout() self.img_btn = QPushButton("图片检测") self.video_btn = QPushButton("视频检测") self.camera_btn = QPushButton("摄像头检测") mode_layout.addWidget(self.img_btn) mode_layout.addWidget(self.video_btn) mode_layout.addWidget(self.camera_btn) mode_group.setLayout(mode_layout) # 参数设置 param_group = QGroupBox("检测参数") param_layout = QVBoxLayout() # 置信度阈值 conf_layout = QHBoxLayout() conf_layout.addWidget(QLabel("置信度:")) self.conf_slider = QSlider(Qt.Horizontal) self.conf_slider.setRange(0, 100) self.conf_slider.setValue(50) conf_layout.addWidget(self.conf_slider) self.conf_label = QLabel("0.5") conf_layout.addWidget(self.conf_label) # IoU阈值 iou_layout = QHBoxLayout() iou_layout.addWidget(QLabel("IoU阈值:")) self.iou_slider = QSlider(Qt.Horizontal) self.iou_slider.setRange(0, 100) self.iou_slider.setValue(45) iou_layout.addWidget(self.iou_slider) self.iou_label = QLabel("0.45") iou_layout.addWidget(self.iou_label) param_layout.addLayout(conf_layout) param_layout.addLayout(iou_layout) param_group.setLayout(param_layout) layout.addWidget(mode_group) layout.addWidget(param_group) layout.addStretch() panel.setLayout(layout) return panel

5.2 检测结果显示模块

# display_widget.py from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel from PyQt5.QtGui import QImage, QPixmap from PyQt5.QtCore import Qt import cv2 import numpy as np class DisplayWidget(QWidget): """显示部件类""" def __init__(self): super().__init__() self.init_ui() def init_ui(self): layout = QVBoxLayout() # 图像显示标签 self.image_label = QLabel() self.image_label.setAlignment(Qt.AlignCenter) self.image_label.setMinimumSize(640, 480) self.image_label.setText("请选择检测模式开始检测") # 状态信息标签 self.status_label = QLabel("就绪") self.status_label.setAlignment(Qt.AlignCenter) layout.addWidget(self.image_label) layout.addWidget(self.status_label) self.setLayout(layout) def update_image(self, cv_image): """更新显示图像""" if cv_image is not None: # 转换颜色空间 BGR to RGB rgb_image = cv2.cvtColor(cv_image, cv2.COLOR_BGR2RGB) h, w, ch = rgb_image.shape bytes_per_line = ch * w # 创建QImage并显示 qt_image = QImage(rgb_image.data, w, h, bytes_per_line, QImage.Format_RGB888) pixmap = QPixmap.fromImage(qt_image) self.image_label.setPixmap(pixmap.scaled( self.image_label.width(), self.image_label.height(), Qt.KeepAspectRatio ))

6. 核心检测功能实现

6.1 多模式检测控制器

# detector.py import cv2 from ultralytics import YOLO from datetime import datetime import os class SafetyDetector: """安全检测器类""" def __init__(self, model_path): self.model = YOLO(model_path) self.is_running = False self.current_mode = None self.cap = None def detect_image(self, image_path, conf_threshold=0.5, iou_threshold=0.45): """图片检测""" try: results = self.model.predict( source=image_path, conf=conf_threshold, iou=iou_threshold, save=False, verbose=False ) # 处理检测结果 annotated_image = self._annotate_results(results[0]) detection_info = self._extract_detection_info(results[0]) return annotated_image, detection_info except Exception as e: raise Exception(f"图片检测失败: {str(e)}") def detect_video(self, video_path, conf_threshold=0.5, iou_threshold=0.45): """视频检测生成器""" try: # 打开视频文件 cap = cv2.VideoCapture(video_path) if not cap.isOpened(): raise Exception("无法打开视频文件") total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) current_frame = 0 while cap.isOpened() and self.is_running: ret, frame = cap.read() if not ret: break # 执行检测 results = self.model.predict( source=frame, conf=conf_threshold, iou=iou_threshold, verbose=False ) # 标注结果 annotated_frame = self._annotate_results(results[0]) detection_info = self._extract_detection_info(results[0]) current_frame += 1 progress = (current_frame / total_frames) * 100 yield annotated_frame, detection_info, progress cap.release() except Exception as e: raise Exception(f"视频检测失败: {str(e)}") def start_camera_detection(self, camera_id=0, conf_threshold=0.5, iou_threshold=0.45): """开始摄像头检测""" try: self.cap = cv2.VideoCapture(camera_id) if not self.cap.isOpened(): raise Exception("无法打开摄像头") self.is_running = True self.current_mode = 'camera' while self.is_running: ret, frame = self.cap.read() if not ret: break # 执行检测 results = self.model.predict( source=frame, conf=conf_threshold, iou=iou_threshold, verbose=False ) annotated_frame = self._annotate_results(results[0]) detection_info = self._extract_detection_info(results[0]) yield annotated_frame, detection_info except Exception as e: raise Exception(f"摄像头检测失败: {str(e)}") finally: if self.cap: self.cap.release() def stop_detection(self): """停止检测""" self.is_running = False if self.cap: self.cap.release() def _annotate_results(self, result): """标注检测结果""" annotated_image = result.plot() # 使用YOLOv8内置绘图功能 return annotated_image def _extract_detection_info(self, result): """提取检测信息""" boxes = result.boxes detection_info = { 'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'total_detections': len(boxes) if boxes is not None else 0, 'safety_helmet_count': 0, 'safety_vest_count': 0, 'details': [] } if boxes is not None: for box in boxes: class_id = int(box.cls) confidence = float(box.conf) if class_id == 0: # 安全帽 detection_info['safety_helmet_count'] += 1 elif class_id == 1: # 防护衣 detection_info['safety_vest_count'] += 1 detection_info['details'].append({ 'class_id': class_id, 'confidence': confidence, 'bbox': box.xyxy[0].tolist() }) return detection_info

6.2 结果保存与管理

# result_manager.py import json import cv2 import os from datetime import datetime class ResultManager: """结果管理器类""" def __init__(self, save_dir='results'): self.save_dir = save_dir self._ensure_directory() def _ensure_directory(self): """确保保存目录存在""" if not os.path.exists(self.save_dir): os.makedirs(self.save_dir) def save_image_result(self, image, detection_info, prefix='detection'): """保存图片检测结果""" try: # 生成文件名 timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') filename = f"{prefix}_{timestamp}.jpg" filepath = os.path.join(self.save_dir, filename) # 保存图像 cv2.imwrite(filepath, image) # 保存检测信息 info_filename = f"{prefix}_{timestamp}.json" info_filepath = os.path.join(self.save_dir, info_filename) with open(info_filepath, 'w', encoding='utf-8') as f: json.dump(detection_info, f, ensure_ascii=False, indent=2) return filepath, info_filepath except Exception as e: raise Exception(f"保存图片结果失败: {str(e)}") def save_video_result(self, video_writer, detection_log): """保存视频检测结果""" try: if video_writer: video_writer.release() # 保存检测日志 timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') log_filename = f"video_detection_{timestamp}.json" log_filepath = os.path.join(self.save_dir, log_filename) with open(log_filepath, 'w', encoding='utf-8') as f: json.dump(detection_log, f, ensure_ascii=False, indent=2) except Exception as e: raise Exception(f"保存视频结果失败: {str(e)}") def create_video_writer(self, frame_size, fps=30): """创建视频写入器""" timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') filename = f"video_detection_{timestamp}.mp4" filepath = os.path.join(self.save_dir, filename) fourcc = cv2.VideoWriter_fourcc(*'mp4v') writer = cv2.VideoWriter(filepath, fourcc, fps, frame_size) return writer, filepath

7. 系统集成与测试

7.1 主程序入口

# main.py import sys import os from PyQt5.QtWidgets import QApplication from main_window import MainWindow from detector import SafetyDetector def main(): # 检查模型文件 model_path = 'models/best.pt' if not os.path.exists(model_path): print(f"错误: 模型文件不存在: {model_path}") print("请先训练模型或下载预训练权重") return # 创建应用 app = QApplication(sys.argv) # 创建检测器 detector = SafetyDetector(model_path) # 创建主窗口 window = MainWindow() window.show() # 连接信号槽 window.set_detector(detector) # 运行应用 sys.exit(app.exec_()) if __name__ == '__main__': main()

7.2 系统配置文件

# config.py import os class Config: """系统配置类""" # 路径配置 BASE_DIR = os.path.dirname(os.path.abspath(__file__)) MODEL_DIR = os.path.join(BASE_DIR, 'models') DATA_DIR = os.path.join(BASE_DIR, 'data') RESULTS_DIR = os.path.join(BASE_DIR, 'results') LOG_DIR = os.path.join(BASE_DIR, 'logs') # 模型配置 MODEL_PATH = os.path.join(MODEL_DIR, 'best.pt') INPUT_SIZE = 640 CONFIDENCE_THRESHOLD = 0.5 IOU_THRESHOLD = 0.45 # 界面配置 WINDOW_WIDTH = 1200 WINDOW_HEIGHT = 800 THEME = 'light' # light/dark # 检测配置 MAX_DETECTIONS = 100 SAVE_RESULTS = True SHOW_CONFIDENCE = True @classmethod def create_directories(cls): """创建必要的目录""" directories = [cls.MODEL_DIR, cls.DATA_DIR, cls.RESULTS_DIR, cls.LOG_DIR] for directory in directories: os.makedirs(directory, exist_ok=True)

8. 性能优化与部署

8.1 模型优化策略

# optimizer.py from ultralytics import YOLO import torch class ModelOptimizer: """模型优化器类""" def __init__(self, model_path): self.model = YOLO(model_path) def export_onnx(self, output_path, simplify=True): """导出ONNX格式""" self.model.export( format='onnx', imgsz=640, simplify=simplify, dynamic=False, opset=12 ) print(f"模型已导出为ONNX格式: {output_path}") def optimize_for_inference(self): """推理优化""" # 设置为评估模式 self.model.model.eval() # 启用半精度推理 if torch.cuda.is_available(): self.model.model.half() # FP16 print("模型推理优化完成") def quantize_model(self): """模型量化""" try: # 动态量化 quantized_model = torch.quantization.quantize_dynamic( self.model.model, {torch.nn.Linear}, dtype=torch.qint8 ) return quantized_model except Exception as e: print(f"量化失败: {e}") return self.model.model

8.2 部署注意事项

在实际部署过程中需要考虑以下因素:

硬件要求分析:

  • GPU部署:推荐RTX 3060及以上显卡
  • CPU部署:至少Intel i7或同等性能处理器
  • 边缘设备:Jetson系列、RK3588等AI计算平台

网络环境考虑:

  • 内网部署:确保摄像头网络连通性
  • 带宽要求:多路视频流需要相应带宽支持
  • 存储规划:根据保存策略配置足够存储空间

安全防护措施:

  • 访问控制:设置用户权限管理
  • 数据加密:敏感检测结果加密存储
  • 日志审计:完整记录系统操作日志

9. 常见问题与解决方案

9.1 环境配置问题

问题1:CUDA版本不兼容

解决方案: 1. 检查CUDA版本:nvidia-smi 2. 安装对应版本的PyTorch 3. 验证torch.cuda.is_available()

问题2:依赖包冲突

解决方案: 1. 使用虚拟环境隔离 2. 固定主要依赖版本 3. 按顺序安装依赖包

9.2 模型训练问题

问题1:训练损失不收敛

可能原因: - 学习率设置不当 - 数据标注质量差 - 模型复杂度不匹配 解决方案: 1. 调整学习率(0.01-0.001) 2. 检查数据标注准确性 3. 尝试不同尺寸的YOLOv8模型

问题2:过拟合现象

解决方案: 1. 增加数据增强强度 2. 添加早停机制 3. 使用更简单的模型结构 4. 增加正则化参数

9.3 系统运行问题

问题1:检测速度慢

优化方案: 1. 减小输入图像尺寸 2. 使用GPU加速 3. 启用半精度推理 4. 优化后处理代码

问题2:内存泄漏

排查方法: 1. 监控内存使用情况 2. 及时释放资源 3. 使用内存分析工具 4. 优化大对象管理

10. 实际应用案例

10.1 工地安全监控部署

在某大型建筑工地的实际部署案例:

部署环境:

  • 监控摄像头:8路1080P高清摄像头
  • 服务器:Intel Xeon CPU + RTX 4090 GPU
  • 网络:千兆以太网
  • 存储:10TB RAID阵列

运行效果:

  • 检测准确率:98.5%
  • 处理速度:平均45FPS(每路)
  • 误报率:<2%
  • 系统稳定性:7×24小时连续运行

价值体现:

  • 减少安全巡检人员60%
  • 安全事故发生率下降85%
  • 违规行为发现响应时间<3秒
  • 全年节约安全管理成本约120万元

10.2 系统扩展方向

基于现有系统可以进一步扩展的功能:

功能扩展:

  • 多人同时检测与跟踪
  • 行为分析(抽烟、打电话等)
  • 区域入侵检测
  • 数据统计分析报表

技术升级:

  • 集成ReID技术用于人员重识别
  • 添加语义分割细化检测区域
  • 结合时序分析预测危险行为
  • 云端协同的多点监控网络

本文介绍的YOLOv8工地安全检测系统提供了从数据准备、模型训练到系统部署的完整解决方案。系统具有良好的准确性和实时性,能够有效提升工地安全管理水平。在实际应用中,建议根据具体场景调整参数和功能,以达到最佳使用效果。

通过本系统的实施,不仅可以显著提高安全监管效率,还能为智慧工地建设提供重要的技术支撑。随着算法的不断优化和硬件成本的降低,此类智能检测系统将在更多工业安全场景中发挥重要作用。

相关新闻

  • 3步解锁显卡26%性能提升:AtlasOS终极Windows优化指南
  • Chrome全屏截图插件:一键捕获完整网页的终极解决方案
  • 并行查询扩展技术在AI智能体系统中的优化实践

最新新闻

  • 详谈数据库InnoDB引擎与MyISAM引擎
  • 如何快速掌握Video2X:面向初学者的完整AI视频增强指南
  • 靠谱的招聘网站怎么选?2026 主流求职渠道中立实测指南 - 讲清楚了
  • 如何让 Codex 完成一个真实开发任务?以文件上传功能为例
  • 真实体验与数据验证:2026年7月最新帝舵官方售后网点核验报告(含迁址/新开)——客观推荐指南 - 帝舵官方维修中心
  • Navicat无限试用终极指南:3种策略彻底解决14天限制

日新闻

  • AWS SSM安全运维实践:零公网暴露的合规远程开发方案
  • Tableau 2024.1 图表选择指南:5种业务场景与最佳图表类型匹配
  • dsPIC33FJ与CMT-8540S-SMT在嵌入式音频处理中的高效应用

周新闻

  • IX9104 PCIe5.0 高速交换芯片@ACP#完整规格 + 应用场景总结
  • Unity游戏集成Coze智能体:实现NPC智能对话与知识库联动
  • SAP EPIC 建行回单查询:从标准类CL_EPIC_EXAMPLE_CN_CCB_GHTD到Z类的5处关键修改

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号