当前位置: 首页 > news >正文

基于YOLOv8深度学习+Pyqt5的电动车头盔佩戴检测系统

wx供重浩:创享日记
对话框发送:225头盔
获取完整源码源文件+已标注的数据集(1463张)+源码各文件说明+配置跑通说明文档
若需要一对一远程操作在你电脑跑通,有偿59yuan


效果展示

基于YOLOv8深度学习+PyQT5的电动车头盔佩戴检测系统

在这里插入图片描述

各文件说明

在这里插入图片描述


随着电动车的普及,交通安全问题日益凸显。头盔作为保护骑行者头部安全的重要装备,其佩戴情况的监测对于减少交通事故伤害具有重要意义。本文提出了一种基于YOLOv8(You Only Look Once version 8)的电动车头盔佩戴检测系统,旨在实时监测并提醒骑行者佩戴头盔。该系统利用深度学习技术,通过训练YOLOv8模型来识别电动车骑行者是否佩戴头盔,并在检测到未佩戴头盔的情况下发出警报。系统设计考虑了实时性、准确性和用户友好性,为提升电动车骑行安全提供了一种有效的技术解决方案。

电动车作为一种便捷的交通工具,在城市交通中扮演着越来越重要的角色。然而,由于缺乏必要的安全措施,电动车事故频发,尤其是头部伤害,往往导致严重后果。头盔的正确佩戴可以有效降低头部受伤的风险。因此,开发一种能够实时监测头盔佩戴情况的系统,对于提高骑行者的安全意识和减少交通事故具有重要作用。

YOLOv8是YOLO系列目标检测模型的最新版本,它在前代模型的基础上进行了优化,提高了检测速度和准确性。YOLOv8采用了多尺度特征图的融合、更精细的锚点框设计以及更有效的损失函数,使得模型在处理复杂场景时表现出色。

系统设计
数据集准备
为了训练YOLOv8模型,首先需要收集和标注一个包含大量电动车骑行者图像的数据集。数据集应包含各种天气条件、不同光照环境以及多种头盔类型。图像标注需要指出头盔的位置和类别,以便模型学习区分佩戴头盔与否。

模型训练
使用准备好的数据集,对YOLOv8模型进行训练。训练过程中,需要调整学习率、批大小、训练周期等超参数,以获得最佳的检测效果。同时,可以采用数据增强技术,如随机裁剪、旋转、颜色变换等,以提高模型的泛化能力。

系统实现
系统的核心是YOLOv8模型,它负责从输入的实时视频流中检测头盔。系统还包括一个用户界面,用于显示检测结果和发出警报。当模型检测到未佩戴头盔的骑行者时,系统会通过声音或视觉信号提醒用户。

实时检测
为了实现实时检测,系统需要能够在低延迟的情况下处理视频流。这要求模型不仅要准确,还要高效。在实际部署中,可能需要在边缘设备上进行模型推理,以减少对中心服务器的依赖。

结果与讨论
在测试集上,YOLOv8模型展现出了较高的头盔检测准确率。在不同的场景和光照条件下,模型均能稳定地识别出佩戴和未佩戴头盔的骑行者。然而,模型在处理遮挡严重或头盔与骑行者头部颜色相近的情况下仍有改进空间。

结论
本文提出的基于YOLOv8的电动车头盔佩戴检测系统,能够有效地提高电动车骑行者的安全意识。通过实时监测和提醒,该系统有助于减少因未佩戴头盔导致的交通事故伤害。未来的工作将集中在进一步提高模型的鲁棒性,以及探索更高效的模型部署方案。


软件系统部分源码

