赞
踩
使用Pyqt5 制作一个界面,并连接摄像头
最后一篇博客地址:https://blog.csdn.net/Liuchengzhizhi/article/details/123692365
B站视频:https://www.bilibili.com/video/BV1rZ4y1B7t8?share_source=copy_web
源码:https://gitee.com/wx_b915676bb6/yolo-pyqt.git
承接上回,我们把环境装好啦,那么接下来就要开始我们的UI啦,预计完成连接摄像的内容
项目要求——自己想的
那我们就开始新的记录吧
我就随手画了一个
因为我的是虚拟机,所以我首先要把我的摄像头连接到虚拟机上,因为我的是usb摄像头,所以要把对应的服务打开,如下图
然后我们来连一下
安装一下我们需要的OpenCV库
#激活虚拟环境
conda activate yolo
#更新pip
python3 -m pip install --upgrade pip
#安装opencv库 该版本是适用于我的pyqt5的
pip3 install opencv-python==4.3.0.36
这样我们需要的库就安装完成了(我这里出现了问题:我安装好后,我的vscode没有检测到,后来我重启vscode后,就检测到了,所以如果遇到同样的问题,我建议重启一下软件,但是首先要看看自己到底有没有安装成功)
重启后,引用库就是蓝绿色的,说明vscode检测到了这几个库
然后我们来测试一下,摄像头到底有没有连上
我复制黏贴了该博客的代码,进行的测试
python3+pyqt5+pycharm 打开摄像头显示_ZJE-CSDN博客_pyqt5 打开摄像头
from PyQt5 import QtCore,QtGui,QtWidgets import sys import cv2 import numpy as np class Ui_MainWindow(QtWidgets.QWidget): def __init__(self,parent=None): super().__init__(parent) #父类的构造函数 self.timer_camera = QtCore.QTimer() #定义定时器,用于控制显示视频的帧率 self.cap = cv2.VideoCapture() #视频流 self.CAM_NUM = 0 #为0时表示视频流来自笔记本内置摄像头 self.set_ui() #初始化程序界面 self.slot_init() #初始化槽函数 '''程序界面布局''' def set_ui(self): self.__layout_main = QtWidgets.QHBoxLayout() #总布局 self.__layout_fun_button = QtWidgets.QVBoxLayout() #按键布局 self.__layout_data_show = QtWidgets.QVBoxLayout() #数据(视频)显示布局 self.button_open_camera = QtWidgets.QPushButton('打开相机') #建立用于打开摄像头的按键 self.button_close = QtWidgets.QPushButton('退出') #建立用于退出程序的按键 self.button_open_camera.setMinimumHeight(50) #设置按键大小 self.button_close.setMinimumHeight(50) self.button_close.move(10,100) #移动按键 '''信息显示''' self.label_show_camera = QtWidgets.QLabel() #定义显示视频的Label self.label_show_camera.setFixedSize(641,481) #给显示视频的Label设置大小为641x481 '''把按键加入到按键布局中''' self.__layout_fun_button.addWidget(self.button_open_camera) #把打开摄像头的按键放到按键布局中 self.__layout_fun_button.addWidget(self.button_close) #把退出程序的按键放到按键布局中 '''把某些控件加入到总布局中''' self.__layout_main.addLayout(self.__layout_fun_button) #把按键布局加入到总布局中 self.__layout_main.addWidget(self.label_show_camera) #把用于显示视频的Label加入到总布局中 '''总布局布置好后就可以把总布局作为参数传入下面函数''' self.setLayout(self.__layout_main) #到这步才会显示所有控件 '''初始化所有槽函数''' def slot_init(self): self.button_open_camera.clicked.connect(self.button_open_camera_clicked) #若该按键被点击,则调用button_open_camera_clicked() self.timer_camera.timeout.connect(self.show_camera) #若定时器结束,则调用show_camera() self.button_close.clicked.connect(self.close)#若该按键被点击,则调用close(),注意这个close是父类QtWidgets.QWidget自带的,会关闭程序 '''槽函数之一''' def button_open_camera_clicked(self): if self.timer_camera.isActive() == False: #若定时器未启动 flag = self.cap.open(self.CAM_NUM) #参数是0,表示打开笔记本的内置摄像头,参数是视频文件路径则打开视频 if flag == False: #flag表示open()成不成功 msg = QtWidgets.QMessageBox.warning(self,'warning',"请检查相机于电脑是否连接正确",buttons=QtWidgets.QMessageBox.Ok) else: self.timer_camera.start(30) #定时器开始计时30ms,结果是每过30ms从摄像头中取一帧显示 self.button_open_camera.setText('关闭相机') else: self.timer_camera.stop() #关闭定时器 self.cap.release() #释放视频流 self.label_show_camera.clear() #清空视频显示区域 self.button_open_camera.setText('打开相机') def show_camera(self): flag,self.image = self.cap.read() #从视频流中读取 show = cv2.resize(self.image,(640,480)) #把读到的帧的大小重新设置为 640x480 show = cv2.cvtColor(show,cv2.COLOR_BGR2RGB) #视频色彩转换回RGB,这样才是现实的颜色 showImage = QtGui.QImage(show.data,show.shape[1],show.shape[0],QtGui.QImage.Format_RGB888) #把读取到的视频数据变成QImage形式 self.label_show_camera.setPixmap(QtGui.QPixmap.fromImage(showImage)) #往显示视频的Label里 显示QImage if __name__ =='__main__': app = QtWidgets.QApplication(sys.argv) #固定的,表示程序应用 ui = Ui_MainWindow() #实例化Ui_MainWindow ui.show() #调用ui的show()以显示。同样show()是源于父类QtWidgets.QWidget的 sys.exit(app.exec_()) #不加这句,程序界面会一闪而过
然后就成功啦,还是很开心哒( * ▽ *)
问题
点击启动,发现有报错,提示已放弃(核心已转储),我就参考了这篇博客,将opencv降版本,如果该版本还是报错,那就再把版本降低
还有一个问题是,我第一次运行的时候,上面的这个界面是很卡,而且打开相机发现直接无响应。我以为有错误,但是我第二遍运行的时候,就成功了,所以第一次不成功的话,就看看运行第二次有没有问题,有问题再看报错。
同时这个需要检测你的摄像头,如果打开摄像头,提示找不到摄像头,就需要你去修改一下你的摄像头的编号。就是下面注释的地方。至于这个编号怎么改,可以一个一个试,也可以去搜一下如何查看摄像头编号(我默认的这个0是可以的)(可以自己搜一下如何查看摄像头编号)
首先,我们把上面复制的代码自己学习解读一下,好方便我们接下来自己做一个类似的,看代码方面就不多做赘述了。
参考的文章有下面这几个
(38条消息) PyQt5高级界面控件之QTimer(十一)_jia666666的博客-CSDN博客_pyqt5 qtimer
里面用到了布局的组件
左边是一张表,右边就是视频,下面是对应的按钮
简单来说,释放掉视频流时,我不清空视频显示区域,这样显示的图片就停在最后一张,就像是截取了一样
(因为我的项目与物体识别有关,所以我的设想是点击确认后,视频暂停,用户确认表中信息与图片中的信息是否有误,无误,再点击成交,所以我的设想中需要这一功能,但到后期,还需要修改,改为处理后的显示图片)
代码如下
这里我将函数名称也修改了,变量名称也修改了注意一下(就微改了改了几行代码)
from PyQt5 import QtCore,QtGui,QtWidgets import sys import cv2 import numpy as np class Ui_MainWindow(QtWidgets.QWidget): def __init__(self,parent=None): super().__init__(parent) #父类的构造函数 self.timer_camera = QtCore.QTimer() #定义定时器,用于控制显示视频的帧率 self.cap = cv2.VideoCapture() #视频流 self.CAM_NUM = 0 #为0时表示视频流来自笔记本内置摄像头 self.set_ui() #初始化程序界面 ''' Check whether the camera is connected and started''' self.open_camera() self.slot_init() #初始化槽函数 '''程序界面布局''' def set_ui(self): self.__layout_main = QtWidgets.QHBoxLayout() #总布局 self.__layout_fun_button = QtWidgets.QVBoxLayout() #按键布局 self.__layout_data_show = QtWidgets.QVBoxLayout() #数据(视频)显示布局 self.button_confirm = QtWidgets.QPushButton('重新确认') #建立用于打开摄像头的按键 self.button_close = QtWidgets.QPushButton('退出') #建立用于退出程序的按键 self.button_confirm.setMinimumHeight(50) #设置按键大小 self.button_close.setMinimumHeight(50) self.button_close.move(10,100) #移动按键 这句话去掉好像也没关系 '''信息显示''' self.label_show_camera = QtWidgets.QLabel() #定义显示视频的Label self.label_show_camera.setFixedSize(641,481) #给显示视频的Label设置大小为641x481 '''把按键加入到按键布局中''' self.__layout_fun_button.addWidget(self.button_confirm) #把打开摄像头的按键放到按键布局中 self.__layout_fun_button.addWidget(self.button_close) #把退出程序的按键放到按键布局中 '''把某些控件加入到总布局中''' self.__layout_main.addLayout(self.__layout_fun_button) #把按键布局加入到总布局中 self.__layout_main.addWidget(self.label_show_camera) #把用于显示视频的Label加入到总布局中 '''总布局布置好后就可以把总布局作为参数传入下面函数''' self.setLayout(self.__layout_main) #到这步才会显示所有控件 '''初始化所有槽函数''' def slot_init(self): self.button_confirm.clicked.connect(self.open_camera) #若该按键被点击,则调用button_confirm() self.timer_camera.timeout.connect(self.show_camera) #若定时器结束,则调用show_camera() self.button_close.clicked.connect(self.close) #若该按键被点击,则调用close(),注意这个close是父类QtWidgets.QWidget自带的,会关闭程序 '''槽函数之一''' def open_camera(self): if self.timer_camera.isActive() == False: #若定时器未启动 flag = self.cap.open(self.CAM_NUM) #参数是0,表示打开笔记本的内置摄像头,参数是视频文件路径则打开视频 if flag == False: #flag表示open()成不成功 msg = QtWidgets.QMessageBox.warning(self,'warning',"请检查相机于电脑是否连接正确",buttons=QtWidgets.QMessageBox.Ok) else: self.timer_camera.start(30) #定时器开始计时30ms,结果是每过30ms从摄像头中取一帧显示 self.button_confirm.setText('确定') else: self.timer_camera.stop() #关闭定时器 self.cap.release() #释放视频流 # self.label_show_camera.clear() #清空视频显示区域 self.button_confirm.setText('重新确认') def show_camera(self): flag,self.image = self.cap.read() #从视频流中读取 show = cv2.resize(self.image,(640,480)) #把读到的帧的大小重新设置为 640x480 show = cv2.cvtColor(show,cv2.COLOR_BGR2RGB) #视频色彩转换回RGB,这样才是现实的颜色 showImage = QtGui.QImage(show.data,show.shape[1],show.shape[0],QtGui.QImage.Format_RGB888) #把读取到的视频数据变成QImage形式 self.label_show_camera.setPixmap(QtGui.QPixmap.fromImage(showImage)) #往显示视频的Label里 显示QImage if __name__ =='__main__': app = QtWidgets.QApplication(sys.argv) #固定的,表示程序应用 ui = Ui_MainWindow() #实例化Ui_MainWindow ui.show() #调用ui的show()以显示。同样show()是源于父类QtWidgets.QWidget的 sys.exit(app.exec_()) #不加这句,程序界面会一闪而过
参考的文章有下面面几篇
python GUI库图形界面开发之PyQt5控件QTableWidget详细使用方法与属性 - 云+社区 - 腾讯云 (tencent.com)
在这里我重新修改了我的代码,使其成为为上面设计的图纸。同时我将表格的内容设为不可编辑
代码如下
关于摄像头的代码没有修改,所以就没有黏贴上来
修改的内容有:
from PyQt5 import QtCore,QtGui,QtWidgets from PyQt5.QtWidgets import QHeaderView from PyQt5.QtWidgets import QAbstractItemView import sys import cv2 import numpy as np class Ui_MainWindow(QtWidgets.QWidget): def __init__(self,parent=None): super().__init__(parent) #父类的构造函数 self.timer_camera = QtCore.QTimer() #定义定时器,用于控制显示视频的帧率 self.cap = cv2.VideoCapture() #视频流 self.CAM_NUM = 0 #为0时表示视频流来自笔记本内置摄像头 self.set_ui() #初始化程序界面 ''' Check whether the camera is connected and started''' self.open_camera() self.slot_init() #初始化槽函数 '''程序界面布局''' def set_ui(self): self.__layout_main = QtWidgets.QGridLayout() #总布局 self.__layout_fun_button1 = QtWidgets.QHBoxLayout() #按键布局1 self.__layout_fun_button2 = QtWidgets.QHBoxLayout() #按键布局2 self.__layout_data_show = QtWidgets.QVBoxLayout() #数据(视频)显示布局 self.__layout_list_show = QtWidgets.QVBoxLayout() #表格布局 self.button_confirm = QtWidgets.QPushButton('重新确认') #建立用于打开摄像头的按键 # self.button_close = QtWidgets.QPushButton('退出') #建立用于退出程序的按键 self.button_settle_accounts = QtWidgets.QPushButton('结账') #建立结账的按钮 self.list_show = QtWidgets.QTableWidget(6,3) #建立表格 self.label_account = QtWidgets.QLabel("总价") #建立label '''set butten size ''' self.button_confirm.setMinimumHeight(50) #设置按键大小 # self.button_close.setMinimumHeight(50) self.button_settle_accounts.setMinimumHeight(50) self.label_account.setMinimumHeight(50) # self.button_close.move(10,100) #移动按键 这句话去掉好像也没关系 '''set label font''' font = QtGui.QFont() font.setPixelSize(18) self.label_account.setFont(font) '''set list''' self.list_show.setHorizontalHeaderLabels(["名称","数量","单价"]) self.list_show.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)# adaptive size self.list_show.setEditTriggers(QAbstractItemView.EditTrigger(False)) #将表格的内容设为不可编辑 '''信息显示''' self.label_show_camera = QtWidgets.QLabel() #定义显示视频的Label self.label_show_camera.setFixedSize(641,481) #给显示视频的Label设置大小为641x481 '''把按键加入到按键布局中''' self.__layout_fun_button1.addWidget(self.button_confirm) #把重新确认的按键放到按键布局中 # self.__layout_fun_button1.addWidget(self.button_close) #把退出程序的按键放到按键布局中 self.__layout_fun_button2.addWidget(self.button_settle_accounts) #把结账的按键放到按键布局中 '''把表格加入到表格布局中''' self.__layout_list_show.addWidget(self.list_show) #将表格添加到表格布局中 self.__layout_list_show.addWidget(self.label_account) #将总价label添加到表格布局中 '''把某些控件加入到总布局中''' self.__layout_main.addLayout(self.__layout_list_show,0,0) #将表格布局添加到总布局中 self.__layout_main.addLayout(self.__layout_fun_button1,1,1) #把按键布局加入到总布局中 self.__layout_main.addLayout(self.__layout_fun_button2,1,0) #把按键布局加入到总布局中 self.__layout_main.addWidget(self.label_show_camera,0,1) #把用于显示视频的Label加入到总布局中 '''总布局布置好后就可以把总布局作为参数传入下面函数''' self.setLayout(self.__layout_main) #到这步才会显示所有控件 '''初始化所有槽函数''' def slot_init(self): self.button_confirm.clicked.connect(self.open_camera) #若该按键被点击,则调用button_confirm() self.timer_camera.timeout.connect(self.show_camera) #若定时器结束,则调用show_camera()
整体的效果看下图,它是可以自由放大缩小的
可能遇到的问题,就是找了很长时间才找到如何让表格禁止编辑。
还有就是需要稍稍会一些界面的布局的东西。
ok,这第二集的日记就结束啦。下一章,我们就要尝试连接yolo,让yolov5处理后,在显示画面。
总结一下:真的是什么都不会,就做完这些东西我花了两个上午的时间。有很多查的东西也看不懂,也是到了最后,才慢慢摸到了我想要的功能。真不知道,以后真的坐上了开发,这个英文开发文档看不懂会怎么办(>_<)。真的是一看到这些全英文的东西脑袋就大。
不过还是做出来了我想要的效果,还是要鼓励一下自己的嘛。
那么我们就开始我们第三章日记的记录吧。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。