基于深度学习YOLOv8的睡岗检测睡岗识别在岗检测系统设计目标检测
本文介绍了一个基于YOLOv8深度学习模型的睡岗识别系统。该系统包含550+张已标注图片的数据集、训练好的模型(准确率99.4%)和完整的UI界面。系统支持图片、视频和摄像头检测,可识别"在岗"和"睡岗"两种状态,并能保存检测结果。该系统采用PyQt5开发图形界面,提供置信度、位置信息显示和数量统计功能。源码展示了系统初始化、模型加载和信号连接等关键功能实现
获取完整资源,请查看个人主页的个人简介
1、数据集(已全部标注)
2、训练好的模型(pt文件和图表)
3、完整系统UI界面、文件目录说明、程序运行说明
一、数据集介绍
1、数量:550+张图片和对应标签
2、类别:names = {0: ‘on_post’, 1: ‘sleeping_post’}
CH_names = [‘在岗’,’睡岗’]

二、训练好的模型介绍
1、基于YOLOv8训练的模型
2、训练轮数:300轮
3、精确率:99.4%


三、完整系统介绍
1、检测识别:
names = names = {0: ‘on_post’, 1: ‘sleeping_post’}
CH_names = [‘在岗’,’睡岗’]
2、图片检测+视频检测+摄像头检测
3、展示检测目标置信度位置信息,统计数量,自由选择检测结果
4、检测结果保存至本地
5、自定义系统标题:UIProgram->UiMain.py->拉到末尾
6、自定义系统图标:UIProgram->ui_imgs->替换图片注意文件格式和名称不变