# -*- 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 torchclass 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 = 770self.show_height = 480self.org_path = Noneself.is_camera_open = Falseself.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 = Falseself.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:returnself.ui.comboBox.setDisabled(False)self.org_path = file_pathself.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_namesself.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 = Falseself.ui.CaplineEdit.setText('摄像头未开启')self.cap = Nonedirectory = QFileDialog.getExistingDirectory(self,"选取文件夹","./")  # 起始路径if not  directory:returnself.org_path = directoryimg_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_pathself.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_namesself.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_imgdef combox_change(self):com_text = self.ui.comboBox.currentText()if com_text == '全部':cur_box = self.location_listcur_img = self.results.plot()self.ui.type_lb.setText(Config.CH_names[self.cls_list[0]])self.ui.label_conf.setText(str(self.conf_list[0]))else:index = int(com_text.split('_')[-1])cur_box = [self.location_list[index]]cur_img = self.results[index].plot()self.ui.type_lb.setText(Config.CH_names[self.cls_list[index]])self.ui.label_conf.setText(str(self.conf_list[index]))# 设置坐标位置值self.ui.label_xmin.setText(str(cur_box[0][0]))self.ui.label_ymin.setText(str(cur_box[0][1]))self.ui.label_xmax.setText(str(cur_box[0][2]))self.ui.label_ymax.setText(str(cur_box[0][3]))resize_cvimg = cv2.resize(cur_img, (self.img_width, self.img_height))pix_img = tools.cvimg_to_qpiximg(resize_cvimg)self.ui.label_show.clear()self.ui.label_show.setPixmap(pix_img)self.ui.label_show.setAlignment(Qt.AlignCenter)def get_video_path(self):file_path, _ = QFileDialog.getOpenFileName(None, '打开视频', './', "Image files (*.avi *.mp4 *.jepg *.png)")if not file_path:return Noneself.org_path = file_pathself.ui.VideolineEdit.setText(file_path)return file_pathdef video_start(self):# 删除表格所有行self.ui.tableWidget.setRowCount(0)self.ui.tableWidget.clearContents()# 清空下拉框self.ui.comboBox.clear()# 定时器开启,每隔一段时间,读取一帧self.timer_camera.start(1)self.timer_camera.timeout.connect(self.open_frame)def tabel_info_show(self, locations, clses, confs, path=None):path = pathfor location, cls, conf in zip(locations, clses, confs):row_count = self.ui.tableWidget.rowCount()  # 返回当前行数(尾部)self.ui.tableWidget.insertRow(row_count)  # 尾部插入一行item_id = QTableWidgetItem(str(row_count+1))  # 序号item_id.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)  # 设置文本居中item_path = QTableWidgetItem(str(path))  # 路径# item_path.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)item_cls = QTableWidgetItem(str(Config.CH_names[cls]))item_cls.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)  # 设置文本居中item_conf = QTableWidgetItem(str(conf))item_conf.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)  # 设置文本居中item_location = QTableWidgetItem(str(location)) # 目标框位置# item_location.setTextAlignment(Qt.AlignHCenter | Qt.AlignVCenter)  # 设置文本居中self.ui.tableWidget.setItem(row_count, 0, item_id)self.ui.tableWidget.setItem(row_count, 1, item_path)self.ui.tableWidget.setItem(row_count, 2, item_cls)self.ui.tableWidget.setItem(row_count, 3, item_conf)self.ui.tableWidget.setItem(row_count, 4, item_location)self.ui.tableWidget.scrollToBottom()def video_stop(self):self.cap.release()self.timer_camera.stop()# self.timer_info.stop()def open_frame(self):ret, now_img = self.cap.read()if ret:# 目标检测t1 = time.time()results = self.model(now_img)[0]t2 = time.time()take_time_str = '{:.3f} s'.format(t2 - t1)self.ui.time_lb.setText(take_time_str)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]now_img = results.plot()# 获取缩放后的图片尺寸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)# 目标数目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_namesself.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)else:self.cap.release()self.timer_camera.stop()def vedio_show(self):if self.is_camera_open:self.is_camera_open = Falseself.ui.CaplineEdit.setText('摄像头未开启')video_path = self.get_video_path()if not video_path:return Noneself.cap = cv2.VideoCapture(video_path)self.video_start()self.ui.comboBox.setDisabled(True)def camera_show(self):self.is_camera_open = not self.is_camera_openif self.is_camera_open:self.ui.CaplineEdit.setText('摄像头开启')self.cap = cv2.VideoCapture(0)self.video_start()self.ui.comboBox.setDisabled(True)else:self.ui.CaplineEdit.setText('摄像头未开启')self.ui.label_show.setText('')if self.cap:self.cap.release()cv2.destroyAllWindows()self.ui.label_show.clear()def get_resize_size(self, img):_img = img.copy()img_height, img_width , depth= _img.shaperatio = img_width / img_heightif ratio >= self.show_width / self.show_height:self.img_width = self.show_widthself.img_height = int(self.img_width / ratio)else:self.img_height = self.show_heightself.img_width = int(self.img_height * ratio)return self.img_width, self.img_heightdef save_detect_video(self):if self.cap is None and not self.org_path:QMessageBox.about(self, '提示', '当前没有可保存信息,请先打开图片或视频!')returnif self.is_camera_open:QMessageBox.about(self, '提示', '摄像头视频无法保存!')returnif self.cap:res = QMessageBox.information(self, '提示', '保存视频检测结果可能需要较长时间,请确认是否继续保存?',QMessageBox.Yes | QMessageBox.No ,  QMessageBox.Yes)if res == QMessageBox.Yes:self.video_stop()com_text = self.ui.comboBox.currentText()self.btn2Thread_object = btn2Thread(self.org_path, self.model, com_text)self.btn2Thread_object.start()self.btn2Thread_object.update_ui_signal.connect(self.update_process_bar)else:returnelse:if os.path.isfile(self.org_path):fileName = os.path.basename(self.org_path)name , end_name= fileName.rsplit(".",1)save_name = name + '_detect_result.' + end_namesave_img_path = os.path.join(Config.save_path, save_name)# 保存图片cv2.imwrite(save_img_path, self.draw_img)QMessageBox.about(self, '提示', '图片保存成功!\n文件路径:{}'.format(save_img_path))else:img_suffix = ['jpg', 'png', 'jpeg', 'bmp']for file_name in os.listdir(self.org_path):full_path = os.path.join(self.org_path, file_name)if os.path.isfile(full_path) and file_name.split('.')[-1].lower() in img_suffix:name, end_name = file_name.rsplit(".",1)save_name = name + '_detect_result.' + end_namesave_img_path = os.path.join(Config.save_path, save_name)results = self.model(full_path)[0]now_img = results.plot()# 保存图片cv2.imwrite(save_img_path, now_img)QMessageBox.about(self, '提示', '图片保存成功!\n文件路径:{}'.format(Config.save_path))def update_process_bar(self,cur_num, total):if cur_num == 1:self.progress_bar = ProgressBar(self)self.progress_bar.show()if cur_num >= total:self.progress_bar.close()QMessageBox.about(self, '提示', '视频保存成功!\n文件在{}目录下'.format(Config.save_path))returnif self.progress_bar.isVisible() is False:# 点击取消保存时,终止进程self.btn2Thread_object.stop()returnvalue = int(cur_num / total *100)self.progress_bar.setValue(cur_num, total, value)QApplication.processEvents()class btn2Thread(QThread):"""进行检测后的视频保存"""# 声明一个信号update_ui_signal = pyqtSignal(int,int)def __init__(self, path, model, com_text):super(btn2Thread, self).__init__()self.org_path = pathself.model = modelself.com_text = com_text# 用于绘制不同颜色矩形框self.colors = tools.Colors()self.is_running = True  # 标志位,表示线程是否正在运行def run(self):# VideoCapture方法是cv2库提供的读取视频方法cap = cv2.VideoCapture(self.org_path)# 设置需要保存视频的格式“xvid”# 该参数是MPEG-4编码类型,文件名后缀为.avifourcc = cv2.VideoWriter_fourcc(*'XVID')# 设置视频帧频fps = cap.get(cv2.CAP_PROP_FPS)# 设置视频大小size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))# VideoWriter方法是cv2库提供的保存视频方法# 按照设置的格式来out输出fileName = os.path.basename(self.org_path)name, end_name = fileName.split('.')save_name = name + '_detect_result.avi'save_video_path = os.path.join(Config.save_path, save_name)out = cv2.VideoWriter(save_video_path, fourcc, fps, size)prop = cv2.CAP_PROP_FRAME_COUNTtotal = int(cap.get(prop))print("[INFO] 视频总帧数:{}".format(total))cur_num = 0# 确定视频打开并循环读取while (cap.isOpened() and self.is_running):cur_num += 1print('当前第{}帧,总帧数{}'.format(cur_num, total))# 逐帧读取,ret返回布尔值# 参数ret为True 或者False,代表有没有读取到图片# frame表示截取到一帧的图片ret, frame = cap.read()if ret == True:# 检测results = self.model(frame)[0]frame = results.plot()out.write(frame)self.update_ui_signal.emit(cur_num, total)else:break# 释放资源cap.release()out.release()def stop(self):self.is_running = Falseif __name__ == "__main__":app = QApplication(sys.argv)win = MainWindow()win.show()sys.exit(app.exec_())

