从子 window 更改 QThread 变量
Changing QThread variable from a sub window
我正在编写一个 WebCam Gui,它应该可以拍照并使用 WebCam 参数进行操作。在主 GUI window 上激活视频流后,可以打开一个额外的 window 来更改 WebCamera 参数 Screenshot 1, Screenshot 2.
我正在使用 Qthread 在 QLabel 上进行流式传输。此外,我还能够根据相机属性的变化设置初始相机参数 window。我的问题是通过在子 window 上使用滑块更改曝光参数并在主 window.
上实时查看结果
请看代码。
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import cv2
class MainFrame(QMainWindow):
def __init__(self):
super(MainFrame, self).__init__()
# Loading UI
uic.loadUi("MainFrame.ui", self)
# Remove maximize button to prevent crushing
self.setWindowFlags(Qt.WindowCloseButtonHint | Qt.WindowMinimizeButtonHint)
# Define Widgets
self.Video_Feed = self.findChild(QLabel, 'Video_Feed')
self.Case_Name = self.findChild(QLineEdit, "Case_Name")
self.Pictures_List = self.findChild(QListWidget, "Pictures_List")
self.Start_Video = self.findChild(QAction, 'actionStart_Video')
self.Start_Video.setShortcut('Shift+S')
self.Stop_Video = self.findChild(QAction, 'actionStop_Video')
self.Stop_Video.setShortcut('Shift+F')
self.Take_a_Picture = self.findChild(QAction, 'actionTake_a_picture')
self.Take_a_Timed_Picture = self.findChild(QAction, 'actionTake_a_timed_picture')
self.Camera_Properties = self.findChild(QAction, 'actionProperties')
# Initializing Video
self.Start_Video.triggered.connect(self.Start_Video_Clicked)
self.Stop_Video.triggered.connect(self.Stop_Video_Clicked)
self.Camera_Properties.triggered.connect(self.Camera_Properties_Clicked)
def Video_Feed_Update(self, Image):
self.Video_Feed.setPixmap(QPixmap.fromImage(Image))
def Start_Video_Clicked(self):
self.Video_Feed_is_Running = True
self.thread = QThread()
self.Video_Thread = Worker()
self.Video_Thread.moveToThread(self.thread)
self.Video_Thread.ImageUpdate.connect(self.Video_Feed_Update)
self.thread.started.connect(self.Video_Thread.run)
self.thread.start()
def Stop_Video_Clicked(self):
self.Video_Thread.stop_video()
self.Video_Feed.setText("Your video starts here")
def Camera_Properties_Clicked(self):
self.CP = CameraParameters()
Initial_Exposure = self.Video_Thread.Camera_Initial_Parameters()
self.CP.Setup_Exposure(int(Initial_Exposure))
self.CP.Exposure_Calibration.connect(self.Video_Thread.Exposure_update)
self.CP.show()
class Worker(QObject):
ImageUpdate = pyqtSignal(QImage)
def run(self):
self.ThreadActive = True
self.Capture = cv2.VideoCapture(1, cv2.CAP_DSHOW)
self.Capture.set(3, 1920)
self.Capture.set(4, 1080)
while self.ThreadActive:
ret, frame = self.Capture.read()
if ret:
image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Converting Video into QT5 readable format
qt_video_format = QImage(image.data, image.shape[1], image.shape[0], QImage.Format_RGB888)
qt_picture = qt_video_format.scaled(1280, 720, Qt.KeepAspectRatio)
self.ImageUpdate.emit(qt_picture)
def stop_video(self):
self.ThreadActive = False
self.Capture.release()
def Camera_Initial_Parameters(self):
return self.Capture.get(cv2.CAP_PROP_EXPOSURE)
def Exposure_update(self, value):
self.Capture.set(cv2.CAP_PROP_EXPOSURE, value)
class CameraParameters(QDialog):
Exposure_Calibration = pyqtSignal(int)
def __init__(self):
super().__init__()
uic.loadUi('Cam_Parameters.ui', self)
# Sliders
self.Exposure_Slider = self.findChild(QSlider, 'ExposureSlider')
self.Exposure_Slider.setRange(-10, 10)
self.White_Balance_Slider = self.findChild(QSlider, 'WBSlider')
self.White_Balance_Slider.setMinimum(-10)
self.White_Balance_Slider.setMaximum(10)
self.Brightness_Slider = self.findChild(QSlider, 'BrightnessSlider')
self.Brightness_Slider.setMinimum(0)
self.Brightness_Slider.setMaximum(300)
self.Saturation_Slider = self.findChild(QSlider, 'SaturationSlider')
self.Saturation_Slider.setMinimum(0)
self.Saturation_Slider.setMaximum(300)
self.Contrast_Slider = self.findChild(QSlider, 'ContrastSlider')
self.Contrast_Slider.setMinimum(-10)
self.Contrast_Slider.setMaximum(10)
self.Gamma_Slider = self.findChild(QSlider, 'GammaSlider')
self.Gamma_Slider.setMinimum(-10)
self.Gamma_Slider.setMaximum(10)
self.Sharpness_Slider = self.findChild(QSlider, 'SharpnessSlider')
self.Sharpness_Slider.setMinimum(0)
self.Sharpness_Slider.setMaximum(100)
# Sliders values
self.Exposure_Value = self.findChild(QLabel, 'Exposure_Value')
self.White_Balance_Value = self.findChild(QLabel, 'WB_value')
self.Brightness_Value = self.findChild(QLabel, 'Brightness_value')
self.Saturation_Value = self.findChild(QLabel, 'Saturation_value')
self.Contrast_Value = self.findChild(QLabel, 'Contrast_value')
self.Gamma_Value = self.findChild(QLabel, 'Gamma_value')
self.Sharpness_Value = self.findChild(QLabel, 'Sharpness_value')
# Connections
self.Exposure_Slider.valueChanged.connect(self.Exposure_sliding)
def Setup_Exposure(self, value):
self.Exposure_Slider.setValue(value)
self.Exposure_Value.setText(str(value))
def Exposure_sliding(self, value):
self.Exposure_Value.setText(str(value))
self.Exposure_Calibration.emit(value)
if __name__ == "__main__":
App = QApplication(sys.argv)
Root = MainFrame()
Root.show()
sys.exit(App.exec())
Cam_Parameters.ui, MainFrame.ui 用于 GUI
我承认我不知道为什么会这样,但是将连接更改为 lambda 函数就可以了。
self.CP.Exposure_Calibration.connect(lambda x: self.Video_Thread.Exposure_update(x))
我正在编写一个 WebCam Gui,它应该可以拍照并使用 WebCam 参数进行操作。在主 GUI window 上激活视频流后,可以打开一个额外的 window 来更改 WebCamera 参数 Screenshot 1, Screenshot 2.
我正在使用 Qthread 在 QLabel 上进行流式传输。此外,我还能够根据相机属性的变化设置初始相机参数 window。我的问题是通过在子 window 上使用滑块更改曝光参数并在主 window.
上实时查看结果请看代码。
import sys
from PyQt5.QtWidgets import *
from PyQt5 import uic
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import cv2
class MainFrame(QMainWindow):
def __init__(self):
super(MainFrame, self).__init__()
# Loading UI
uic.loadUi("MainFrame.ui", self)
# Remove maximize button to prevent crushing
self.setWindowFlags(Qt.WindowCloseButtonHint | Qt.WindowMinimizeButtonHint)
# Define Widgets
self.Video_Feed = self.findChild(QLabel, 'Video_Feed')
self.Case_Name = self.findChild(QLineEdit, "Case_Name")
self.Pictures_List = self.findChild(QListWidget, "Pictures_List")
self.Start_Video = self.findChild(QAction, 'actionStart_Video')
self.Start_Video.setShortcut('Shift+S')
self.Stop_Video = self.findChild(QAction, 'actionStop_Video')
self.Stop_Video.setShortcut('Shift+F')
self.Take_a_Picture = self.findChild(QAction, 'actionTake_a_picture')
self.Take_a_Timed_Picture = self.findChild(QAction, 'actionTake_a_timed_picture')
self.Camera_Properties = self.findChild(QAction, 'actionProperties')
# Initializing Video
self.Start_Video.triggered.connect(self.Start_Video_Clicked)
self.Stop_Video.triggered.connect(self.Stop_Video_Clicked)
self.Camera_Properties.triggered.connect(self.Camera_Properties_Clicked)
def Video_Feed_Update(self, Image):
self.Video_Feed.setPixmap(QPixmap.fromImage(Image))
def Start_Video_Clicked(self):
self.Video_Feed_is_Running = True
self.thread = QThread()
self.Video_Thread = Worker()
self.Video_Thread.moveToThread(self.thread)
self.Video_Thread.ImageUpdate.connect(self.Video_Feed_Update)
self.thread.started.connect(self.Video_Thread.run)
self.thread.start()
def Stop_Video_Clicked(self):
self.Video_Thread.stop_video()
self.Video_Feed.setText("Your video starts here")
def Camera_Properties_Clicked(self):
self.CP = CameraParameters()
Initial_Exposure = self.Video_Thread.Camera_Initial_Parameters()
self.CP.Setup_Exposure(int(Initial_Exposure))
self.CP.Exposure_Calibration.connect(self.Video_Thread.Exposure_update)
self.CP.show()
class Worker(QObject):
ImageUpdate = pyqtSignal(QImage)
def run(self):
self.ThreadActive = True
self.Capture = cv2.VideoCapture(1, cv2.CAP_DSHOW)
self.Capture.set(3, 1920)
self.Capture.set(4, 1080)
while self.ThreadActive:
ret, frame = self.Capture.read()
if ret:
image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# Converting Video into QT5 readable format
qt_video_format = QImage(image.data, image.shape[1], image.shape[0], QImage.Format_RGB888)
qt_picture = qt_video_format.scaled(1280, 720, Qt.KeepAspectRatio)
self.ImageUpdate.emit(qt_picture)
def stop_video(self):
self.ThreadActive = False
self.Capture.release()
def Camera_Initial_Parameters(self):
return self.Capture.get(cv2.CAP_PROP_EXPOSURE)
def Exposure_update(self, value):
self.Capture.set(cv2.CAP_PROP_EXPOSURE, value)
class CameraParameters(QDialog):
Exposure_Calibration = pyqtSignal(int)
def __init__(self):
super().__init__()
uic.loadUi('Cam_Parameters.ui', self)
# Sliders
self.Exposure_Slider = self.findChild(QSlider, 'ExposureSlider')
self.Exposure_Slider.setRange(-10, 10)
self.White_Balance_Slider = self.findChild(QSlider, 'WBSlider')
self.White_Balance_Slider.setMinimum(-10)
self.White_Balance_Slider.setMaximum(10)
self.Brightness_Slider = self.findChild(QSlider, 'BrightnessSlider')
self.Brightness_Slider.setMinimum(0)
self.Brightness_Slider.setMaximum(300)
self.Saturation_Slider = self.findChild(QSlider, 'SaturationSlider')
self.Saturation_Slider.setMinimum(0)
self.Saturation_Slider.setMaximum(300)
self.Contrast_Slider = self.findChild(QSlider, 'ContrastSlider')
self.Contrast_Slider.setMinimum(-10)
self.Contrast_Slider.setMaximum(10)
self.Gamma_Slider = self.findChild(QSlider, 'GammaSlider')
self.Gamma_Slider.setMinimum(-10)
self.Gamma_Slider.setMaximum(10)
self.Sharpness_Slider = self.findChild(QSlider, 'SharpnessSlider')
self.Sharpness_Slider.setMinimum(0)
self.Sharpness_Slider.setMaximum(100)
# Sliders values
self.Exposure_Value = self.findChild(QLabel, 'Exposure_Value')
self.White_Balance_Value = self.findChild(QLabel, 'WB_value')
self.Brightness_Value = self.findChild(QLabel, 'Brightness_value')
self.Saturation_Value = self.findChild(QLabel, 'Saturation_value')
self.Contrast_Value = self.findChild(QLabel, 'Contrast_value')
self.Gamma_Value = self.findChild(QLabel, 'Gamma_value')
self.Sharpness_Value = self.findChild(QLabel, 'Sharpness_value')
# Connections
self.Exposure_Slider.valueChanged.connect(self.Exposure_sliding)
def Setup_Exposure(self, value):
self.Exposure_Slider.setValue(value)
self.Exposure_Value.setText(str(value))
def Exposure_sliding(self, value):
self.Exposure_Value.setText(str(value))
self.Exposure_Calibration.emit(value)
if __name__ == "__main__":
App = QApplication(sys.argv)
Root = MainFrame()
Root.show()
sys.exit(App.exec())
Cam_Parameters.ui, MainFrame.ui 用于 GUI
我承认我不知道为什么会这样,但是将连接更改为 lambda 函数就可以了。
self.CP.Exposure_Calibration.connect(lambda x: self.Video_Thread.Exposure_update(x))