PyQt5+QtDesigner编写摄像头界面程序(三)——主程序的编写

文章目录

    • 前言
    • 1、Slider和SpinBox
    • 2、控件初始化
    • 3、参数初始化
    • 4、控件回调函数

前言

上一节中,我们已经完成了程序的界面设计,并初步编写了主函数可以生成程序的界面。这一节将介绍如何编写各控件的调用函数,实现摄像头参数的调控,并通过time函数实现摄像头的实时图像显示。
在上一节中,我们通过QtDesigner生成了程序界面的ui文件,然后通过PyUIC将该ui文件转换成了py文件。在PyCharm中打开pyuic生成的py文件:“QtTest.py”,该文件的主要内容如下所示:
PyQt5+QtDesigner编写摄像头界面程序(三)——主程序的编写_第1张图片
该文件中定义了一个界面类Ui_CamShow,在该类中定义了两个函数setupUi和retranslateUi。展开setupUi函数可以发现,该函数的内容正是我们在QtDesigner中进行的各种控件、布局的创建和属性设置。而retranslateUi函数主要实现各控件的显示设置。由于setupUi函数的末尾调用了retranslateUi函数,因此我们在主函数中只需要调用setupUi函数就可以生成程序界面。
在上一节中,为了观察程序界面的运行效果,我们简单编写了一下主函数,内容如下图所示。首先,我们从创建好的QtTest中导入界面类Ui_CamShow,然后导入程序需要的各种库函数。接下来,我们定义了一个新的类CamShow,用来实现程序的主要功能。程序的最后一段,“if name == ‘main’:”后面的内容是程序的主函数,它的内容很少,在后续工作中也不再进行修改,其功能就是控制程序的开始和结束,实例化CamShow类。我们的主要代码内容都放在CamShow类中。

PyQt5+QtDesigner编写摄像头界面程序(三)——主程序的编写_第2张图片
目前,在CamShow类中,我们只定义了一个初始化函数“init(self,parent=None):”,在实例化CamShow类时,会自动调用它的初始化函数,因此,我们把想要让程序自动实现的程序功能都放在该函数下。目前,该函数下调用了两个函数:super函数实现了类的继承,将QMainWindow,Ui_CamShow的各种属性过继给CamShow类;setupUI函数则是从Ui_CamShow中继承过来的函数,用来实现程序界面的创建和属性设置。

super(CamShow,self).__init__(parent)
self.setupUi(self)

接下来,我们在初始化函数“init(self,parent=None):”中继续添加新的函数,来实现程序的功能。我们添加的函数如下图所示,根据我们程序的需要,一共添加六个函数,函数PrepSliders用来实现各个slider和对应的spinbox的关联,保证两个控件的值始终相等;函数PrepWidgets用来初始化各个控件,由于某些控件需要在其它控件背后的函数运行后才能工作,因此需要先将它“disable”,例如,“保存”功能,必须在我们点击“开始”按钮开始取图后才有效,因此在程序最开始的时候,需要将“保存”按钮“disable”;PrepParameters用来定义并初始化程序运行过程中会用到的变量;CallBackFunctions则是各个控件背后的功能函数的集合,它定义了我们在程序界面上进行某项操作后实际执行的代码;最后两行,则是计时器的定义和调用,它定义了一个定时器,等我们执行计时器开始的代码后,该计时器就开始计时,每次计时结束都会调用一次函数TimerOutFun,我们用计时器实现对摄像头图像的循环读取和显示。当然,这些函数都是我们自己定义的函数,我们后面的工作就是编写代码实现这些函数的功能。

    def __init__(self,parent=None):
        super(CamShow,self).__init__(parent)
        self.setupUi(self)
        self.PrepSliders()
        self.PrepWidgets()
        self.PrepParameters()
        self.CallBackFunctions()
        self.Timer = QTimer()
        self.Timer.timeout.connect(self.TimerOutFun)

另外,由于我们定义了很多新的函数,这些函数会调用到很多新的库函数,我们需要把对应的库全部import进来。我们需要导入的所有库函数如下所示:

