我正在使用pyqt5将openCV 3.0与Qt5在Python 3.4.3中集成。我一直在尝试构建一个应用程序来处理来自文件的视频,但是遇到了pyqt的麻烦。具体来说,我将多次通过文件对话框加载视频,这些视频的大小不一样。因此,我希望我的应用程序中的主窗口包装/扩展到正在播放的视频的大小。
下面是我的代码的简化版本,其中包含用于显示视频的3个核心类。一个用于主窗口,一个用于框架查看器窗口小部件以显示GUI中的每个视频帧,一个用于视频处理器通过opencv读取和处理视频,将其转换为QImage然后将其发送给查看器。
class videoProcessor(QtCore.QObject):
filename = None
cap = None
videoSignal = QtCore.pyqtSignal(QtGui.QImage)
def __init__(self):
super().__init__()
self.filename = "test.mp4"
@QtCore.pyqtSlot()
def runVideoProcessor(self):
self.cap = cv2.VideoCapture(self.filename)
while self.cap.isOpened():
ret, frame = self.cap.read()
if ret:
outimg = cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)
imgh, imgw, bytesPerComponent = outimg.shape
bytesPerLine = bytesPerComponent * imgw;
qtimg = QtGui.QImage(outimg.data,imgw,imgh,bytesPerLine,QtGui.QImage.Format_RGB888)
self.videoSignal.emit(qtimg)
else:
break
self.cap.release()
class frameViewer(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.image = QtGui.QImage()
self.imageAvailable = False
def paintEvent(self,event):
painter = QtGui.QPainter(self)
painter.drawImage(0,0,self.image)
self.image = QtGui.QImage()
painter.end()
@QtCore.pyqtSlot(QtGui.QImage)
def setFrame(self,image):
self.image = image
self.setFixedSize(self.image.size())
self.repaint()
class mainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.fview = frameViewer()
self.vproc = videoProcessor()
self.vproc.videoSignal.connect(self.fview.setFrame)
self.startButton = QtWidgets.QPushButton("Start")
self.startButton.clicked.connect(self.vproc.runVideoProcessor)
self.mainLayout = QtWidgets.QVBoxLayout()
self.mainLayout.addWidget(self.fview)
self.mainLayout.addWidget(self.startButton)
self.mainWidget = QtWidgets.QWidget()
self.mainWidget.setLayout(self.mainLayout)
self.mainWidget.setSizePolicy(QtWidgets.QSizePolicy.Expanding,QtWidgets.QSizePolicy.Expanding)
self.setCentralWidget(self.mainWidget)
self.statusBar().showMessage('Ready')
self.setGeometry(50, 50, 300, 300)
self.setWindowTitle('OpenCV PyQt Test')
self.show()
if __name__=='__main__':
app = QtWidgets.QApplication(sys.argv)
mw = mainWindow()
sys.exit(app.exec_())
到目前为止,该程序可以运行视频,但有两个主要问题:
self.image=QtGui.QImage()
中设置paintEvent
,程序崩溃。但是,如果我将该行放入视频末尾,则窗口将变为空白,因为每当窗口更新时,将在最后一帧的位置绘制空QImage
。有关如何解决这些问题的任何想法?谢谢。