相关文章:

基于YOLOv8深度学习+Pyqt5的电动车头盔佩戴检测系统

wx供重浩:创享日记 对话框发送:225头盔 获取完整源码源文件已标注的数据集(1463张)源码各文件说明配置跑通说明文档 若需要一对一远程操作在你电脑跑通,有偿59yuan 效果展示 基于YOLOv8深度学习PyQT5的电动车头盔佩戴检…...

【数据结构】B树,B+树,B*树

文章目录 一、B树1.B树的定义2.B树的插入3.B树的中序遍历 二、B树和B*树1.B树的定义2.B树的插入3.B*树的定义4.B树系列总结 三、B树与B树的应用 一、B树 1.B树的定义 1. 在内存中搜索效率高的数据结构有AVL树,红黑树,哈希表等,但这是在内存…...

常用实验室器皿耐硝酸盐酸进口PFA材质容量瓶螺纹盖密封效果好

PFA容量瓶规格参考:10ml、25ml、50ml、100ml、250ml、500ml、1000ml。 别名可溶性聚四氟乙烯容量瓶、特氟龙容量瓶。常用于ICP-MS、ICP-OES等痕量分析以及同位素分析等实验,也可在地质、电子化学品、半导体分析测试、疾控中心、制药厂、环境检测中心等机…...