from QtTest import Ui_CamShow
import sys
from PyQt5.QtWidgets import QApplication,QMainWindow,QFileDialog
from PyQt5.QtCore import QTimer,QCoreApplication
from PyQt5.QtGui import QPixmap
import cv2
import qimage2ndarray
import time

接下来,我们来逐个实现刚才定义的这些函数。

1、Slider和SpinBox

PrepSliders函数的实现代码如下所示,我们一共定义了7对slider和spinbox,我们需要逐个地将它们关联起来。函数的代码其实很容易理解,基本上就像读英语一样。以前两行为例,它们的功能就是一旦RedColorSld的值发生变化后,就调用RedColorSpB的setValue函数,将变化后的值赋给RedColorSpB;反过来,一旦RedColorSpB的值发生变化后,就调用RedColorSld的setValue函数,将变化后的值赋给RedColorSld。这样一来,RedColorSld和RedColorSpB就关联起来了,不管哪一个的值发生改变,另一个也会随之而改变。

    def PrepSliders(self):
        self.RedColorSld.valueChanged.connect(self.RedColorSpB.setValue)
        self.RedColorSpB.valueChanged.connect(self.RedColorSld.setValue)
        self.GreenColorSld.valueChanged.connect(self.GreenColorSpB.setValue)
        self.GreenColorSpB.valueChanged.connect(self.GreenColorSld.setValue)
        self.BlueColorSld.valueChanged.connect(self.BlueColorSpB.setValue)
        self.BlueColorSpB.valueChanged.connect(self.BlueColorSld.setValue)
        self.ExpTimeSld.valueChanged.connect(self.ExpTimeSpB.setValue)
        self.ExpTimeSpB.valueChanged.connect(self.ExpTimeSld.setValue)
        self.GainSld.valueChanged.connect(self.GainSpB.setValue)
        self.GainSpB.valueChanged.connect(self.GainSld.setValue)
        self.BrightSld.valueChanged.connect(self.BrightSpB.setValue)
        self.BrightSpB.valueChanged.connect(self.BrightSld.setValue)
        self.ContrastSld.valueChanged.connect(self.ContrastSpB.setValue)
        self.ContrastSpB.valueChanged.connect(self.ContrastSld.setValue)

这里需要注意的是,我们需要保证slider和对应的spinbox的取值范围是一致的,也就是它们的最大和最小值必须相等,这一点,我们在QtDesigner设计时可以设置它们的相关属性来保证,在接下来的程序编写过程中,如果涉及到它们的最大或最小值变动时也要保证slider和spinbox同时变动。

2、控件初始化

PrepWidgets函数的内容如下所示,首先要调用一个PrepCamera函数,这个函数我们后面再编写,接下来,就是在开始取图前,将相关的控件都“disable”,设置方法就是调用“setEnabled”函数,并给它赋值为False,类似地,如果赋值为True的话就是将该控件“enable”。

    def PrepWidgets(self):
        self.PrepCamera()
        self.StopBt.setEnabled(False)
        self.RecordBt.setEnabled(False)
        self.GrayImgCkB.setEnabled(False)
        self.RedColorSld.setEnabled(False)
        self.RedColorSpB.setEnabled(False)
        self.GreenColorSld.setEnabled(False)
        self.GreenColorSpB.setEnabled(False)
        self.BlueColorSld.setEnabled(False)
        self.BlueColorSpB.setEnabled(False)
        self.ExpTimeSld.setEnabled(False)
        self.ExpTimeSpB.setEnabled(False)
        self.GainSld.setEnabled(False)
        self.GainSpB.setEnabled(False)
        self.BrightSld.setEnabled(False)
        self.BrightSpB.setEnabled(False)
        self.ContrastSld.setEnabled(False)
        self.ContrastSpB.setEnabled(False)

