界面开发
开发主窗口界面
from PyQt5 import QtWidgets
from PyQt5 import QtCore,QtGui
import sys
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
self.toolbar()
def initUI(self):
menubar = self.menuBar()
file_menu = menubar.addMenu('文件')
open_action = QtWidgets.QAction('打开', self)
file_menu.addAction(open_action)
save_action = QtWidgets.QAction('保存', self)
file_menu.addAction(save_action)
open_action.triggered.connect(self.click_word_file)
self.setWindowTitle("人脸识别系统")
from main_panel import Mean_tool_demo
self.myPanel = Mean_tool_demo()
self.setCentralWidget(self.myPanel)
self.setMinimumSize(900,720)
def toolbar(self):
toolbal = QtWidgets.QToolBar("快捷窗口")
self.addToolBar(toolbal)
cricle_btn = QtWidgets.QAction("画圆",self)
cricle_btn.setStatusTip("画圆")
cricle_btn.setShortcut("Ctrl+C")
cricle_btn.triggered.connect(self.print_c)
toolbal.addAction(cricle_btn)
def print_c(self):
print(111111)
def click_word_file(self):
fileinfo = QtWidgets.QFileDialog.getOpenFileName(self,"打开文件",".","Image files(*.jpg *.png *.bmp)")
file_name = fileinfo[0]
if file_name != '':
self.myPanel.image_path = file_name
self.myPanel.image_path_label.setText("当前图像路径:"+file_name)
new_pixmap = QtGui.QPixmap(file_name)
pix = new_pixmap.scaled(QtCore.QSize(800,800),QtCore.Qt.KeepAspectRatio)
self.myPanel.image_label.setAlignment(QtCore.Qt.AlignCenter)
self.myPanel.image_label.setPixmap(pix)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
main_win = MainWindow()
main_win.setStyleSheet("background - color: lightblue;")
main_win.show()
app.exec_()
pannel界面展示
from PyQt5 import QtWidgets
from PyQt5 import QtCore,QtGui
import sys
import os,time
import cv2
from threading import Thread
os.environ['KMP_DUPLICATE_LIB_OK']='True'
from ultralytics import YOLO
from table_view import Mydata_model
head1 = ["序号","文件路径","目标编号","类别","置信度","位置坐标"]
data1 = [['示例:1',15,15,4,8,1]]
class Mean_tool_demo(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.root_path = self.root_path()
self.count = 1
self.image_ = []
self.yolo_things = []
self.cute_image_ = []
self.run_type_control = -1
self.yolo_model = YOLO('./pyqt5_YOLO_model/yolov3-tinyu.pt')
self.image_save_path = None
self.image_path = f'D:\\images\\car.png'
all_vbox = QtWidgets.QVBoxLayout()
all_vbox.addWidget(self.header_format())
all_vbox.addWidget(self.down_format())
all_vbox.addStretch(1)
self.setLayout(all_vbox)
def root_path(self):
name = "exp_1"
path = "./pyqt5_YOLO_model/data"
for root,dir,files in os.walk(path):
if root == path :
file_path = os.path.join(root,name)
if not os.path.exists(file_path):
os.mkdir(file_path)
else:
n = len(dir)
file_path = os.path.join(root,f"exp_{n+1}")
if not os.path.exists(file_path):
os.mkdir(file_path)
return file_path
def header_format(self):
self.image_label = QtWidgets.QLabel()
image = cv2.imread(self.image_path)
image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
h,w,c = image.shape
img = QtGui.QImage(image.data,w,h,w*3,QtGui.QImage.Format_RGB888)
pixmap = QtGui.QPixmap(img)
pix = pixmap.scaled(QtCore.QSize(600,600),QtCore.Qt.KeepAspectRatio)
self.image_label.setPixmap(pix)
self.image_label.setAlignment(QtCore.Qt.AlignCenter)
self.image_label2 = QtWidgets.QLabel()
image1 = cv2.imread(self.image_path)
image1 = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
h,w,c = image1.shape
img1 = QtGui.QImage(image1.data,w,h,w*3,QtGui.QImage.Format_RGB888)
pixmap1 = QtGui.QPixmap(img1)
pix1 = pixmap1.scaled(QtCore.QSize(600,600),QtCore.Qt.KeepAspectRatio)
self.image_label2.setPixmap(pix1)
self.image_label2.setAlignment(QtCore.Qt.AlignCenter)
btnPane1 = QtWidgets.QGroupBox("原图像")
hbox = QtWidgets.QHBoxLayout()
hbox.addWidget(self.image_label)
btnPane1.setLayout(hbox)
btnPane2 = QtWidgets.QGroupBox("YOLO处理后图像")
hbox1 = QtWidgets.QHBoxLayout()
hbox1.addWidget(self.image_label2)
btnPane2.setLayout(hbox1)
btnPane3 = QtWidgets.QGroupBox("图像界面显示器")
hbox2 = QtWidgets.QHBoxLayout()
hbox2.addWidget(btnPane1)
hbox2.addWidget(btnPane2)
btnPane3.setLayout(hbox2)
return btnPane3
def left_down_format(self):
self.table_layout = QtWidgets.QTableView()
self.model = Mydata_model(data1,head1)
self.table_layout.setModel(self.model)
self.table_layout.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.table_layout.horizontalHeader().setVisible(True)
self.table_layout.verticalHeader().setVisible(True)
self.table_layout.resizeColumnsToContents()
self.table_layout.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
self.table_layout.horizontalHeader().setVisible(True)
self.table_layout.verticalHeader().setVisible(True)
self.table_layout.resizeColumnsToContents()
header = self.table_layout.horizontalHeader()
header.setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
header.setStyleSheet("background-color:black;color:red")
self.table_layout.setSelectionBehavior(QtWidgets.QTableView.SelectRows)
self.table_layout.setSelectionMode(QtWidgets.QTableWidget.SingleSelection)
self.table_layout.setMinimumSize(500,500)
table_view_window = QtWidgets.QGroupBox("表格显示框")
vbox = QtWidgets.QVBoxLayout()
vbox.addWidget(self.table_layout)
table_view_window.setLayout(vbox)
return table_view_window
def righr_down_format(self):
font = QtGui.QFont()
font.setPointSize(10)
font.setBold(True)
btn1_open_image = QtWidgets.QPushButton("🧩打开图像")
btn1_open_image.setFixedSize(150,50)
btn1_open_image.setFont(font)
btn1_open_image.clicked.connect(self.click_button_image_file)
btn1_open_image.setStyleSheet("background-color:orgian;color:white")
btn2_open_video = QtWidgets.QPushButton("📽️打开视频")
btn2_open_video.setFixedSize(150,50)
btn2_open_video.setFont(font)
btn2_open_video.clicked.connect(self.click_button_video_file)
btn2_open_video.setStyleSheet("background-color:orgian;color:white")
btn3_open_came = QtWidgets.QPushButton("📽️打开摄像头")
btn3_open_came.setFixedSize(150,50)
btn3_open_came.setFont(font)
btn3_open_came.clicked.connect(self.click_button_camera)
btn3_open_came.setStyleSheet("background-color:orgian;color:white")
btn4_cute_image = QtWidgets.QPushButton("📂图像解析")
btn4_cute_image.setFixedSize(150,50)
btn4_cute_image.setFont(font)
btn4_cute_image.setStyleSheet("background-color:orgian;color:white")
btn4_cute_image.clicked.connect(self.click_button_cute_image)
btn5_save_image = QtWidgets.QPushButton("📴保存文件")
btn5_save_image.setFixedSize(150,50)
btn5_save_image.setFont(font)
btn5_save_image.setStyleSheet("background-color:orgian;color:white")
btn5_save_image.clicked.connect(self.click_button_save_image)
btn6_close = QtWidgets.QPushButton("❎退出")
btn6_close.setFixedSize(150,50)
btn6_close.setFont(font)
btn6_close.clicked.connect(self.click_button_close)
btn6_close.setStyleSheet("background-color:orgian;color:white")
title1 = QtWidgets.QWidget()
hboxlayouott1 = QtWidgets.QHBoxLayout()
hboxlayouott1.addWidget(btn1_open_image)
hboxlayouott1.addWidget(btn2_open_video)
title1.setLayout(hboxlayouott1)
title2 = QtWidgets.QWidget()
hboxlayouott2 = QtWidgets.QHBoxLayout()
hboxlayouott2.addWidget(btn3_open_came)
hboxlayouott2.addWidget(btn4_cute_image)
title2.setLayout(hboxlayouott2)
title3 = QtWidgets.QWidget()
hboxlayouott3 = QtWidgets.QHBoxLayout()
hboxlayouott3.addWidget(btn5_save_image)
hboxlayouott3.addWidget(btn6_close)
title3.setLayout(hboxlayouott3)
title4 = QtWidgets.QGroupBox("操作")
vboxlayouott = QtWidgets.QVBoxLayout()
vboxlayouott.addWidget(title1)
vboxlayouott.addWidget(title2)
vboxlayouott.addWidget(title3)
title4.setLayout(vboxlayouott)
return title4
def down_format(self):
btnPane3 = QtWidgets.QWidget()
hboxlayouott = QtWidgets.QHBoxLayout()
hboxlayouott.addWidget(self.left_down_format())
hboxlayouott.addWidget(self.righr_down_format())
btnPane3.setLayout(hboxlayouott)
return btnPane3
def on_select_row(self):
QtWidgets.QMessageBox.information(self,"提示","当前行数为:"+str(self.table_layout.currentIndex().row()))
print(self.table_layout.currentIndex())
pass
def click_button_save_image(self):
self.model.save_table_data(self.root_path)
def click_button_image_file(self):
self.run_type_control = 1
self.image_.clear()
path = "./pyqt5_YOLO_model"
fileinfo = QtWidgets.QFileDialog.getOpenFileName(self,"打开文件",path,"Image files(*.jpg *.png *.bmp)")
file_name = fileinfo[0]
if file_name != '':
image = cv2.imread(file_name)
image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
image = cv2.resize(image,(300,300))
self.image_.append(image)
h,w,c = image.shape
img = QtGui.QImage(image.data,w,h,w*3,QtGui.QImage.Format_RGB888)
new_pixmap = QtGui.QPixmap(img)
pix = new_pixmap.scaled(QtCore.QSize(300,300),QtCore.Qt.KeepAspectRatio)
self.image_label.setAlignment(QtCore.Qt.AlignCenter)
self.image_label.setPixmap(pix)
else:
QtWidgets.QMessageBox.warning(self,"提示","未选择文件")
return
def click_button_video_file(self):
path = "./pyqt5_YOLO_model"
self.run_type_control = 2
fileinfo = QtWidgets.QFileDialog.getOpenFileName(self,"打开视频文件",path,"视频文件(*.mp4)")
file_name = fileinfo[0]
if file_name != '':
self.capture = cv2.VideoCapture(file_name)
self.timer_id = QtCore.QTimer()
self.timer_id.timeout.connect(self.play_video)
self.timer_id.start(50)
else:
QtWidgets.QMessageBox.warning(self,"提示","未选择文件")
return
def click_button_camera(self):
self.run_type_control = 3
self.capture = cv2.VideoCapture(0,cv2.CAP_DSHOW)
if not self.capture.isOpened():
QtWidgets.QMessageBox.warning(self,"提示","摄像头打开失败")
exit()
else:
self.capture = cv2.VideoCapture(0,cv2.CAP_DSHOW)
self.timer_id = QtCore.QTimer()
self.timer_id.timeout.connect(self.play_video)
self.timer_id.start(50)
def play_video(self):
self.image_.clear()
index ,frame = self.capture.read()
if not index:
self.timer_id.stop()
return
frame = cv2.resize(frame,(300,300))
frame = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
h,w,c = frame.shape
img = QtGui.QImage(frame.data,w,h,w*3,QtGui.QImage.Format_RGB888)
new_pixmap = QtGui.QPixmap(img)
pix = new_pixmap.scaled(QtCore.QSize(300,300),QtCore.Qt.KeepAspectRatio)
self.image_label.setAlignment(QtCore.Qt.AlignCenter)
self.image_label.setPixmap(pix)
if not self.image_ :
self.image_.append(frame)
def click_button_cute_image(self):
if self.run_type_control == 1:
frame = self.image_.pop(0)
frame1 = self.yolo_model(frame)[0]
frame = frame1.plot(line_width = 1)
frame = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
h,w,c = frame.shape
img = QtGui.QImage(frame.data,w,h,w*3,QtGui.QImage.Format_RGB888)
new_pixmap = QtGui.QPixmap(img)
pix = new_pixmap.scaled(QtCore.QSize(300,300),QtCore.Qt.KeepAspectRatio)
self.image_label2.setAlignment(QtCore.Qt.AlignCenter)
self.image_label2.setPixmap(pix)
frame = cv2.cvtColor(frame,cv2.COLOR_RGB2BGR)
path = os.path.join(self.root_path,"{}.jpg".format(self.count))
cv2.imwrite(path,frame)
self.count +=1
self.yolo_things.append(frame1[0].boxes.data)
self.save_tingeg()
elif self.run_type_control == 2 or self.run_type_control == 3:
Thread(target=self.cute_video,daemon=True).start()
Thread(target=self.save_csv_data_slot,daemon=True).start()
Thread(target=self.save_tingeg,daemon=True).start()
def cute_video(self):
while True:
if not self.image_:
continue
else:
frame = self.image_.pop(0)
frame1 = self.yolo_model(frame)[0]
frame = frame1.plot(line_width = 1)
frame = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
h,w,c = frame.shape
img = QtGui.QImage(frame.data,w,h,w*3,QtGui.QImage.Format_RGB888)
new_pixmap = QtGui.QPixmap(img)
pix = new_pixmap.scaled(QtCore.QSize(300,300),QtCore.Qt.KeepAspectRatio)
self.image_label2.setAlignment(QtCore.Qt.AlignCenter)
self.image_label2.setPixmap(pix)
if not self.cute_image_ or not self.yolo_things:
frame = cv2.cvtColor(frame,cv2.COLOR_RGB2BGR)
self.cute_image_.append(frame)
self.yolo_things.append(frame1[0].boxes.data)
def save_csv_data_slot(self):
while True:
if not self.cute_image_:
time.sleep(0.5)
continue
else:
path = os.path.join(self.root_path,"{}.jpg".format(self.count))
cv2.imwrite(path,self.cute_image_.pop(0))
self.count +=1
time.sleep(1)
def save_tingeg(self):
if self.run_type_control == 1:
path = os.path.join(self.root_path,"{}.csv".format(self.count))
person = 1
re = self.model.add_new_record(self.count,path,person,self.yolo_things.pop(0))
if re == 2:
self.on_first_table()
else:
while True:
if not self.yolo_things:
time.sleep(0.5)
continue
else:
path = os.path.join(self.root_path,"{}.csv".format(self.count))
person = 1
re = self.model.add_new_record(self.count,path,person,self.yolo_things.pop(0))
if re == 2:
self.on_first_table()
time.sleep(1)
def on_first_table(self):
self.model = Mydata_model(data1,head1)
self.table_layout.setModel(self.model)
head = self.table_layout.horizontalHeader()
head.setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
def click_button_close(self):
print("释放线程")
self.timer_id.stop()
self.capture.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
main_win = MainWindow()
main_win.show()
app.exec_()
Table界面独立开发,将panel与table进行分离开发,降低后期运维成本
from PyQt5 import QtWidgets
from PyQt5 import QtCore,QtGui
import sys
from PyQt5.QtCore import Qt
import os
import csv,time
import sys
sys.path.append("./pyqt5_YOLO_model")
class Mydata_model(QtCore.QAbstractTableModel):
def __init__(self,data,head):
super(Mydata_model,self).__init__()
self._data = data
self._head = head
def data(self,index,role):
if role == Qt.DisplayRole:
if isinstance(self._data[index.row()][index.column()],int):
return str(self._data[index.row()][index.column()])
return self._data[index.row()][index.column()]
if role == Qt.TextAlignmentRole:
if isinstance(self._data[index.row()][index.column()],int):
return Qt.AlignCenter+Qt.AlignLeft
if isinstance(self._data[index.row()][index.column()],str):
return Qt.AlignCenter
if role == Qt.BackgroundRole and index.column() == 2:
return QtGui.QColor('deeppink')
if role == Qt.ForegroundRole and index.column() == 2:
return QtGui.QColor('yellow')
if role == Qt.DecorationRole and index.column() == 0:
return QtGui.QIcon('check-icon.png')
def rowCount(self, index):
return len(self._data)
def columnCount(self, index):
if len(self._data ) == 0:
return 0
return len(self._head)
def headerData(self, section:int, orientation:Qt.Orientation, role: int=...):
if role == Qt.DisplayRole:
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self._head[section]
if role == Qt.DisplayRole and orientation == Qt.Vertical:
return str(section+1)
def add_new_record(self,count,path,person,data):
person = person
data = data.to('cpu').numpy()[0].tolist()
loc = data[0:4]
index = count
image_path = path
record = data[4]
self._data.append([index,image_path,person,person,record,loc])
return 2
def delete_row(self,row_list):
pass
return num
def save_table_data(self,path):
file_path = os.path.join(path,f"1.csv")
with open(file_path,'w',encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow(self._head)
for row in self._data:
writer.writerow(row)
最终界面展示
主要实现的功能,将image、video、camea数据传入后,进行数据的双屏幕显示,左边屏幕为原图像数据,右边图像为yolo模型处理后的数据。对图像进行实时处理,将结果在页面table中进行实时展示。当点击保存文件时,将Gui界面数据保存到本地创建的文件夹中。