在 PyQt 中动态调整视频大小
Dynamically resizing video in PyQt
我正在用头撞墙试图弄清楚如何调整和重新排列我正在 uilding Raspberry Pi 上的相机应用程序。我希望能够通过点击视频来调整 window 的大小,从全屏应用程序到将显示在触摸屏一角的较小版本。
https://github.com/eighty2fifty1/multicam
我正在使用 OpenCV 运行 相机本身。虽然该应用程序的重点是 运行 4 个摄像头并在它们之间切换,但这一切都发生在外部硬件中,因此只需将其视为显示一个 USB 网络摄像头即可。我还没有完全准备好为此使用 OpenCV,但到目前为止它已经奏效了。
当我尝试调整大小、最小化或最大化 window 时,我的 RPi 4 似乎也出现分段错误。不确定这是否相关,但我已经尝试使用两张全新的 SD 卡来排除硬件问题。
我尝试过的:
正在以编程方式重新排列 window。不会显示视频,还给我一个分段错误。
将 MyWindowClass 子类化为 BigWindowClass 和 SmallWindowClass,然后将单独的 .ui 文件发送到它们各自的 类,然后使用 .show() 和 .hide() 方法以确定我要显示哪一个。这将以大 window 显示视频,但不显示小视频。
为了清楚起见,我省略了一些函数,但完整的源代码在上面的 github link 中。
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_()
所以我自己找到了解决办法。它可能不是最优雅或最有效的,但它正在工作。我从 那里得到了一个重要线索,我需要先复制我的 QImage。
convertToQtFormat = QImage(rgbImage.data, w, h, bytesPerLine, QImage.Format_RGB888)
i = convertToQtFormat.copy()
self.changePixmap.emit(i)
我重新尝试了将我的 Main Window 子类化并使用 2 个单独的 .ui 文件的尝试,经过更多调整后,该程序按预期运行。
https://github.com/eighty2fifty1/multicam/blob/master/multicam4.py
我正在用头撞墙试图弄清楚如何调整和重新排列我正在 uilding Raspberry Pi 上的相机应用程序。我希望能够通过点击视频来调整 window 的大小,从全屏应用程序到将显示在触摸屏一角的较小版本。
https://github.com/eighty2fifty1/multicam
我正在使用 OpenCV 运行 相机本身。虽然该应用程序的重点是 运行 4 个摄像头并在它们之间切换,但这一切都发生在外部硬件中,因此只需将其视为显示一个 USB 网络摄像头即可。我还没有完全准备好为此使用 OpenCV,但到目前为止它已经奏效了。
当我尝试调整大小、最小化或最大化 window 时,我的 RPi 4 似乎也出现分段错误。不确定这是否相关,但我已经尝试使用两张全新的 SD 卡来排除硬件问题。
我尝试过的:
正在以编程方式重新排列 window。不会显示视频,还给我一个分段错误。
将 MyWindowClass 子类化为 BigWindowClass 和 SmallWindowClass,然后将单独的 .ui 文件发送到它们各自的 类,然后使用 .show() 和 .hide() 方法以确定我要显示哪一个。这将以大 window 显示视频,但不显示小视频。
为了清楚起见,我省略了一些函数,但完整的源代码在上面的 github link 中。
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_()
所以我自己找到了解决办法。它可能不是最优雅或最有效的,但它正在工作。我从
convertToQtFormat = QImage(rgbImage.data, w, h, bytesPerLine, QImage.Format_RGB888)
i = convertToQtFormat.copy()
self.changePixmap.emit(i)
我重新尝试了将我的 Main Window 子类化并使用 2 个单独的 .ui 文件的尝试,经过更多调整后,该程序按预期运行。
https://github.com/eighty2fifty1/multicam/blob/master/multicam4.py