PrepCamera函数的代码内容如下所示,为了防止程序出错退出,我们采用了try…except…语句,它实现的功能是先尝试运行try语句后面的代码,如果没有问题就继续往下运行,如果出错就执行except后面的代码。

    def PrepCamera(self):
        try:
            self.camera=cv2.VideoCapture(0)
            self.MsgTE.clear()
            self.MsgTE.append('Oboard camera connected.')
        except Exception as e:
            self.MsgTE.clear()
            self.MsgTE.append(str(e))

我们先来看try后面的代码,self.camera=cv2.VideoCapture(0),的功能就是调用OpenCV的VideoCapture函数打开摄像头,并使用变量self.camera代表该摄像头,参数0意味着打开笔记本自带的摄像头。self.MsgTE.clear():清空文本框MsgTE中的内容。self.MsgTE.append('Oboard camera connected.'):在文本框MsgTE中显示’Oboard camera connected.’,其中append函数意思是在现有的内容后继续添加内容,除此之外,textedit控件还有setPlainText函数,意识是用括号中的文本覆盖原来的文本。
而except语句后面的内容则是捕获出错内容Exception,并将其内容显示在文本框MsgTE中,这样,当程序出错时,程序就不会自动退出,而且我们可以通过文本框MsgTE查看出错信息,帮助我们找到问题所在。

3、参数初始化

PrepParameters函数的代码如下所示。我们定义了变量self.RecordFlag,该值为0时不保存视频,为1才时开始保存视频。变量self.RecordPath定义了默认的文件存储路径。self.FilePathLE.setText(self.RecordPath)将路径名显示在文本框FilePathLE中。变量self.Image_num定义了读取图片的次数,self.R、self.G、 self.B为三个颜色通道的强度增益系数。

def PrepParameters(self):
    self.RecordFlag=0
    self.RecordPath='D:/Python/PyQt/'
    self.FilePathLE.setText(self.RecordPath)
    self.Image_num=0
    self.R=1
    self.G=1
    self.B=1

    self.ExpTimeSld.setValue(self.camera.get(15))
    self.SetExposure()
    self.GainSld.setValue(self.camera.get(14))
    self.SetGain()
    self.BrightSld.setValue(self.camera.get(10))
    self.SetBrightness()
    self.ContrastSld.setValue(self.camera.get(11))
    self.SetContrast()
    self.MsgTE.clear()

后面的内容用来初始化摄像头参数控件的值,即读取摄像头的曝光、增益、亮度、对比度等参数,并将这些值显示在相应的控件上。摄像头参数读取函数为self.camera.get(),括号中的不同序号代表不同的参数,具体的对应关系可见链接cvGetCaptureProperty。

4、控件回调函数

CallBackFunctions函数的代码内容如下所示,它定义了每一个功能控件的触发条件和相应的回调函数。通常来讲,button的触发条件为clicked,即鼠标单击按钮后调用相应的函数;checkbox的触发条件为stateChanged,即单击使其状态发生变化后调用相应函数;slider的触发条件可选择valueChanged、sliderRressed、sliderReleased等,可以根据需要选择触发条件。当然,各个回调函数需要我们后面再分别编写。

    def CallBackFunctions(self):
        self.FilePathBt.clicked.connect(self.SetFilePath)
        self.ShowBt.clicked.connect(self.StartCamera)
        self.StopBt.clicked.connect(self.StopCamera)
        self.RecordBt.clicked.connect(self.RecordCamera)
        self.ExitBt.clicked.connect(self.ExitApp)
        self.GrayImgCkB.stateChanged.connect(self.SetGray)
        self.ExpTimeSld.valueChanged.connect(self.SetExposure)
        self.GainSld.valueChanged.connect(self.SetGain)
        self.BrightSld.valueChanged.connect(self.SetBrightness)
        self.ContrastSld.valueChanged.connect(self.SetContrast)
        self.RedColorSld.valueChanged.connect(self.SetR)
        self.GreenColorSld.valueChanged.connect(self.SetG)
        self.BlueColorSld.valueChanged.connect(self.SetB)

上面代码中,我们一共调用了13个回调函数,程序功能的具体实现的主要通过这些函数来实现,下一节我们将继续介绍这些函数的具体内容。

你可能感兴趣的:(程序界面设计)