【kubernetes】二进制部署k8s集群之cni网络插件flannel和calico工作原理

k8s集群的三种接口 k8s集群有三大接口: CRI:容器进行时接口,连接容器引擎--docker、containerd、cri-o、podman CNI:容器网络接口,用于连接网络插件如:flannel、calico、cilium CSI:容器存储…...

Pycharm一直打不开,无任何报错

我windows安装了pycharm一直打不开(无论专业版还是社区版都打不开),无任何弹窗,无任何报错 最后解决问题: 查看环境变量PYCHARM_VM_OPTIONS 发现有一个环境变量PYCHARM_VM_OPTIONS 删除PYCHARM_VM_OPTIONS这个环境变量,pycharm终…...

用html编写的小广告板

用html编写的小广告板 相关代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</tit…...

hive中如何取交集并集和差集

交集 要获取两个表的交集&#xff0c;你可以使用INNER JOIN或者JOIN&#xff1a; SELECT * FROM table1 JOIN table2 ON table1.column_name table2.column_name;也可以使用 INTERSECT 关键字 SELECT * FROM table1 INTERSECT SELECT * FROM table2;并集 要获取两个表的并集…...

2024.2.26

今天又复习了一下熟悉的C语言 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> #include<windows.h>int main() {//数组初始化int n;scanf("%d", &n);int array[500];int i 0;for (i 0; i < n; i){scanf("%…...

【kubernetes】关于k8s集群的声明式管理资源

目录 一、声明式管理方法 二、资源配置清单管理 1、导出资源配置清单 2、修改资源配置清单并应用 2.1离线修改 2.2在线修改 三、通过资源配置清单创建资源对象 获取K8S资源配置清单文件模板&#xff1f; 关于配置清单常见的字段 方案一&#xff1a;手写yaml配置文件 …...

8.openEuler操作系统网络管理和防火墙(二)

openEuler OECA认证辅导,标红的文字为学习重点和考点。 如果需要做实验,建议安装麒麟信安、银河麒麟、统信等具有图形化的操作系统,其安装与openeuler基本一致。 3.通过IP命令配置网络 配置IP地址: 使用ip命令为接口配置地址,命令格式如下,其中 interface-name 为网卡名…...

1904_ARM Cortex M系列芯片特性小结

