我正在使用带有Qt库的python3构建我的Gui(pyqt5)。
在主Gui中,我有一个标签,可以在其中放置图像,还有一个listWidget
,其中应包含作为图标的项目,还有一个lineEdit
,它以流的源为内容,还有一个按钮来启动我的应用。
我的目标是现场直播和实时分析。
为此,我使用QThread
更新了GUI,并进行了多处理以进行分析。
这是我的代码:
class Stream(QThread):
change_image_signal = pyqtSignal(QImage)
def __init__(self, src, queue):
QThread.__init__(self)
self.stream = cv2.VideoCapture(src)
self.queue = queue
def run(self):
frame_shift = 5
frames_per_sec = 10
sleep_time = 1 / frames_per_sec
frame_count = 0
while self.stream.isOpened():
ret, frame = self.stream.read()
frame_count += 1
if not ret:
break
rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
if frame_count % (frame_shift + 1) == 0:
self.queue.put(rgb_image)
qt_format_image = QImage(rgb_image.data, rgb_image.shape[1], rgb_image.shape[0], 3 * rgb_image.shape[1],
QImage.Format_RGB888)
image = qt_format_image.scaled(400, 400)
self.change_image_signal.emit(image)
time.sleep(sleep_time)
class ThreadToListWidget(QThread):
append_item_signal = pyqtSignal(QImage)
def __init__(self, analyze_queue):
QThread.__init__(self)
self.analyze_queue = analyze_queue
def run(self):
while True:
frame = self.analyze_queue.get()
if frame is None:
break
qt_format_image = QImage(frame.data, frame.shape[1], frame.shape[0], 3 * frame.shape[1],
QImage.Format_RGB888)
image = qt_format_image.scaled(300, 300)
self.append_item_signal.emit(image)
class AnalyzeProcess(multiprocessing.Process):
def __init__(self, queue, analyze_queue):
multiprocessing.Process.__init__(self)
self.queue = queue
self.analyze_queue = analyze_queue
def run(self):
while True:
frame = self.queue.get()
...
do analyzing to the frame
...
self.analyze_queue.put(frame)
self.analyze_queue.put(None)
class MyGui(QWidget):
def __init__(self):
QWidget.__init__(self)
...
my widgets:
line_edit
image_label
list_widget
button
...
self.button.clicked.connect(self.start)
def start(self):
queue = multiprocessing.Queue()
analyze_queue = multiprocessing.Queue()
self.stream_thread = Stream(self.line_edit.text(), queue)
self.stream_thread.change_image_signal.connect(self.change_image)
self.list_widget_thread = ThreadToListWidget(analyze_queue)
self.list_widget_thread.append_item_signal.connect(self.append_item)
self.analyze_process = AnalyzeProcess(queue, analyze_queue)
self.stream_thread.start()
self.analyze_process.start()
self.list_widget_thread.start()
def change_image(self, image):
self.image_label.setPixmap(QPixmap.fromImage(image))
def append_item(self, image):
pix = QPixmap.fromImage(image)
icon = QIcon(pix)
item = QListWidgetItem()
item.setIcon(icon)
self.list_widget.addItem(item)
self.repaint()
if __name__ == 'main':
app = QApplication(sys.argv)
gui = MyGui()
gui.show()
app.exec_()
我的问题是,当我在列表小部件中添加该项目时,标签上显示的实时流式传输会冻结一秒钟。
谁能告诉我代码中有什么问题以及是否由于更新gui的函数之间没有同步而导致此问题?!
答案 0 :(得分:0)
尝试将time.sleep(sleep_time)
更改为QThread.msleep(10)
import sys
import cv2
import multiprocessing
#import time
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class Stream(QThread):
change_image_signal = pyqtSignal(QImage)
def __init__(self, src, queue):
QThread.__init__(self)
self.stream = cv2.VideoCapture(src)
self.queue = queue
def run(self):
frame_shift = 5
# frames_per_sec = 10
# sleep_time = 1 / frames_per_sec
frame_count = 0
while self.stream.isOpened():
ret, frame = self.stream.read()
frame_count += 1
if not ret:
break
rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
if frame_count % (frame_shift + 1) == 0:
self.queue.put(rgb_image)
qt_format_image = QImage(rgb_image.data, rgb_image.shape[1], rgb_image.shape[0], 3 * rgb_image.shape[1],
QImage.Format_RGB888)
image = qt_format_image.scaled(400, 400)
self.change_image_signal.emit(image)
# time.sleep(sleep_time) # ---
QThread.msleep(10) # +++
class ThreadToListWidget(QThread):
append_item_signal = pyqtSignal(QImage)
def __init__(self, analyze_queue):
QThread.__init__(self)
self.analyze_queue = analyze_queue
def run(self):
while True:
frame = self.analyze_queue.get()
if frame is None:
break
qt_format_image = QImage(frame.data, frame.shape[1], frame.shape[0], 3 * frame.shape[1],
QImage.Format_RGB888)
image = qt_format_image.scaled(300, 300)
self.append_item_signal.emit(image)
class AnalyzeProcess(multiprocessing.Process):
def __init__(self, queue, analyze_queue):
multiprocessing.Process.__init__(self)
self.queue = queue
self.analyze_queue = analyze_queue
def run(self):
while True:
frame = self.queue.get()
#...
# "do analyzing to the frame"
#...
self.analyze_queue.put(frame)
self.analyze_queue.put(None)
class MyGui(QWidget):
def __init__(self):
super().__init__()
#...
# my widgets:
self.line_edit = QLineEdit("D:/_Qt/_PyQt/_Qt/Python-Examples/_PyQt5/Player/Samonastrojka.avi")
self.image_label = QLabel()
self.list_widget = QListWidget()
# self.list_widget.resize(420, 300)
self.list_widget.setFrameShape(self.list_widget.NoFrame)
self.list_widget.setFlow(self.list_widget.LeftToRight)
self.list_widget.setWrapping(True)
self.list_widget.setResizeMode(self.list_widget.Adjust)
self.button = QPushButton("button")
grid = QGridLayout(self)
grid.addWidget(self.line_edit, 0, 0, 1, 2)
grid.addWidget(self.image_label, 1, 0)
grid.addWidget(self.list_widget, 1, 1)
grid.addWidget(self.button, 2, 0, 1, 2)
#...
self.button.clicked.connect(self.start)
def start(self):
queue = multiprocessing.Queue()
analyze_queue = multiprocessing.Queue()
self.stream_thread = Stream(self.line_edit.text(), queue)
self.stream_thread.change_image_signal.connect(self.change_image)
self.list_widget_thread = ThreadToListWidget(analyze_queue)
self.list_widget_thread.append_item_signal.connect(self.append_item)
self.analyze_process = AnalyzeProcess(queue, analyze_queue)
self.stream_thread.start()
self.analyze_process.start()
self.list_widget_thread.start()
def change_image(self, image):
self.image_label.setPixmap(QPixmap.fromImage(image))
def append_item(self, image):
self.list_widget.setIconSize(QSize(70, 70))
pix = QPixmap.fromImage(image)
icon = QIcon(pix.scaled(70, 70, Qt.IgnoreAspectRatio, Qt.SmoothTransformation))
item = QListWidgetItem()
item.setIcon(icon)
self.list_widget.insertItem(0, item)
self.repaint()
if __name__ == '__main__':
app = QApplication(sys.argv)
gui = MyGui()
gui.resize(830, 480)
gui.show()
sys.exit(app.exec_())