YOLOV8 + PYQT5单目测距
- 1. 相关配置
- 2. 测距源码
- 3. PYQT环境配置
- 4. 实验结果
- 4.1 界面
- 4.2 界面卡住解决方案
- 5. 实现效果
1. 相关配置
系统:win 10
YOLO版本:yolov8
拍摄视频设备:安卓手机
电脑显卡:NVIDIA 2080Ti(CPU也可以跑,GPU只是起到加速推理效果)
2. 测距源码
详见文章 YOLOv8跟踪分割+单目测距(python),下载源码后进入下一步
3. PYQT环境配置
首先安装一下pyqt5
pip install PyQt5
pip install PyQt5-tools
接着再pycharm设置里配置一下
添加下面两个工具:
工具1:Qt Designer
Program D:\Anaconda3\Lib\site-packages\qt5_applications\Qt\bin\designer.exe#代码所用环境路径
Arauments : $FileName$
Working directory :$FileDir$
工具2:PyUIC
Program D:\Anaconda3\Scripts\pyuic5.exe
Arguments : $FileName$ -o $FileNameWithoutExtension$.py
Working directory :$FileDir$
4. 实验结果
4.1 界面
创建一个main.py文件,将以下代码写入
import sys
import torch
import torchvision
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QLabel
from PyQt5 import QtCore, QtGui, QtWidgets
import cv2
from ultralytics import YOLO
from distance import person_distance,car_distance
class Ui_MainWindow(QMainWindow):
# global text_dis
def __init__(self):
super().__init__()
self.setupUi(self)
self.retranslateUi(self)
self.image_path = ''
self.label = QLabel(self)
self.label.setGeometry(50, 50, 200, 50)
# self.text_dis = None
# 创建一个QTextBrowser来显示变量值
self.text_browser = QtWidgets.QTextBrowser(self.centralwidget)
# 添加QTextBrowser到窗口的布局中
self.setCentralWidget(self.text_browser)
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1128, 1009)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(20, 10, 93, 28))
self.pushButton.setObjectName("pushButton")
self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_2.setGeometry(QtCore.QRect(160, 10, 93, 28))
self.pushButton_2.setObjectName("pushButton_2")
self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)
self.pushButton_3.setGeometry(QtCore.QRect(290, 10, 93, 28))
self.pushButton_3.setObjectName("pushButton_3")
self.label = QtWidgets.QTextBrowser(self.centralwidget)
self.label.setGeometry(QtCore.QRect(420, 10, 93, 28))
self.label.setObjectName("label")
self.label1 = QtWidgets.QTextBrowser(self.centralwidget)
self.label1.setGeometry(QtCore.QRect(20, 60, 1071, 71))
self.label1.setObjectName("label1")
self.label2 = QtWidgets.QLabel(self.centralwidget)
self.label2.setGeometry(QtCore.QRect(40, 190, 481, 421))
self.label2.setObjectName("label2")
self.label3 = QtWidgets.QLabel(self.centralwidget)
self.label3.setGeometry(QtCore.QRect(600, 200, 461, 381))
self.label3.setObjectName("label3")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 1128, 26))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
# 点击响应函数
self.pushButton.clicked.connect(self.uploadImage)
self.pushButton_2.clicked.connect(self.showEnvironment)
self.pushButton_3.clicked.connect(self.startProgram)
# self.image_path = ''
def retranslateUi(self, MainWindow):# 设置界面各个组件的文本内容。
# text_dis = ''
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "上传文件"))
self.pushButton_2.setText(_translate("MainWindow", "终止运行"))
self.pushButton_3.setText(_translate("MainWindow", "启动程序"))
# self.label.setText(_translate("MainWindow", "{}".format(text_dis)))
self.label2.setText(_translate("MainWindow", "CSDN:积极向上的Mr.d"))
self.label3.setText(_translate("MainWindow", "CSDN:积极向上的Mr.d"))
def showEnvironment(self): # 退出
sys.exit()
def uploadImage(self):
file_dialog = QFileDialog()
image_path, _ = file_dialog.getOpenFileName(self, '选择图片', '', 'Images (*.png *.xpm *.jpg *.bmp *.mp4)')
self.image_path = image_path
if image_path:
pixmap = QtGui.QPixmap(image_path)
self.label2.setPixmap(pixmap)
self.label2.setScaledContents(True)
# 加载图片的逻辑保持不变
# global text_dis
def startProgram(self):
text_dis_list = [] # 用于存储每次循环中的 text_dis 值
if self.image_path.endswith('.mp4'):
# 如果是视频文件,使用视频流而不是单个图像
cap = cv2.VideoCapture(self.image_path)
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = int(cap.get(cv2.CAP_PROP_FPS))
out = cv2.VideoWriter('result.mp4', cv2.VideoWriter_fourcc(*'mp4v'), fps, (frame_width, frame_height))
model = YOLO('yolov8n.pt')
while True:
ret, frame = cap.read()
if not ret:
break
# 对每一帧运行对象检测
results = model(frame)
annotated_frame = results[0].plot()
boxes = results[0].boxes.xywh.cpu()
for i, box in enumerate(boxes):
# for box, class_idx in zip(boxes, classes):
x_center, y_center, width, height = box.tolist()
x1 = x_center - width / 2
y1 = y_center - height / 2
x2 = x_center + width / 2
y2 = y_center + height / 2
h = y2 - y1
dis_m = person_distance(h)
text_dis_list.append(dis_m)
max_dis_m = min(text_dis_list)
# global text_dis
if max_dis_m < 2:
text_dis = '高风险'
elif max_dis_m > 5:
text_dis = '低风险'
else:
text_dis = '中风险'
# text_dis_list.append(text_dis)
self.label.setText(text_dis)
# 将检测结果写入输出视频流
out.write(annotated_frame)
# 将结果显示在label3中(可选)
rgb_annotated_frame = cv2.cvtColor(annotated_frame, cv2.COLOR_BGR2RGB)
# 使用QImage将RGB图像转换为Qt格式
height, width, channel = rgb_annotated_frame.shape
bytes_per_line = channel * width
q_img = QImage(rgb_annotated_frame.data, width, height, bytes_per_line, QImage.Format_RGB888)
# 将QImage转换为QPixmap并显示在label3中
pixmap = QPixmap.fromImage(q_img)
# pixmap = QtGui.QPixmap.fromImage(QtGui.QImage(annotated_frame.data, annotated_frame.shape[1], annotated_frame.shape[0], QtGui.QImage.Format_RGB888))
self.label3.setPixmap(pixmap)
self.label3.setScaledContents(True)
cv2.waitKey(1)
cap.release()
out.release()
else:
# 如果是单个图像文件,保持原始逻辑不变
self.label1.setText(self.image_path)
model = YOLO('yolov8n.pt')
results = model(self.image_path)
annotated_frame = results[0].plot()
boxes = results[0].boxes.xywh.cpu()
for i, box in enumerate(boxes):
# for box, class_idx in zip(boxes, classes):
x_center, y_center, width, height = box.tolist()
x1 = x_center - width / 2
y1 = y_center - height / 2
x2 = x_center + width / 2
y2 = y_center + height / 2
h = y2 - y1
dis_m = person_distance(h)
if dis_m < 2:
text_dis = '高风险'
elif dis_m > 5:
text_dis = '低风险'
else:
text_dis = '中风险'
self.label.setText(text_dis)
cv2.imwrite("result.jpg",annotated_frame)
pixmap = QtGui.QPixmap("result.jpg")
self.label3.setPixmap(pixmap)
self.label3.setScaledContents(True)
return text_dis
if __name__ == '__main__':
app = QApplication(sys.argv)
MainWindow1 = QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow1)
MainWindow1.show()
sys.exit(app.exec_())
4.2 界面卡住解决方案
如果点击图片检测或者视频检测按钮卡住,大概律师代码中间出现了错误,这时候是看不到报错的,具体可以把以下这个功能打开,这样就可以看到报错
5. 实现效果
显示界面
检测图片
检测视频
工程源码下载:YOLOV8 + PYQT5单目测距(风险类别检测)
解压密码:csdn:mr.d
文章内容后续会慢慢完善…