1904_ARM Cortex M系列芯片特性小结 全部学习汇总&#xff1a; g_arm_cores: ARM内核的学习笔记 (gitee.com) ARM Cortex M系列的MCU用过好几款了&#xff0c;也涉及到了不同的内核。不过&#xff0c;关于这些内核的基本的特性还是有些不了解。从ARM的官方网站上找来了一个对比…...

热闹元宵进行中,如何利用VR全景展示民宿品牌形象?

错峰出游闹元宵&#xff0c;元宵节恰逢周末&#xff0c;而且还是春节假期返工之后的首个休息日&#xff0c;不少人都想通过短途度假来缓解“节后综合征”。两位数的特价机票、打折的各种酒店让你实现“旅行自由”&#xff0c;那么如何知道特价酒店服务好不好呢&#xff1f;先别…...

css3实现无缝滚动,鼠标经过暂停

js也可以实现&#xff0c;但css3更加的平滑和资源占用更少。下面是具体代码&#xff0c;动画要单独用一个类名&#xff0c;否则暂停估计不会生效&#xff1a; 原理&#xff1a;动画向上移动&#xff0c;目标完全消失后&#xff0c;从头开始&#xff0c;注意 动画移动高度是文本…...

SpringCache缓存专题

SpringCache缓存专题 学习目标 1、理解缓存存在的意义 2、掌握redis与SpringCache的集成方式 3、掌握SpringCache注解的使用 4、掌握项目集成SpringCache流程 第一章 基于SpringCache缓存方案 1.为什么需要缓存 ​ 前台请求&#xff0c;后台先从缓存中取数据&#xff0…...

Doris实战——结合Flink构建极速易用的实时数仓

目录 一、实时数仓的需求与挑战 二、构建极速易用的实时数仓架构 三、解决方案 3.1 如何实现数据的增量与全量同步 3.1.1 增量及全量数据同步 3.1.2 数据一致性保证 3.1.3 DDL 和 DML 同步 Light Schema Change Flink CDC DML 和DDL同步 3.2 如何基于Flink实现多种数…...

阿里开源低代码引擎 - Low-Code Engine

阿里开源低代码引擎 - Low-Code Engine 本文主要介绍如何在Windows运行/开发阿里开源低代码引擎 - Low-Code Engine 详细文档参见【 阿里开源低代码引擎 - Low-Code Engine 官方文档】 目录 阿里开源低代码引擎 - Low-Code Engine一、环境准备1、使用 WSL 在 Windows 上安装 L…...

2024-02-23(Spark)

1.RDD的数据是过程数据 RDD之间进行相互迭代计算&#xff08;Transaction的转换&#xff09;&#xff0c;当执行开启后&#xff0c;代表老RDD的消失 RDD的数据是过程数据&#xff0c;只在处理的过程中存在&#xff0c;一旦处理完成&#xff0c;就不见了。 这个特性可以最大化…...

【JavaSE】实用类——枚举类型、包装类、数学类

目录 Java API枚举优势代码示例 包装类作用包装类和基本数据类型的对应关系包装类的构造方法包装类的常用方法装箱和拆箱 留一个问题大家猜猜看包装类的特点 Math类Random类代码示例 Java API Java API(Java Application Programming Interface) 即Java应用程序编程接口&#…...

Qt中常见的JS类和函数(二): 全局对象

相关系列文章 Qt中字符串转换为JS的函数执行 Qt中常见的JS类和函数(一): 全局对象 Qt中常见的JS类和函数(二): 全局对象 目录 2.3.构造函数属性 2.3.1.Object 2.3.2.Function 2.3.3.Array 2.3.4.ArrayBuffer 2.3.5.String 2.3.6.Boolean 2.3.7.Number 2.3.8.DataView …...

mysql 安装 与 使用

1.安装地址&#xff08;社区免费版本&#xff09; https://dev.mysql.com/downloads/mysql/ 2.查看端口 ****是否被占用&#xff08;例子 3306端口&#xff09; netstat -an | find "3306" 3.配置环境 系统变量名 变量名&#xff1a;MYSQL_HOME 变量值&#…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…...

基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解

JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用&#xff0c;结合SQLite数据库实现联系人管理功能&#xff0c;并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能&#xff0c;同时可以最小化到系统…...