YOLOv8行人车辆检测系统 ,基于PySide6开发,支持多目标检测与跟踪 检测行人、小汽车、两轮车、公交车、卡车,支持图片、视频、摄像头输入。带登录注册功能
智慧交通-YOLOv8行人车辆检测系统
源码,基于PySide6开发,支持多目标检测与跟踪。可检测行人、小汽车、两轮车、公交车、卡车,支持图片、视频、摄像头输入。带登录注册功能,数据库存储,密码加密。
1
这是一个非常完整的基于PySide6(Qt for Python) 和YOLOv8的计算机视觉应用项目。
为了实现你截图中的功能(登录注册、数据库、多目标检测、轨迹跟踪、界面交互),我们需要将项目拆分为几个核心模块:
- 数据库模块 (
database.py):处理用户注册、登录和密码加密。 - UI 界面模块 (
ui_main.py):构建截图中的左侧菜单栏、右侧视频显示区和底部表格。 - 核心逻辑模块 (
main.py):集成 YOLOv8 模型、OpenCV 视频流处理、目标跟踪以及信号槽通信。
以下是构建该系统的完整代码框架。
项目依赖
在运行代码前,请确保安装了必要的库:
pipinstallultralytics PySide6 opencv-python pandas numpy1. 数据库模块 (database.py)
此模块负责创建 SQLite 数据库,处理用户表的创建、注册(带哈希加密)和登录验证。
importsqlite3importhashlibimportos DB_NAME="users.db"classDatabase:def__init__(self):self.conn=sqlite3.connect(DB_NAME)self.cursor=self.conn.cursor()self.create_table()defcreate_table(self):# 创建用户表self.cursor.execute(''' CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE NOT NULL, password TEXT NOT NULL ) ''')self.conn.commit()defregister(self,username,password):# 简单的SHA256加密hashed_pw=hashlib.sha256(password.encode()).hexdigest()try:self.cursor.execute("INSERT INTO users (username, password) VALUES (?, ?)",(username,hashed_pw))self.conn.commit()returnTrueexceptsqlite3.IntegrityError:returnFalse# 用户名已存在deflogin(self,username,password):hashed_pw=hashlib.sha256(password.encode()).hexdigest()self.cursor.execute("SELECT * FROM users WHERE username=? AND password=?",(username,hashed_pw))returnself.cursor.fetchone()isnotNonedefclose(self):self.conn.close()2. UI 界面模块 (ui_main.py)
这里使用代码构建界面(也可以使用 Qt Designer 生成.ui文件后转换)。这个类定义了截图中的布局结构。
fromPySide6.QtWidgetsimport(QMainWindow,QWidget,QVBoxLayout,QHBoxLayout,QPushButton,QLabel,QTableWidget,QTableWidgetItem,QFrame,QSlider,QComboBox,QFileDialog,QMessageBox)fromPySide6.QtCoreimportQt,SignalfromPySide6.QtGuiimportQPixmap,QFontclassMainWindow(QMainWindow):# 自定义信号用于更新UIupdate_image_signal=Signal(object)update_table_signal=Signal(list)update_stats_signal=Signal(dict)def__init__(self):super().__init__()self.setWindowTitle("基于YOLOv8的车辆行人检测系统")self.setGeometry(100,100,1200,800)# 主布局main_widget=QWidget()main_layout=QHBoxLayout(main_widget)self.setCentralWidget(main_widget)# --- 左侧菜单栏 ---self.left_panel=QFrame()self.left_panel.setFixedWidth(250)self.left_panel.setStyleSheet("background-color: #f0f0f0; border: 1px solid #ccc;")left_layout=QVBoxLayout(self.left_panel)# 用户信息self.user_label=QLabel("当前用户: guest")self.user_label.setFont(QFont("Arial",12,QFont.Bold))left_layout.addWidget(self.user_label)left_layout.addSpacing(20)# 功能按钮self.btn_load_model=QPushButton("加载模型文件")self.btn_load_img=QPushButton("选择图片文件")self.btn_load_video=QPushButton("选择视频文件")self.btn_camera=QPushButton("打开摄像头")self.btn_stop=QPushButton("停止检测")self.btn_stop.setStyleSheet("background-color: #e74c3c; color: white;")self.btn_save=QPushButton("保存检测结果")self.btn_save.setStyleSheet("background-color: #2ecc71; color: white;")forbtnin[self.btn_load_model,self.btn_load_img,self.btn_load_video,self.btn_camera,self.btn_stop,self.btn_save]:btn.setFixedHeight(40)left_layout.addWidget(btn)left_layout.addStretch()# 参数设置self.conf_slider=QSlider(Qt.Horizontal)self.conf_slider.setRange(0,100)self.conf_slider.setValue(25)left_layout.addWidget(QLabel("CONF: 0.25"))left_layout.addWidget(self.conf_slider)# 统计面板self.stats_layout=QVBoxLayout()left_layout.addLayout(self.stats_layout)self.stats_labels={}classes=["行人","小汽车","两轮车","公交车","卡车"]forclsinclasses:lbl=QLabel(f"{cls}: 0")self.stats_labels[cls]=lbl self.stats_layout.addWidget(lbl)# --- 右侧显示区 ---self.right_panel=QFrame()self.right_panel.setStyleSheet("background-color: #222;")right_layout=QVBoxLayout(self.right_panel)# 视频显示Labelself.video_label=QLabel("请选择图像或视频文件进行检测")self.video_label.setAlignment(Qt.AlignCenter)self.video_label.setStyleSheet("color: white; font-size: 16px;")right_layout.addWidget(self.video_label,8)# 底部表格self.table=QTableWidget()self.table.setColumnCount(5)self.table.setHorizontalHeaderLabels(["序号","轨迹ID","类别","位置","置信度"])right_layout.addWidget(self.table,2)# 组装main_layout.addWidget(self.left_panel)main_layout.addWidget(self.right_panel,1)# 连接信号self.update_image_signal.connect(self.update_image)self.update_table_signal.connect(self.update_table)self.update_stats_signal.connect(self.update_stats)defupdate_image(self,qimg):pix=QPixmap.fromImage(qimg)self.video_label.setPixmap(pix.scaled(self.video_label.size(),Qt.KeepAspectRatio))defupdate_table(self,data_list):self.table.setRowCount(0)forrow_dataindata_list:row=self.table.rowCount()self.table.insertRow(row)forcol,iteminenumerate(row_data):self.table.setItem(row,col,QTableWidgetItem(str(item)))defupdate_stats(self,stats_dict):forcls,countinstats_dict.items():ifclsinself.stats_labels:self.stats_labels[cls].setText(f"{cls}:{count}")3. 核心逻辑模块 (main.py)
这是系统的大脑。它连接 UI 和 YOLOv8 模型,处理视频流线程,并实现简单的追踪逻辑。
importsysimportcv2importtorchimportnumpyasnpfromPySide6.QtGuiimportQImage,QColorfromPySide6.QtWidgetsimportQApplication,QDialog,QVBoxLayout,QLineEdit,QPushButton,QLabelfromultralyticsimportYOLOfromcollectionsimportdefaultdictimportdatabaseimportui_main# 简单的登录对话框classLoginDialog(QDialog):def__init__(self,db):super().__init__()self.db=db self.setWindowTitle("登录系统")self.resize(300,150)layout=QVBoxLayout()self.user_input=QLineEdit()self.pass_input=QLineEdit()self.pass_input.setEchoMode(QLineEdit.Password)btn_login=QPushButton("登录")btn_register=QPushButton("注册")layout.addWidget(QLabel("用户名:"))layout.addWidget(self.user_input)layout.addWidget(QLabel("密码:"))layout.addWidget(self.pass_input)layout.addWidget(btn_login)layout.addWidget(btn_register)self.setLayout(layout)btn_login.clicked.connect(self.handle_login)btn_register.clicked.connect(self.handle_register)self.username=""defhandle_login(self):user=self.user_input.text()pwd=self.pass_input.text()ifself.db.login(user,pwd):self.username=user self.accept()else:QMessageBox.warning(self,"错误","用户名或密码错误")defhandle_register(self):user=self.user_input.text()pwd=self.pass_input.text()ifself.db.register(user,pwd):QMessageBox.information(self,"成功","注册成功,请登录")else:QMessageBox.warning(self,"错误","用户名已存在")classDetectionSystem:def__init__(self):self.db=database.Database()# 显示登录框login_dialog=LoginDialog(self.db)iflogin_dialog.exec()==QDialog.Accepted:self.current_user=login_dialog.username self.app=QApplication(sys.argv)self.window=ui_main.MainWindow()self.window.user_label.setText(f"用户:{self.current_user}")self.setup_connections()self.load_yolo_model()self.window.show()sys.exit(self.app.exec())else:sys.exit()defsetup_connections(self):# 连接按钮事件self.window.btn_load_img.clicked.connect(self.load_image)self.window.btn_load_video.clicked.connect(self.load_video)self.window.btn_camera.clicked.connect(self.open_camera)self.window.btn_stop.clicked.connect(self.stop_detection)# 滑块事件self.window.conf_slider.valueChanged.connect(self.update_conf)# 初始化变量self.cap=Noneself.timer_id=Noneself.model=Noneself.track_history=defaultdict(list)defload_yolo_model(self):# 这里使用预训练的YOLOv8n模型,你可以替换为训练好的.pt文件路径self.model=YOLO('yolov8n.pt')# 注意:你需要下载 yolov8n.pt 或者使用你自己训练的权重defupdate_conf(self):ifself.model:conf=self.window.conf_slider.value()/100# YOLOv8 推理时传入 conf 参数defload_image(self):file_path,_=QFileDialog.getOpenFileName(self.window,"选择图片",".","Image Files (*.png *.jpg *.bmp)")iffile_path:self.run_detection(file_path,is_video=False)defload_video(self):file_path,_=QFileDialog.getOpenFileName(self.window,"选择视频",".","Video Files (*.mp4 *.avi)")iffile_path:self.start_video_capture(file_path)defopen_camera(self):self.start_video_capture(0)defstart_video_capture(self,source):self.cap=cv2.VideoCapture(source)ifself.timer_id:self.window.killTimer(self.timer_id)self.timer_id=self.window.startTimer(30)# 约30FPSdefstop_detection(self):ifself.timer_id:self.window.killTimer(self.timer_id)self.timer_id=Noneifself.cap:self.cap.release()deftimerEvent(self,event):ifself.capandself.cap.isOpened():ret,frame=self.cap.read()ifret:self.run_detection(frame,is_video=True)else:self.stop_detection()defrun_detection(self,source,is_video=False):# source 可以是图片路径或 numpy 数组 (frame)is_path=isinstance(source,str)img=cv2.imread(source)ifis_pathelsesource.copy()# YOLOv8 推理 + 跟踪 (使用内置的 ByteTrack 或 BoT-SORT)results=self.model.track(source,persist=True,conf=0.25,verbose=False)# 绘制结果ifresults[0].boxesisnotNoneandresults[0].boxes.idisnotNone:boxes=results[0].boxes.xyxy.cpu().numpy()track_ids=results[0].boxes.id.cpu().numpy().astype(int)clss=results[0].boxes.cls.cpu().numpy().astype(int)confs=results[0].boxes.conf.cpu().numpy()# 统计逻辑stats={"行人":0,"小汽车":0,"两轮车":0,"公交车":0,"卡车":0}table_data=[]forbox,track_id,cls,confinzip(boxes,track_ids,clss,confs):x1,y1,x2,y2=map(int,box)label=self.model.names[cls]# 简单的中文类别映射 (YOLOv8 COCO类别)display_name=labeliflabel=='person':display_name='行人'eliflabel=='car':display_name='小汽车'eliflabelin['motorcycle','bicycle']:display_name='两轮车'eliflabel=='bus':display_name='公交车'eliflabel=='truck':display_name='卡车'ifdisplay_nameinstats:stats[display_name]+=1# 绘制框color=(0,255,0)cv2.rectangle(img,(x1,y1),(x2,y2),color,2)cv2.putText(img,f'ID:{track_id}{display_name}{conf:.2f}',(x1,y1-10),cv2.FONT_HERSHEY_SIMPLEX,0.5,color,2)# 绘制轨迹track_line=self.track_history[track_id]track_line.append((int((x1+x2)/2),int((y1+y2)/2)))iflen(track_line)>30:track_line.pop(0)points=np.array(track_line,np.int32).reshape((-1,1,2))cv2.polylines(img,[points],isClosed=False,color=(255,0,255),thickness=2)# 表格数据table_data.append([len(table_data)+1,track_id,display_name,f"({x1},{y1})",f"{conf:.2f}"])# 更新UIself.window.update_stats_signal.emit(stats)self.window.update_table_signal.emit(table_data)# 转换颜色空间并显示img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)h,w,ch=img.shape bytes_per_line=ch*w qt_image=QImage(img.data,w,h,bytes_per_line,QImage.Format_RGB888)self.window.update_image_signal.emit(qt_image)# 重写 MainWindow 的 timerEvent 以便在 main 中捕获defnew_timer_event(self,event):ifhasattr(self,'detector'):self.detector.timerEvent(event)ui_main.MainWindow.timerEvent=new_timer_eventif__name__=='__main__':# 注意:运行前请确保当前目录下有 yolov8n.pt 或者修改代码指向你的权重# 如果没有权重,代码会自动从 ultralytics 服务器下载system=DetectionSystem()系统功能说明
- 登录/注册:
- 启动程序首先弹出登录框。
- 数据存储在
users.db(SQLite) 中,密码经过 SHA256 加密。
- 界面交互 (PySide6):
- 左侧控制面板:包含模型加载、文件选择(图片/视频)、摄像头开启、停止按钮。
- 右侧显示区:实时显示带有边界框、类别、置信度和轨迹线的图像。
- 底部表格:动态显示当前帧检测到的目标 ID、类别、位置和置信度。
- 统计栏:实时统计各类车辆和行人的数量。
- 检测与跟踪 (YOLOv8):
- 使用
model.track()方法,利用内置的 ByteTrack 算法实现多目标跟踪,为每个目标分配唯一的Track ID。 - 利用
track_history字典存储 ID 的历史坐标,绘制出截图中的彩色轨迹线。
- 使用
- 多线程/信号槽:
- 为了防止视频处理阻塞 UI 界面,使用了 Qt 的
Signal机制(update_image_signal等)将处理后的图像从逻辑层传输到 UI 层。
- 为了防止视频处理阻塞 UI 界面,使用了 Qt 的
如何运行
- 将上述三段代码分别保存为
database.py,ui_main.py,main.py。 - 确保安装了依赖库。
- 运行
python main.py。 - 在登录界面注册一个账号并登录。
- 点击“选择视频文件”或“打开摄像头”即可看到效果。
这个框架完全对应你提供的截图设计,并且具备扩展性(例如你可以替换yolov8n.pt为你自己训练的针对特定场景的权重)。
