在这里插入图片描述

hello hello~ ,这里是 code袁~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹

🦁作者简介:一名喜欢分享和记录学习的在校大学生
💥个人主页code袁的博客
💥 个人QQ:2647996100
🐯 个人wechat:code8896
code袁系列专栏导航
1.《毕业设计与课程设计》本专栏分享一些毕业设计的源码以及项目成果。🥰🥰🥰
2.微信小程序开发》本专栏从基础到入门的一系开发流程,并且分享了自己在开发中遇到的一系列问题。🤹🤹🤹
3.vue开发系列全程线路》本专栏分享自己的vue的学习历程。

非常期待和您一起在这个小小的互联网世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨ 

在这里插入图片描述

一、项目背景与意义

在建筑工地、电力运维、矿山开采等高危作业场景中,安全帽是保障工人生命安全的第一道防线。然而,传统的人工巡检方式存在效率低、覆盖不全、易受主观因素影响等问题,导致未佩戴安全帽的违规行为屡禁不止,埋下了严重的安全隐患。
随着深度学习技术的快速发展,基于计算机视觉的智能安全检测系统应运而生。本项目采用当前最先进的 YOLOv8 目标检测算法,结合 PyQt5 构建了一套完整的智能安全帽检测系统,实现了对作业人员安全帽佩戴情况的实时、自动、精准识别与预警,为工业安全生产提供了强有力的技术支撑。

二、技术栈选型

本项目采用前后端分离的架构设计,核心技术栈如下:
在这里插入图片描述

三、系统架构设计

本系统整体分为用户登录模块、AI 检测模块、数据管理模块和预警通知模块四大核心部分,架构清晰,易于维护和扩展:

1.用户登录模块

提供用户名、密码及验证码校验功能,保障系统访问安全。
支持新用户注册,实现权限管理。
界面采用深色科技风设计,提升用户体验。

2.AI 检测模块

支持三种检测模式:图片检测、视频文件检测、实时摄像头流检测。
集成 YOLOv8 模型,可灵活切换不同权重文件(如best.pt)。
提供置信度阈值调节滑块,用户可根据场景需求调整检测精度。
实时显示检测耗时、发现目标数量、目标类别及置信度。

3.数据管理模块

实时更新检测日志,记录每条检测结果的 ID、源文件、识别类别、置信度和边界框坐标。
支持一键导出检测报告,生成结构化文档用于安全管理和复盘。
提供日志清空功能,方便系统维护。

4.预警通知模块

当检测到未佩戴安全帽(NoHelmet)时,自动触发语音预警,提醒现场人员和管理人员。
在界面右侧实时统计 Helmet 和 NoHelmet 的数量,直观展示检测结果。

四、核心功能实现

1. YOLOv8 模型训练与推理

本项目的核心是 YOLOv8 模型的应用。我们首先收集了包含 “佩戴安全帽” 和 “未佩戴安全帽” 两类目标的数据集,对 YOLOv8n/s/m 等不同尺寸的模型进行了训练和对比,最终选择了在精度和速度上表现最优的模型权重。

from ultralytics import YOLO

model=YOLO("./yolov8n.pt",task="detect")

model.train(data='yolo-bm.yaml',workers=0,epochs=50,batch=16)
2. PyQt5 桌面客户端开发

为了让非技术人员也能方便地使用这套系统,我们基于 PyQt5 开发了直观易用的桌面客户端。主要实现了以下功能:

1.登录界面:

使用 QLineEdit、QPushButton 等组件构建,实现了表单验证和验证码刷新功能。

2.主界面布局:

采用 QSplitter 和 QGridLayout 进行布局,左侧为功能导航栏,中间为检测结果展示区,右侧为系统状态和统计信息区。
实时检测:通过 QTimer 定时器,定时从摄像头或视频文件中读取帧,送入 YOLOv8 模型进行推理,并将结果实时渲染到 QLabel 上。
交互反馈:检测到违规行为时,通过 QSoundEffect 播放语音预警,同时更新日志表格和统计数据。

3. 关键技术细节

实时性优化:通过多线程技术,将模型推理和界面更新分离,避免界面卡顿,确保检测流畅。
置信度调节:通过 QSlider 组件,让用户可以实时调整置信度阈值,过滤掉低置信度的误检。
数据持久化:使用 SQLAlchemy ORM 框架,将检测日志和用户信息高效地存储到数据库中,支持快速查询和导出。

五、效果展示

1. 登录界面

系统启动后,用户首先进入登录界面,输入账号密码和验证码后即可进入主系统。

在这里插入图片描述

2. 图片检测效果

系统可以对单张图片进行检测,精准识别出图中人员是否佩戴安全帽,并标注出置信度。
在这里插入图片描述

3. 视频 / 实时检测效果

