[英]How to pause and play with 'p' key using cv2.waitKey on qt application
我正在使用下面的代碼。
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(640, 480)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.label = QtWidgets.QLabel(self.centralwidget)
self.label.setGeometry(QtCore.QRect(10, 10, 500, 300))
self.label.setText("")
self.label.setObjectName("label")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(50, 400, 75, 23))
self.pushButton.setObjectName("pushButton")
MainWindow.setCentralWidget(self.centralwidget)
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.play)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "PushButton"))
def play(self):
cap = cv2.VideoCapture('vtest.asf')
while True:
ret, show = cap.read()
key = cv2.waitKey(1) & 0xFF
if ret:
rgbImage = cv2.cvtColor(show, cv2.COLOR_BGR2RGB)
image = QImage(rgbImage.data, show.shape[1], show.shape[0], show.strides[0], QImage.Format_RGB888)
l = self.label.setPixmap(QPixmap.fromImage(image).scaled(500, 300, Qt.IgnoreAspectRatio))
if key == ord('p'):
cv2.waitKey(0)
elif key == ord('q'):
break
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
它逐幀顯示,但當我使用“p”鍵盤鍵時它不會暫停,它不起作用。 請讓我知道這是正確的方法。 請告訴我解決方案。 編輯的代碼。
不要修改由 Qt Designer 生成的 class 但您必須將其導入主腳本,在這種情況下您必須使用pyuic5 your_design.ui -o gui.py -x
再次生成 the.py。
You should not use waitKey() if the window that shows the opencv frame is not created by opencv since it will not handle keyboard events, that is, if the window is generated by X technology and opencv only serves to obtain the image from some device那么 X 技術必須處理鍵盤事件。 在這種情況下,該技術是 Qt。
文檔中指出了這一點:
注意: function 僅在至少創建了一個 HighGUI window 並且 window 處於活動狀態時才有效。 如果有多個 HighGUI windows,任何一個都可以激活。
另一方面,讀取幀的任務不會消耗太多時間,因此您不應該使用 while True,因為它會阻塞 GUI 的事件循環,但計時器就足夠了(在 Qt 的情況下,您必須使用 QTimer) .
考慮到上述情況,解決方案是:
├── gui.py
└── main.py
主文件
from gui import Ui_MainWindow
from PyQt5 import QtCore, QtGui, QtWidgets
import cv2
class CameraManager(QtCore.QObject):
frameChanged = QtCore.pyqtSignal(QtGui.QImage)
def __init__(self, parent=None):
super().__init__(parent)
self._capture = None
self._interval = 30
self._timer = QtCore.QTimer(
self, interval=self._interval, timeout=self._on_timeout
)
@property
def capture(self):
return self._capture
@capture.setter
def capture(self, c):
is_active = self._timer.isActive()
if is_active:
self._timer.stop()
if self.capture is not None:
self.capture.release()
self._capture = c
if is_active:
self._timer.start()
@property
def interval(self):
return self._interval
@interval.setter
def interval(self, t):
is_active = self._timer.isActive()
if is_active:
self._timer.stop()
self._timer.setInterval(t)
if is_active:
self._timer.start()
@property
def is_active(self):
return self._timer.isActive() and self.capture is not None
@QtCore.pyqtSlot()
def start(self):
self._timer.start()
@QtCore.pyqtSlot()
def stop(self):
self._timer.stop()
@QtCore.pyqtSlot()
def _on_timeout(self):
if self.capture is None:
return
ret, frame = self.capture.read()
if ret:
# https://stackoverflow.com/a/55468544/6622587
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
h, w, ch = frame.shape
bytesPerLine = ch * w
qImg = QtGui.QImage(
frame.data, w, h, bytesPerLine, QtGui.QImage.Format_RGB888
)
self.frameChanged.emit(qImg)
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
self.camera_manager = CameraManager()
self.camera_manager.frameChanged.connect(self.on_frame_changed)
self.camera_manager.capture = cv2.VideoCapture("vtest.asf")
self.pushButton.clicked.connect(self.camera_manager.start)
QtWidgets.QShortcut(
QtGui.QKeySequence(QtCore.Qt.Key_P), self, activated=self.on_p_pressed
)
@QtCore.pyqtSlot(QtGui.QImage)
def on_frame_changed(self, image):
pixmap = QtGui.QPixmap.fromImage(image)
self.label.setPixmap(pixmap)
@QtCore.pyqtSlot()
def on_p_pressed(self):
if self.camera_manager.is_active:
self.camera_manager.stop()
else:
self.camera_manager.start()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.