我正在使用下面的代码。
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 生成的类,但必须将其导入到主脚本中,在这种情况下,您必须使用 pyuic5 your_design.ui -o gui.py -x
再次生成 .py .
如果显示opencv框架的窗口不是由opencv创建的,则不应使用waitKey(),因为它不会处理键盘事件,也就是说,如果窗口是由X技术生成的,并且opencv仅用于获取图像对于某些设备,X 技术必须处理键盘事件。在本例中,该技术就是 Qt。
the docs中指出了这一点:
Note: The function only works if there is at least one HighGUI window created and the window is active. If there are several HighGUI windows, any of them can be active.
另一方面,读取帧的任务不会消耗太多时间,因此您不应该使用 while True,因为它会阻塞 GUI 的事件循环,但计时器就足够了(在 Qt 的情况下,您必须使用一个 QTimer)。
考虑到上述情况,解决方案是:
├── gui.py
└── main.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_())
关于python - 如何在 qt 应用程序上使用 cv2.waitKey 使用 'p' 键暂停和播放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61254040/