在实时摄像头或视频流检测中,系统能够以毫秒级的速度处理每一帧,实时显示检测结果和预警信息。
在这里插入图片描述

六、模型结果

在这里插入图片描述

在这里插入图片描述

七、核心代码

import sys
import os
import pymysql
from datetime import datetime
# 将当前目录加入系统路径,确保能导入同目录的login.py
sys.path.append(os.path.dirname(os.path.abspath(__file__)))

from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, 
                             QHBoxLayout, QLabel, QLineEdit, QPushButton, 
                             QFrame, QSpacerItem, QSizePolicy, QMessageBox,
                             QGraphicsDropShadowEffect)
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QFont, QCursor, QColor

# 尝试导入登录窗口(添加异常处理,防止导入失败)
try:
    from login import LoginWindow
except ImportError as e:
    print(f"导入登录模块失败: {e}")
    LoginWindow = None

# ================= MySQL 数据库配置 =================
def get_mysql_connection():
    """创建并返回 MySQL 连接(按需修改配置)"""
    try:
        conn = pymysql.connect(
            host='localhost',  # 数据库地址(本地填localhost,远程填IP)
            port=3306,         # MySQL端口(默认3306)
            user='root',       # 数据库用户名
            password='123456',  # 替换为你的MySQL密码
            database='helmet',  # 数据库名
        )
        return conn
    except pymysql.MySQLError as e:
        QMessageBox.critical(None, "数据库错误", f"连接MySQL失败:{str(e)}")
        return None

class RegisterWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.login_window = None
        self.initUI()
        
    def initUI(self):
        self.setWindowTitle('🚜 智能安全帽检测系统 - 账号注册')
        self.resize(900, 580)
        
        # 1. 设置主窗口背景
        main_widget = QWidget()
        main_widget.setObjectName("MainWindow")
        self.setCentralWidget(main_widget)
        main_layout = QVBoxLayout(main_widget)
        main_layout.setContentsMargins(40, 40, 40, 40) # 留出边距,用于显示阴影
        
        # 2. 创建居中的主卡片
        self.card_frame = QFrame()
        self.card_frame.setObjectName("MainCard")
        card_layout = QHBoxLayout(self.card_frame)
        card_layout.setContentsMargins(0, 0, 0, 0)
        card_layout.setSpacing(0)
        
        # 为卡片添加高级阴影
        shadow = QGraphicsDropShadowEffect(self)
        shadow.setBlurRadius(20)
        shadow.setXOffset(0)
        shadow.setYOffset(10)
        shadow.setColor(QColor(0, 0, 0, 80))
        self.card_frame.setGraphicsEffect(shadow)

        # 3. 加载全局现代化 QSS 样式表
        self.setup_style()

        # ================= 1. 左侧信息面板 =================
        left_panel = QFrame()
        left_panel.setObjectName("LeftPanel")
        left_layout = QVBoxLayout(left_panel)
        left_layout.setContentsMargins(40, 40, 40, 40)
        left_layout.setAlignment(Qt.AlignCenter)
        
        logo_label = QLabel("📝")
        logo_label.setFont(QFont("Segoe UI Emoji", 70))
        logo_label.setAlignment(Qt.AlignCenter)
        logo_label.setStyleSheet("margin-bottom: 20px;")
        
        left_title = QLabel("欢迎注册")
        left_title.setFont(QFont("Microsoft YaHei", 24, QFont.Bold))
        left_title.setStyleSheet("color: #F8FAFC; letter-spacing: 2px;")
        left_title.setAlignment(Qt.AlignCenter)
        
        sub_title = QLabel("智能终端系统")
        sub_title.setFont(QFont("Microsoft YaHei", 12))
        sub_title.setStyleSheet("color: #38BDF8; margin-top: 10px; font-weight: bold;")
        sub_title.setAlignment(Qt.AlignCenter)
        
        desc_label = QLabel("加入我们,体验前沿的AI视觉检测服务\n安全、高效、精准防护")
        desc_label.setFont(QFont("Microsoft YaHei", 10))
        desc_label.setStyleSheet("color: #94A3B8; margin-top: 15px; line-height: 1.5;")
        desc_label.setAlignment(Qt.AlignCenter)
        
        left_layout.addStretch()
        left_layout.addWidget(logo_label)
        left_layout.addWidget(left_title)
        left_layout.addWidget(sub_title)
        left_layout.addWidget(desc_label)
        left_layout.addStretch()

        # ================= 2. 右侧注册面板 =================
        right_panel = QFrame()
        right_panel.setObjectName("RightPanel")
        right_layout = QVBoxLayout(right_panel)
        right_layout.setContentsMargins(50, 40, 50, 40)
        
        right_layout.addStretch(1)
        
        right_title = QLabel("创建新账号")
        right_title.setFont(QFont("Microsoft YaHei", 18, QFont.Bold))
        right_title.setStyleSheet("color: #F8FAFC; margin-bottom: 5px;")
        right_title.setAlignment(Qt.AlignCenter)
        right_layout.addWidget(right_title)

        right_sub = QLabel("填写以下信息完成注册")
        right_sub.setStyleSheet("color: #64748B; margin-bottom: 25px; font-size: 13px;")
        right_sub.setAlignment(Qt.AlignCenter)
        right_layout.addWidget(right_sub)

        # --- 用户名输入区 ---
        right_layout.addWidget(self.create_label("设置用户名"))
        user_frame = QFrame()
        user_frame.setProperty("class", "InputFrame")
        user_layout = QHBoxLayout(user_frame)
        user_layout.setContentsMargins(15, 8, 15, 8)
        user_icon = QLabel("👤")
        user_icon.setStyleSheet("color: #94A3B8; font-size: 14px;")
        self.reg_user_input = QLineEdit()
        self.reg_user_input.setPlaceholderText("请输入4-16位字母或数字")
        user_layout.addWidget(user_icon)
        user_layout.addWidget(self.reg_user_input)
        right_layout.addWidget(user_frame)
        
        right_layout.addSpacing(15)

        # --- 密码输入区 ---
        right_layout.addWidget(self.create_label("设置密码"))
        pwd_frame = QFrame()
        pwd_frame.setProperty("class", "InputFrame")
        pwd_layout = QHBoxLayout(pwd_frame)
        pwd_layout.setContentsMargins(15, 8, 15, 8)
        pwd_icon = QLabel("🔒")
        pwd_icon.setStyleSheet("color: #94A3B8; font-size: 14px;")
        self.reg_pwd_input = QLineEdit()
        self.reg_pwd_input.setPlaceholderText("请输入密码(至少6位)")
        self.reg_pwd_input.setEchoMode(QLineEdit.Password)
        pwd_layout.addWidget(pwd_icon)
        pwd_layout.addWidget(self.reg_pwd_input)
        right_layout.addWidget(pwd_frame)
        
        right_layout.addSpacing(15)

        # --- 确认密码输入区 ---
        right_layout.addWidget(self.create_label("确认密码"))
        pwd2_frame = QFrame()
        pwd2_frame.setProperty("class", "InputFrame")
        pwd2_layout = QHBoxLayout(pwd2_frame)
        pwd2_layout.setContentsMargins(15, 8, 15, 8)
        pwd2_icon = QLabel("🔒")
        pwd2_icon.setStyleSheet("color: #94A3B8; font-size: 14px;")
        self.reg_pwd2_input = QLineEdit()
        self.reg_pwd2_input.setPlaceholderText("请再次输入密码以确认")
        self.reg_pwd2_input.setEchoMode(QLineEdit.Password)
        pwd2_layout.addWidget(pwd2_icon)
        pwd2_layout.addWidget(self.reg_pwd2_input)
        right_layout.addWidget(pwd2_frame)
        
        right_layout.addSpacing(30)

        # --- 按钮区 ---
        self.btn_submit_register = QPushButton("立 即 注 册")
        self.btn_submit_register.setObjectName("btn_register_main")
        self.btn_submit_register.setCursor(QCursor(Qt.PointingHandCursor))
        self.btn_submit_register.clicked.connect(self.submit_register)
        right_layout.addWidget(self.btn_submit_register)
        
        right_layout.addSpacing(10)
        
        self.btn_back_to_login = QPushButton("已有账号?返回登录")
        self.btn_back_to_login.setObjectName("btn_ghost")
        self.btn_back_to_login.setCursor(QCursor(Qt.PointingHandCursor))
        self.btn_back_to_login.clicked.connect(self.back_to_login)
        right_layout.addWidget(self.btn_back_to_login)

        right_layout.addStretch(1)

        # ================= 3. 加入主卡片布局 =================
        card_layout.addWidget(left_panel, 45) # 调整比例,视觉更协调
        card_layout.addWidget(right_panel, 55)
        
        main_layout.addWidget(self.card_frame)

    def setup_style(self):
        """定义现代化 UI 样式表"""
        style = """
            /* 全局与背景 */
            QWidget#MainWindow {
                background-color: #0F172A; /* 深邃蓝灰背景 */
            }
            * {
                font-family: "Segoe UI", "Microsoft YaHei", sans-serif;
            }
            
            /* 主卡片布局 */
            QFrame#MainCard {
                background-color: transparent;
            }
            QFrame#LeftPanel {
                background-color: #1E293B;
                border-top-left-radius: 12px;
                border-bottom-left-radius: 12px;
                border: 1px solid #334155;
                border-right: none;
            }
            QFrame#RightPanel {
                background-color: #0F172A;
                border-top-right-radius: 12px;
                border-bottom-right-radius: 12px;
                border: 1px solid #334155;
                border-left: 1px solid #1E293B;
            }

            /* 输入框包装层 */
            .InputFrame {
                background-color: #1E293B;
                border: 1px solid #334155;
                border-radius: 8px;
            }
            .InputFrame:hover {
                border: 1px solid #475569;
                background-color: #233043;
            }

            /* 原生输入框 */
            QLineEdit {
                background-color: transparent;
                border: none;
                color: #F8FAFC;
                font-size: 14px;
                padding-left: 5px;
            }
            QLineEdit::placeholder {
                color: #64748B;
            }

            /* 注册主按钮 */
            QPushButton#btn_register_main {
                background-color: #2563EB;
                color: white;
                border: none;
                border-radius: 8px;
                padding: 14px;
                font-size: 15px;
                font-weight: bold;
                letter-spacing: 2px;
            }
            QPushButton#btn_register_main:hover {
                background-color: #3B82F6;
            }
            QPushButton#btn_register_main:pressed {
                background-color: #1D4ED8;
            }

            /* 返回登录幽灵按钮 */
            QPushButton#btn_ghost {
                background-color: transparent;
                color: #94A3B8;
                border: 1px solid #334155;
                border-radius: 8px;
                padding: 12px;
                font-size: 14px;
            }
            QPushButton#btn_ghost:hover {
                border: 1px solid #475569;
                color: #F8FAFC;
                background-color: rgba(51, 65, 85, 0.5);
            }
        """
        self.setStyleSheet(style)
        
    def create_label(self, text):
        """辅助函数:创建输入框上方的小标题标签"""
        lbl = QLabel(text)
        lbl.setFont(QFont("Microsoft YaHei", 10, QFont.Bold))
        lbl.setStyleSheet("color: #94A3B8; margin-bottom: 2px; margin-left: 2px;")
        return lbl
    
    def submit_register(self):
        """处理注册提交逻辑 - 写入MySQL数据库"""
        # 1. 获取并验证输入
        username = self.reg_user_input.text().strip()
        password = self.reg_pwd_input.text().strip()
        password2 = self.reg_pwd2_input.text().strip()
        
        # 基础验证
        if not username:
            QMessageBox.warning(self, "注册提示", "请输入用户名!")
            return
        if len(username) < 4 or len(username) > 16:
            QMessageBox.warning(self, "注册提示", "用户名长度需在4-16位之间!")
            return
        if not password:
            QMessageBox.warning(self, "注册提示", "请输入密码!")
            return
        if len(password) < 6:
            QMessageBox.warning(self, "注册提示", "密码长度至少6位!")
            return
        if password != password2:
            QMessageBox.warning(self, "注册提示", "两次输入的密码不一致!")
            return
        
        # 2. 连接MySQL并写入数据
        conn = get_mysql_connection()
        if not conn:
            return
        
        try:
            # 创建游标
            cursor = conn.cursor()
            
            # 检查用户名是否已存在
            check_sql = "SELECT username FROM user WHERE username = %s"
            cursor.execute(check_sql, (username,))
            if cursor.fetchone():  # 查到数据说明用户名已存在
                QMessageBox.warning(self, "注册提示", "用户名已存在!")
                return
            
            # 插入新用户(注意:实际项目中密码要加密,这里先明文演示)
            insert_sql = "INSERT INTO user (username, password) VALUES (%s, %s)"
            cursor.execute(insert_sql, (username, password))
            
            # 提交事务
            conn.commit()
            QMessageBox.information(self, "注册成功", "账号注册成功!即将返回登录界面")
            
            # 返回登录
            self.back_to_login()
            
        except pymysql.MySQLError as e:
            conn.rollback()  # 出错回滚
            QMessageBox.critical(self, "数据库错误", f"注册失败:{str(e)}")
        finally:
            # 关闭游标和连接
            cursor.close()
            conn.close()
    
    def back_to_login(self):
        """返回登录界面"""
        try:
            if LoginWindow is None:
                QMessageBox.critical(self, "错误", "无法找到登录窗口模块!")
                return
            
            self.login_window = LoginWindow()
            self.login_window.show()
            self.close()
            
        except Exception as e:
            QMessageBox.critical(self, "错误", f"打开登录窗口失败:{str(e)}")
    
    def closeEvent(self, event):
        """窗口关闭时的清理操作"""
        if self.login_window and not self.login_window.isVisible():
            self.login_window.show()
        event.accept()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyle("Fusion")
    
    # 启用全局字体抗锯齿优化
    font = app.font()
    font.setStyleStrategy(QFont.PreferAntialias)
    app.setFont(font)
    
    window = RegisterWindow()
    window.show()
    sys.exit(app.exec_())
八、源码获取

大家点赞、收藏、关注、评论啦 、查看👇🏻获取联系方式👇🏻

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