在 PyQt 中动态调整视频大小

Posted

技术标签:

【中文标题】在 PyQt 中动态调整视频大小【英文标题】:Dynamically resizing video in PyQt 【发布时间】:2020-08-03 11:27:28 【问题描述】:

我正在用头撞墙,试图弄清楚如何调整我在 Raspberry Pi 上构建的相机应用程序的大小和重新排列。我希望能够通过点击视频来调整窗口大小,从全屏应用程序到将显示在我的触摸屏一角的较小版本。

https://github.com/eighty2fifty1/multicam

我正在使用 OpenCV 来运行相机本身。虽然该应用程序的目的是运行 4 个摄像头并在它们之间切换,但这一切都发生在外部硬件中,因此只需将其视为显示一个 USB 网络摄像头。我还没有完全准备好为此使用 OpenCV,但到目前为止它已经奏效了。

当我尝试调整窗口大小、最小化或最大化窗口时,我的 RPi 4 似乎也出现了分段错误。不确定这是否相关,但我使用两张全新的 SD 卡进行了尝试,希望能排除硬件问题。

我尝试过的:

以编程方式重新排列窗口。不会显示视频,还会出现分段错误。

将 MyWindowClass 子类化为 BigWindowClass 和 SmallWindowClass,然后将单独的 .ui 文件发送到它们各自的类,然后使用 .show() 和 .hide() 方法来确定我想要显示哪一个。这将在大窗口中显示视频,而不是小窗口。

为了清楚起见,我省略了一些函数,但完整的源代码在上面的 github 链接中。

class Thread(QThread):
    global file, big, small
    changePixmap = pyqtSignal(QImage)

    def run(self):
        cap = cv2.VideoCapture(0)
        while running:
            ret, frame = cap.read()
            if ret:
                # not sure if the queue was necessary to prevent memory or processor problems
                if q.qsize() < 10:
                    q.put(frame)
                else:
                    print(q.qsize())

                if not q.empty():
                    f = q.get()
                    rgbImage = cv2.cvtColor(f, cv2.COLOR_BGR2RGB)
                    h, w, ch = rgbImage.shape
                    bytesPerLine = ch * w
                    convertToQtFormat = QImage(rgbImage.data, w, h, bytesPerLine, QImage.Format_RGB888)
                    if file == big:
                        p = convertToQtFormat.scaled(640, 480, Qt.KeepAspectRatio)
                    elif file == small:
                        p = convertToQtFormat.scaled(200, 150, Qt.KeepAspectRatio)

                    else:
                        pass
                    self.changePixmap.emit(p)

        if self.isFinished():
            print("thread killed")


class MyWindowClass(QMainWindow, form_class):
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        self.setupUi(self)
        self.sel = Selector()
        self.press = 0
        self.rel = 0

        self.videoLbl = ClickableLabel(self.videoLbl)
        self.setWindowTitle('Camera')

        self.connectSignals()
        self.th = Thread(self)
        self.th.changePixmap.connect(self.setImage)
        self.th.start()
        self.show()

    @pyqtSlot(QImage)
    def setImage(self, image):
        pixmap = QPixmap.fromImage(image)
        self.videoLbl.setPixmap(pixmap)

 # this will eventually be the function to change views
    def _resize(self):
        print("resize clicked")

    # signal connections
    def connectSignals(self):
        self.cam1.clicked.connect(lambda: self.sel.selectCamera(1))
        self.cam2.clicked.connect(lambda: self.sel.selectCamera(2))
        self.cam3.clicked.connect(lambda: self.sel.selectCamera(3))
        self.cam4.clicked.connect(lambda: self.sel.selectCamera(4))

        self.buttonGroup.setId(self.cam1, 1)
        self.buttonGroup.setId(self.cam2, 2)
        self.buttonGroup.setId(self.cam3, 3)
        self.buttonGroup.setId(self.cam4, 4)
        '''
        self.resizeButton.clicked.connect(resizeWindow)
        self.posCheck.clicked.connect(posit)
        '''
        self.pairButton.pressed.connect(self.prPress)
        self.pairButton.released.connect(self.prRel)

        self.sel.camSelected.connect(self.selected)
        self.videoLbl.clicked.connect(self._resize)


app = QtWidgets.QApplication(sys.argv)
window = MyWindowClass(None)
window.show()
running = True

app.exec_()

【问题讨论】:

【参考方案1】:

所以我自己找到了解决方案。它可能不是最优雅或最有效的,但它正在工作。我从Qt crashes when picture from OpenCV is too large 得到一个重要线索,我需要先复制我的 QImage。

convertToQtFormat = QImage(rgbImage.data, w, h, bytesPerLine, QImage.Format_RGB888)
i = convertToQtFormat.copy()
self.changePixmap.emit(i)

我重新尝试对我的主窗口进行子类化并使用 2 个单独的 .ui 文件,经过几次调整后,程序按预期运行。

https://github.com/eighty2fifty1/multicam/blob/master/multicam4.py

【讨论】:

谢谢!!我遇到了完全相同的问题。执行 python 脚本时出现段错误。如果我用 gdb 运行脚本,gdb 报告在这个函数中发生了段错误: qt_convert_rgb888_to_rgb32(unsigned int*, unsigned char const*, int) () from /lib/arm-linux-gnueabihf/libQt5Gui.so.5 .

以上是关于在 PyQt 中动态调整视频大小的主要内容,如果未能解决你的问题,请参考以下文章

在 QGraphicScene 中动态调整视频大小

有没有办法让标签的字体大小动态调整到 PyQt5 中标签中的文本?

Swift - 如何根据视频播放器框架的大小动态调整 UIView 的大小

如何允许在 PyQt4 中调整 QMessageBox 的大小

PyQt - 手动调整菜单小部件的大小不会调整其内容的大小

如何在 PyQt4 中使用 setRowHeight 和 resizeRowToContents 调整行的大小?