在现代工业生产环境中,睡岗现象不仅代表着员工的不文明行为,更是一种严重的玩忽职守表现,对生产安全构成重大威胁。在需要连续值守的岗位,如工厂生产线、交通监控、安保中心等,人员一旦在岗位上睡觉,极易导致操作失误、无法及时调整机器工况、不能第一时间发现问题等情况,给整个生产作业带来巨大的安全隐患,并影响生产进度。传统的睡岗检测方法主要依靠人工监控和定期巡查,这种方式不仅效率低下,而且容易因监控人员疲劳导致漏检,难以实现全天候、全覆盖的实时监测。
随着人工智能技术的发展,特别是深度学习技术在计算机视觉领域的突破,为目标检测任务提供了新的解决方案。YOLO(You Only Look Once)系列算法作为近年来目标检测领域的重要进展,以其高效的检测速度和卓越的准确率,在多个实时检测场景中展现了强大的潜力。其中,YOLOv8作为Ultralytics公司发布的新一代目标检测模型,采用更轻量的架构、更先进的损失函数与Anchor-Free策略,在COCO等数据集上表现优异,成为实现睡岗检测的理想技术选择。
在此背景下,本研究提出了一种基于YOLOv8深度学习模型与PyQt5图形界面的睡岗识别系统,通过计算机视觉技术自动检测人员的睡岗行为,并进行实时预警。该系统不仅解决了传统人工监测效率低下的问题,还为工作场所的安全管理提供了智能化、自动化的解决方案,对提升生产效率、预防安全事故具有重要的现实意义。
基于YOLOv8和PyQt5的睡岗识别系统具有广阔的应用前景和重要的实用价值。在工业制造领域,系统可以部署在工厂生产线上,实时监测工人的在岗状态,避免因疲劳操作而引发的安全事故。在交通运输行业,该系统可用于驾驶员的疲劳驾驶监测,通过分析驾驶员的面部表情和身体姿势,及时发现睡岗行为,有效预防交通事故的发生。此外,在安保监控、医院护理等需要长时间值勤的领域,系统同样能够发挥重要作用,确保监控工作的连续性和有效性,保障患者安全。
从管理效率角度看,睡岗识别系统的应用将显著提升安全管理水平。传统的睡岗监测主要依靠管理人员的人工巡查,这种方式不仅效率低下,而且容易因主观因素导致监测结果不一致。本系统实现了睡岗检测的自动化和智能化,减少人工巡检和监督的频次和成本,提高管理效率。系统还能够提供客观的睡岗行为记录,为员工绩效考核提供数据支持,帮助企业建立更加公正、透明的管理制度。
随着技术的不断发展和应用场景的不断拓展,睡岗识别系统将在更多领域发挥重要作用。未来,系统可进一步结合人体姿态估计、多摄像头联动及行为统计分析等先进技术,进一步提升系统的智能化和实用性。同时,系统也可以与现有的考勤系统、安全管理系统进行集成,形成更加全面的智能管理解决方案,为保障社会安全和生产效率提供更加有力的技术支撑。
部分源码
# -*- coding: utf-8 -*-
import time
from PyQt5.QtWidgets import QApplication , QMainWindow, QFileDialog, \
QMessageBox,QWidget,QHeaderView,QTableWidgetItem, QAbstractItemView
import sys
import os
from PIL import ImageFont
from ultralytics import YOLO
sys.path.append('UIProgram')
from UIProgram.UiMain import Ui_MainWindow
import sys
from PyQt5.QtCore import QTimer, Qt, QThread, pyqtSignal,QCoreApplication
import detect_tools as tools
import cv2
import Config
from UIProgram.QssLoader import QSSLoader
from UIProgram.precess_bar import ProgressBar
import numpy as np
# import torch
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(QMainWindow, self).__init__(parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.initMain()
self.signalconnect()
# 加载css渲染效果
style_file = 'UIProgram/style.css'
qssStyleSheet = QSSLoader.read_qss_file(style_file)
self.setStyleSheet(qssStyleSheet)
def signalconnect(self):
self.ui.PicBtn.clicked.connect(self.open_img)
self.ui.comboBox.activated.connect(self.combox_change)
self.ui.VideoBtn.clicked.connect(self.vedio_show)
self.ui.CapBtn.clicked.connect(self.camera_show)
self.ui.SaveBtn.clicked.connect(self.save_detect_video)
self.ui.ExitBtn.clicked.connect(QCoreApplication.quit)
self.ui.FilesBtn.clicked.connect(self.detact_batch_imgs)
def initMain(self):
self.show_width = 770
self.show_height = 480
self.org_path = None
self.is_camera_open = False
self.cap = None
# self.device = 0 if torch.cuda.is_available() else 'cpu'
# 加载检测模型
self.model = YOLO(Config.model_path, task='detect')
self.model(np.zeros((48, 48, 3))) #预先加载推理模型
self.fontC = ImageFont.truetype("Font/platech.ttf", 25, 0)
# 用于绘制不同颜色矩形框
self.colors = tools.Colors()
# 更新视频图像
self.timer_camera = QTimer()
# 更新检测信息表格
# self.timer_info = QTimer()
# 保存视频
self.timer_save_video = QTimer()
# 表格
self.ui.tableWidget.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)
self.ui.tableWidget.verticalHeader().setDefaultSectionSize(40)
self.ui.tableWidget.setColumnWidth(0, 80) # 设置列宽
self.ui.tableWidget.setColumnWidth(1, 200)
self.ui.tableWidget.setColumnWidth(2, 150)
self.ui.tableWidget.setColumnWidth(3, 90)
self.ui.tableWidget.setColumnWidth(4, 230)
# self.ui.tableWidget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) # 表格铺满
# self.ui.tableWidget.horizontalHeader().setSectionResizeMode(0, QHeaderView.Interactive)
# self.ui.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers) # 设置表格不可编辑
self.ui.tableWidget.setSelectionBehavior(QAbstractItemView.SelectRows) # 设置表格整行选中
self.ui.tableWidget.verticalHeader().setVisible(False) # 隐藏列标题
self.ui.tableWidget.setAlternatingRowColors(True) # 表格背景交替
# 设置主页背景图片border-image: url(:/icons/ui_imgs/icons/camera.png)
# self.setStyleSheet("#MainWindow{background-image:url(:/bgs/ui_imgs/bg3.jpg)}")
def open_img(self):
if self.cap:
# 打开图片前关闭摄像头
self.video_stop()
self.is_camera_open = False
self.ui.CaplineEdit.setText('摄像头未开启')
self.cap = None
# 弹出的窗口名称:'打开图片'
# 默认打开的目录:'./'
# 只能打开.jpg与.gif结尾的图片文件
# file_path, _ = QFileDialog.getOpenFileName(self.ui.centralwidget, '打开图片', './', "Image files (*.jpg *.gif)")
file_path, _ = QFileDialog.getOpenFileName(None, '打开图片', './', "Image files (*.jpg *.jepg *.png)")
if not file_path:
return
self.ui.comboBox.setDisabled(False)
self.org_path = file_path
self.org_img = tools.img_cvread(self.org_path)
# 目标检测
t1 = time.time()
self.results = self.model(self.org_path)[0]
t2 = time.time()
take_time_str = '{:.3f} s'.format(t2 - t1)
self.ui.time_lb.setText(take_time_str)
location_list = self.results.boxes.xyxy.tolist()
self.location_list = [list(map(int, e)) for e in location_list]
cls_list = self.results.boxes.cls.tolist()
self.cls_list = [int(i) for i in cls_list]
self.conf_list = self.results.boxes.conf.tolist()
self.conf_list = ['%.2f %%' % (each*100) for each in self.conf_list]
# now_img = self.cv_img.copy()
# for loacation, type_id, conf in zip(self.location_list, self.cls_list, self.conf_list):
# type_id = int(type_id)
# color = self.colors(int(type_id), True)
# # cv2.rectangle(now_img, (int(x1), int(y1)), (int(x2), int(y2)), colors(int(type_id), True), 3)
# now_img = tools.drawRectBox(now_img, loacation, Config.CH_names[type_id], self.fontC, color)
now_img = self.results.plot()
self.draw_img = now_img
# 获取缩放后的图片尺寸
self.img_width, self.img_height = self.get_resize_size(now_img)
resize_cvimg = cv2.resize(now_img,(self.img_width, self.img_height))
pix_img = tools.cvimg_to_qpiximg(resize_cvimg)
self.ui.label_show.setPixmap(pix_img)
self.ui.label_show.setAlignment(Qt.AlignCenter)
# 设置路径显示
self.ui.PiclineEdit.setText(self.org_path)
# 目标数目
target_nums = len(self.cls_list)
self.ui.label_nums.setText(str(target_nums))
# 设置目标选择下拉框
choose_list = ['全部']
target_names = [Config.names[id]+ '_'+ str(index) for index,id in enumerate(self.cls_list)]
# object_list = sorted(set(self.cls_list))
# for each in object_list:
# choose_list.append(Config.CH_names[each])
choose_list = choose_list + target_names
self.ui.comboBox.clear()
self.ui.comboBox.addItems(choose_list)
if target_nums >= 1:
self.ui.type_lb.setText(Config.CH_names[self.cls_list[0]])
self.ui.label_conf.setText(str(self.conf_list[0]))
# 默认显示第一个目标框坐标
# 设置坐标位置值
self.ui.label_xmin.setText(str(self.location_list[0][0]))
self.ui.label_ymin.setText(str(self.location_list[0][1]))
self.ui.label_xmax.setText(str(self.location_list[0][2]))
self.ui.label_ymax.setText(str(self.location_list[0][3]))
else:
self.ui.type_lb.setText('')
self.ui.label_conf.setText('')
self.ui.label_xmin.setText('')
self.ui.label_ymin.setText('')
self.ui.label_xmax.setText('')
self.ui.label_ymax.setText('')
# # 删除表格所有行
self.ui.tableWidget.setRowCount(0)
self.ui.tableWidget.clearContents()
self.tabel_info_show(self.location_list, self.cls_list, self.conf_list,path=self.org_path)
def detact_batch_imgs(self):
if self.cap:
# 打开图片前关闭摄像头
self.video_stop()
self.is_camera_open = False
self.ui.CaplineEdit.setText('摄像头未开启')
self.cap = None
directory = QFileDialog.getExistingDirectory(self,
"选取文件夹",
"./") # 起始路径
if not directory:
return
self.org_path = directory
img_suffix = ['jpg','png','jpeg','bmp']
for file_name in os.listdir(directory):
full_path = os.path.join(directory,file_name)
if os.path.isfile(full_path) and file_name.split('.')[-1].lower() in img_suffix:
# self.ui.comboBox.setDisabled(False)
img_path = full_path
self.org_img = tools.img_cvread(img_path)
# 目标检测
t1 = time.time()
self.results = self.model(img_path)[0]
t2 = time.time()
take_time_str = '{:.3f} s'.format(t2 - t1)
self.ui.time_lb.setText(take_time_str)
location_list = self.results.boxes.xyxy.tolist()
self.location_list = [list(map(int, e)) for e in location_list]
cls_list = self.results.boxes.cls.tolist()
self.cls_list = [int(i) for i in cls_list]
self.conf_list = self.results.boxes.conf.tolist()
self.conf_list = ['%.2f %%' % (each * 100) for each in self.conf_list]
now_img = self.results.plot()
self.draw_img = now_img
# 获取缩放后的图片尺寸
self.img_width, self.img_height = self.get_resize_size(now_img)
resize_cvimg = cv2.resize(now_img, (self.img_width, self.img_height))
pix_img = tools.cvimg_to_qpiximg(resize_cvimg)
self.ui.label_show.setPixmap(pix_img)
self.ui.label_show.setAlignment(Qt.AlignCenter)
# 设置路径显示
self.ui.PiclineEdit.setText(img_path)
# 目标数目
target_nums = len(self.cls_list)
self.ui.label_nums.setText(str(target_nums))
# 设置目标选择下拉框
choose_list = ['全部']
target_names = [Config.names[id] + '_' + str(index) for index, id in enumerate(self.cls_list)]
choose_list = choose_list + target_names
self.ui.comboBox.clear()
self.ui.comboBox.addItems(choose_list)
if target_nums >= 1:
self.ui.type_lb.setText(Config.CH_names[self.cls_list[0]])
self.ui.label_conf.setText(str(self.conf_list[0]))
# 默认显示第一个目标框坐标
# 设置坐标位置值
self.ui.label_xmin.setText(str(self.location_list[0][0]))
self.ui.label_ymin.setText(str(self.location_list[0][1]))
self.ui.label_xmax.setText(str(self.location_list[0][2]))
self.ui.label_ymax.setText(str(self.location_list[0][3]))
else:
self.ui.type_lb.setText('')
self.ui.label_conf.setText('')
self.ui.label_xmin.setText('')
self.ui.label_ymin.setText('')
self.ui.label_xmax.setText('')
self.ui.label_ymax.setText('')
# # 删除表格所有行
# self.ui.tableWidget.setRowCount(0)
# self.ui.tableWidget.clearContents()
self.tabel_info_show(self.location_list, self.cls_list, self.conf_list, path=img_path)
self.ui.tableWidget.scrollToBottom()
QApplication.processEvents() #刷新页面
def draw_rect_and_tabel(self, results, img):
now_img = img.copy()
location_list = results.boxes.xyxy.tolist()
self.location_list = [list(map(int, e)) for e in location_list]
cls_list = results.boxes.cls.tolist()
self.cls_list = [int(i) for i in cls_list]
self.conf_list = results.boxes.conf.tolist()
self.conf_list = ['%.2f %%' % (each * 100) for each in self.conf_list]
for loacation, type_id, conf in zip(self.location_list, self.cls_list, self.conf_list):
type_id = int(type_id)
color = self.colors(int(type_id), True)
# cv2.rectangle(now_img, (int(x1), int(y1)), (int(x2), int(y2)), colors(int(type_id), True), 3)
now_img = tools.drawRectBox(now_img, loacation, Config.CH_names[type_id], self.fontC, color)
# 获取缩放后的图片尺寸
self.img_width, self.img_height = self.get_resize_size(now_img)
resize_cvimg = cv2.resize(now_img, (self.img_width, self.img_height))
pix_img = tools.cvimg_to_qpiximg(resize_cvimg)
self.ui.label_show.setPixmap(pix_img)
self.ui.label_show.setAlignment(Qt.AlignCenter)
# 设置路径显示
self.ui.PiclineEdit.setText(self.org_path)
# 目标数目
target_nums = len(self.cls_list)
self.ui.label_nums.setText(str(target_nums))
if target_nums >= 1:
self.ui.type_lb.setText(Config.CH_names[self.cls_list[0]])
self.ui.label_conf.setText(str(self.conf_list[0]))
self.ui.label_xmin.setText(str(self.location_list[0][0]))
self.ui.label_ymin.setText(str(self.location_list[0][1]))
self.ui.label_xmax.setText(str(self.location_list[0][2]))
self.ui.label_ymax.setText(str(self.location_list[0][3]))
else:
self.ui.type_lb.setText('')
self.ui.label_conf.setText('')
self.ui.label_xmin.setText('')
self.ui.label_ymin.setText('')
self.ui.label_xmax.setText('')
self.ui.label_ymax.setText('')
# 删除表格所有行
self.ui.tableWidget.setRowCount(0)
self.ui.tableWidget.clearContents()
self.tabel_info_show(self.location_list, self.cls_list, self.conf_list, path=self.org_path)
return now_img
def get_resize_size(self, img):
_img = img.copy()
img_height, img_width , depth= _img.shape
ratio = img_width / img_height
if ratio >= self.show_width / self.show_height:
self.img_width = self.show_width
self.img_height = int(self.img_width / ratio)
else:
self.img_height = self.show_height
self.img_width = int(self.img_height * ratio)
return self.img_width, self.img_height
def save_detect_video(self):
if self.cap is None and not self.org_path:
QMessageBox.about(self, '提示', '当前没有可保存信息,请先打开图片或视频!')
return
if self.is_camera_open:
QMessageBox.about(self, '提示', '摄像头视频无法保存!')
return
if __name__ == "__main__":
app = QApplication(sys.argv)
win = MainWindow()
win.show()
sys.exit(app.exec_())
获取完整资源,请查看个人主页的个人简介
更多推荐
所有评论(0)