一、前言
本篇的内容是学习的这一位博主的:程序界面设计_doc_cheng的博客-csdn博客。
这是我见过很详细的教你如何使用的pyqt5来完成ui界面设计的,专注于ui界面设计。对我而言,这教程就像是一个实用工具,因为我只需要能够显示图像并展示模型推理的结果即可。
最近一直在努力改进网络和编写脚本,已经有一段时间没写博客了。因此,我打算重新整理这位博主的内容,争取以更简单的方式呈现。
二、ui界面设计
预览图如下所示:
这里我们主要讲解代码部分,ui文件我会直接的提供给大家,大家可以下载下来后再对照着学习。
三、代码讲解
当我们使用pyuic生成代码的时候,一般情况下这个类下有两个函数:setupui和retranslateui。
一般而言,这两个方法用于设置用户界面的初始化和翻译文本。在 setupui 中,会设置窗口、布局、按钮、文本框等元素的属性和初始状态;而在 retranslateui 中,会设置用户界面元素的文本内容。
如果我们只是想要一个像上面的一个浏览图,你可以直接使用下面的代码直接进行预览,它本身并没有任何的功能,只是将ui界面的布局展示出来了,要想做更多的事情,那就需要给这个类补充更多的功能。
from oboardcamdisp import ui_mainwindow
import sys
from pyqt5.qtwidgets import qapplication, qmainwindow
class camshow(qmainwindow, ui_mainwindow):
def __init__(self, parent=none):
super(camshow, self).__init__(parent)
self.setupui(self)
if __name__ == '__main__':
app = qapplication(sys.argv)
ui=camshow()
ui.show()
sys.exit(app.exec_())
你随意的点击滑动这些控件是没有任何用的,这里的camshow 类继承自 qmainwindow 和 ui_mainwindow,通过调用 setupui 方法初始化界面。
1,滑动条与微调框的连接
当我运行上面的文件时候,我们发现移动滑动条或者给微调框调整是各改各的,这里我们可以通过将滑块的 valuechanged 信号连接到对应微调框的 setvalue 槽,以及将微调框的 valuechanged 信号连接到对应滑块的 setvalue 槽。
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)
这里通信成功,像上面的self.redcolorsld和self.redcolorspb都是继承的ui_mainwindow下面的,名字,还有数值都需要自己去修改。
其实也就是这下面的两个地方:
2,相机的初始化和参数设置
这里通过 cv2.videocapture 初始化了相机,并设置了一些相机参数,例如曝光时间、增益、亮度和对比度。通过连接滑动条和微调框,能使用户能够动态地调整这些参数。
def prepcamera(self):
try:
self.camera = cv2.videocapture(0)
self.msgte.clear()
self.msgte.append('oboard camera connected.')
self.msgte.setplaintext()
except exception as e:
self.msgte.clear()
self.msgte.append(str(e))
def prepparameters(self):
self.recordpath='d:/pythonproject/pythonproject1/opencvpyqt5/'
self.filepathle.settext(self.recordpath) # 默认显示
self.recordflag=0
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()
3,界面按钮和相关功能
在这一步中,为界面上的按钮添加了一些功能,例如启动相机、停止相机、录像等。通过连接这些按钮的点击事件,我们实现了相应的功能。特别是,通过 callbackfunctions 函数,我们将按钮的点击事件与后台函数进行了关联。
def startcamera(self):
self.showbt.setenabled(false)
self.stopbt.setenabled(true)
self.recordbt.setenabled(true)
self.grayimgckb.setenabled(true)
if self.grayimgckb.ischecked() == 0:
self.redcolorsld.setenabled(true)
self.redcolorspb.setenabled(true)
self.greencolorsld.setenabled(true)
self.greencolorspb.setenabled(true)
self.bluecolorsld.setenabled(true)
self.bluecolorspb.setenabled(true)
self.exptimesld.setenabled(true)
self.exptimespb.setenabled(true)
self.gainsld.setenabled(true)
self.gainspb.setenabled(true)
self.brightsld.setenabled(true)
self.brightspb.setenabled(true)
self.contrastsld.setenabled(true)
self.contrastspb.setenabled(true)
self.recordbt.settext('录像')
self.timer.start(1)
self.timelb = time.perf_counter()
在最开始运行的时候,有些需要禁用,比如,比如在上面的地方灰度的checkbox没有被点击可以调试r、g、b。
def stopcamera(self):
if self.stopbt.text()=='暂停':
self.stopbt.settext('继续')
self.recordbt.settext('保存')
self.timer.stop()
elif self.stopbt.text()=='继续':
self.stopbt.settext('暂停')
self.recordbt.settext('录像')
self.timer.start(1)
这是一个很简单的逻辑,在这个函数中,如果当前按钮的文本为 ‘暂停’,则将其设置为 ‘继续’ ,并将录像按钮的文本设置为 ‘保存’,最后停止计时器;如果当前按钮的文本为 ‘继续',则将其设置为 ‘暂停’,将录像按钮的文本设置为 ‘录像’ ,并重新启动计时器。
def recordcamera(self):
tag=self.recordbt.text()
if tag=='保存':
try:
image_name=self.recordpath+'image'+time.strftime('%y%m%d%h%m%s',time.localtime(time.time()))+'.jpg'
print(image_name)
cv2.imwrite(image_name, self.image)
self.msgte.clear()
self.msgte.setplaintext('image saved.')
except exception as e:
self.msgte.clear()
self.msgte.setplaintext(str(e))
elif tag == '录像':
self.recordbt.settext('停止')
video_name = self.recordpath + 'video' + time.strftime('%y%m%d%h%m%s',time.localtime(time.time())) + '.avi'
fps = self.fmratelcd.value()
size = (self.image.shape[1],self.image.shape[0])
fourcc = cv2.videowriter_fourcc('m', 'j', 'p', 'g')
self.video_writer = cv2.videowriter(video_name, fourcc,self.camera.get(5), size)
self.recordflag=1
self.msgte.setplaintext('video recording...')
self.stopbt.setenabled(false)
self.exitbt.setenabled(false)
elif tag == '停止':
self.recordbt.settext('录像')
self.video_writer.release()
self.recordflag = 0
self.msgte.setplaintext('video saved.')
self.stopbt.setenabled(true)
self.exitbt.setenabled(true)
如果按钮的文本为 '保存',则执行保存图片的操作。首先构造图片文件名,使用 cv2.imwrite 将当前图像保存为 jpg 文件,然后清空消息显示框并显示保存成功或者错误信息。如果按钮的文本为 '录像',则执行开始录像的操作。构造视频文件名,设置录像相关参数(帧率、大小等),创建 cv2.videowriter 对象开始录像,并在消息显示框中显示录像信息。同时禁用停止按钮和退出按钮,防止在录像时进行其他操作。如果按钮的文本为 '停止',则执行停止录像的操作。将按钮文本设置为 '录像',释放 cv2.videowriter 对象,停止录像标志,显示录像保存成功的消息,并启用停止按钮和退出按钮。
4,图像处理与显示
def coloradjust(self, img):
try:
b = img[:, :, 0]
g = img[:, :, 1]
r = img[:, :, 2]
# 根据滑动条的值进行颜色通道的调整
b = b * self.b
g = g * self.g
r = r * self.r
img_adjusted = img.copy()
img_adjusted[:, :, 0] = b
img_adjusted[:, :, 1] = g
img_adjusted[:, :, 2] = r
return img_adjusted
except exception as e:
self.msgte.setplaintext(str(e))
def dispimg(self):
if self.grayimgckb.ischecked():
img = cv2.cvtcolor(self.image, cv2.color_bgr2gray)
else:
img = cv2.cvtcolor(self.image, cv2.color_bgr2rgb)
qimg = qimage2ndarray.array2qimage(img)
self.displb.setpixmap(qpixmap(qimg))
self.displb.show()
coloradjust函数用于进行颜色调整。然后,通过 qimage2ndarray 将处理后的图像转换为 qimage,最后使用 qpixmap 在界面上的 displb 标签上显示图像。这样,我们完成了图像处理与显示的步骤。
5,使用回调函数将功能与控件进行连接
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)
def setr(self):
r=self.redcolorsld.value()
self.r=r/255
def setg(self):
g=self.greencolorsld.value()
self.g=g/255
def setb(self):
b=self.bluecolorsld.value()
self.b=b/255
def setcontrast(self):
contrast_toset=self.contrastsld.value()
try:
self.camera.set(11,contrast_toset)
self.msgte.setplaintext('the contrast is set to ' + str(self.camera.get(11)))
except exception as e:
self.msgte.setplaintext(str(e))
def setbrightness(self):
brightness_toset=self.brightsld.value()
try:
self.camera.set(10,brightness_toset)
self.msgte.setplaintext('the brightness is set to ' + str(self.camera.get(10)))
except exception as e:
self.msgte.setplaintext(str(e))
def setgain(self):
gain_toset=self.gainsld.value()
try:
self.camera.set(14,gain_toset)
self.msgte.setplaintext('the gain is set to '+str(self.camera.get(14)))
except exception as e:
self.msgte.setplaintext(str(e))
def setexposure(self):
try:
exposure_time_toset=self.exptimesld.value()
self.camera.set(15,exposure_time_toset)
self.msgte.setplaintext('the exposure time is set to '+str(self.camera.get(15)))
except exception as e:
self.msgte.setplaintext(str(e))
def setgray(self):
if self.grayimgckb.ischecked():
self.redcolorsld.setenabled(false)
self.redcolorspb.setenabled(false)
self.greencolorsld.setenabled(false)
self.greencolorspb.setenabled(false)
self.bluecolorsld.setenabled(false)
self.bluecolorspb.setenabled(false)
else:
self.redcolorsld.setenabled(true)
self.redcolorspb.setenabled(true)
self.greencolorsld.setenabled(true)
self.greencolorspb.setenabled(true)
self.bluecolorsld.setenabled(true)
self.bluecolorspb.setenabled(true)
四、其他补充
如果报错pyqt下载不了,是缺少了c++,下一个visual studio然后安装一个c++桌面开发就可以了。
如果运行出现:
说的是sip版本不对,这个不影响运行,可以不用理会。
五、资源下载
pyqt5-opencv-uidesign/camshow at main · auorui/pyqt5-opencv-uidesign (github.com)
主函数文件:
from oboardcamdisp import ui_mainwindow
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
class camshow(qmainwindow,ui_mainwindow):
def __del__(self):
try:
self.camera.release() # 释放资源
except:
return
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)
# 滑动条与微调框的连接
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)
# 相机的初始化和参数设置
def prepcamera(self):
try:
self.camera=cv2.videocapture(0)
self.msgte.clear()
self.msgte.append('oboard camera connected.')
self.msgte.setplaintext()
except exception as e:
self.msgte.clear()
self.msgte.append(str(e))
def prepparameters(self):
self.recordflag = 0
self.recordpath ='d:/pythonproject/pythonproject1/opencvpyqt5/camshow'
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()
# 相机的初始化和参数设置
def startcamera(self):
self.showbt.setenabled(false)
self.stopbt.setenabled(true)
self.recordbt.setenabled(true)
self.grayimgckb.setenabled(true)
if self.grayimgckb.ischecked() == 0:
self.redcolorsld.setenabled(true)
self.redcolorspb.setenabled(true)
self.greencolorsld.setenabled(true)
self.greencolorspb.setenabled(true)
self.bluecolorsld.setenabled(true)
self.bluecolorspb.setenabled(true)
self.exptimesld.setenabled(true)
self.exptimespb.setenabled(true)
self.gainsld.setenabled(true)
self.gainspb.setenabled(true)
self.brightsld.setenabled(true)
self.brightspb.setenabled(true)
self.contrastsld.setenabled(true)
self.contrastspb.setenabled(true)
self.recordbt.settext('录像')
self.timer.start(1)
self.timelb=time.perf_counter()
def stopcamera(self):
if self.stopbt.text()=='暂停':
self.stopbt.settext('继续')
self.recordbt.settext('保存')
self.timer.stop()
elif self.stopbt.text()=='继续':
self.stopbt.settext('暂停')
self.recordbt.settext('录像')
self.timer.start(1)
def recordcamera(self):
tag = self.recordbt.text()
if tag == '保存':
try:
image_name=self.recordpath+'image'+time.strftime('%y%m%d%h%m%s',time.localtime(time.time()))+'.jpg'
print(image_name)
cv2.imwrite(image_name, self.image)
self.msgte.clear()
self.msgte.setplaintext('image saved.')
except exception as e:
self.msgte.clear()
self.msgte.setplaintext(str(e))
elif tag == '录像':
self.recordbt.settext('停止')
video_name = self.recordpath + 'video' + time.strftime('%y%m%d%h%m%s',time.localtime(time.time())) + '.avi'
fps = self.fmratelcd.value()
size = (self.image.shape[1],self.image.shape[0])
fourcc = cv2.videowriter_fourcc('m', 'j', 'p', 'g')
self.video_writer = cv2.videowriter(video_name, fourcc,self.camera.get(5), size)
self.recordflag=1
self.msgte.setplaintext('video recording...')
self.stopbt.setenabled(false)
self.exitbt.setenabled(false)
elif tag == '停止':
self.recordbt.settext('录像')
self.video_writer.release()
self.recordflag = 0
self.msgte.setplaintext('video saved.')
self.stopbt.setenabled(true)
self.exitbt.setenabled(true)
# 图像处理与显示
def coloradjust(self, img):
try:
b = img[:, :, 0]
g = img[:, :, 1]
r = img[:, :, 2]
# 根据滑动条的值进行颜色通道的调整
b = b * self.b
g = g * self.g
r = r * self.r
img_adjusted = img.copy()
img_adjusted[:, :, 0] = b
img_adjusted[:, :, 1] = g
img_adjusted[:, :, 2] = r
return img_adjusted
except exception as e:
self.msgte.setplaintext(str(e))
def dispimg(self):
if self.grayimgckb.ischecked():
img = cv2.cvtcolor(self.image, cv2.color_bgr2gray)
else:
img = cv2.cvtcolor(self.image, cv2.color_bgr2rgb)
qimg = qimage2ndarray.array2qimage(img)
self.displb.setpixmap(qpixmap(qimg))
self.displb.show()
def timeroutfun(self):
success, img = self.camera.read()
if success:
self.image = self.coloradjust(img)
self.dispimg()
self.image_num += 1
if self.recordflag:
self.video_writer.write(img)
if self.image_num % 10 == 9:
frame_rate = 10/(time.perf_counter()-self.timelb)
self.fmratelcd.display(frame_rate)
self.timelb = time.perf_counter()
self.imgwidthlcd.display(self.camera.get(3))
self.imgheightlcd.display(self.camera.get(4))
else:
self.msgte.clear()
self.msgte.setplaintext('image obtaining failed.')
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)
def setr(self):
r=self.redcolorsld.value()
self.r=r/255
def setg(self):
g=self.greencolorsld.value()
self.g=g/255
def setb(self):
b=self.bluecolorsld.value()
self.b=b/255
def setcontrast(self):
contrast_toset=self.contrastsld.value()
try:
self.camera.set(11,contrast_toset)
self.msgte.setplaintext('the contrast is set to ' + str(self.camera.get(11)))
except exception as e:
self.msgte.setplaintext(str(e))
def setbrightness(self):
brightness_toset=self.brightsld.value()
try:
self.camera.set(10,brightness_toset)
self.msgte.setplaintext('the brightness is set to ' + str(self.camera.get(10)))
except exception as e:
self.msgte.setplaintext(str(e))
def setgain(self):
gain_toset=self.gainsld.value()
try:
self.camera.set(14,gain_toset)
self.msgte.setplaintext('the gain is set to '+str(self.camera.get(14)))
except exception as e:
self.msgte.setplaintext(str(e))
def setexposure(self):
try:
exposure_time_toset=self.exptimesld.value()
self.camera.set(15,exposure_time_toset)
self.msgte.setplaintext('the exposure time is set to '+str(self.camera.get(15)))
except exception as e:
self.msgte.setplaintext(str(e))
def setgray(self):
if self.grayimgckb.ischecked():
self.redcolorsld.setenabled(false)
self.redcolorspb.setenabled(false)
self.greencolorsld.setenabled(false)
self.greencolorspb.setenabled(false)
self.bluecolorsld.setenabled(false)
self.bluecolorspb.setenabled(false)
else:
self.redcolorsld.setenabled(true)
self.redcolorspb.setenabled(true)
self.greencolorsld.setenabled(true)
self.greencolorspb.setenabled(true)
self.bluecolorsld.setenabled(true)
self.bluecolorspb.setenabled(true)
def setfilepath(self):
dirname = qfiledialog.getexistingdirectory(self, "浏览", '.')
if dirname:
self.filepathle.settext(dirname)
self.recordpath=dirname+'/'
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)
def exitapp(self):
self.timer.stop()
self.camera.release()
self.msgte.setplaintext('exiting the application..')
qcoreapplication.quit()
if __name__ == '__main__':
app = qapplication(sys.argv)
ui=camshow()
ui.show()
sys.exit(app.exec_())
发表评论