linux桌面小程序开发日记2(pyqt5+yolov5)

2022/2/14 7:17:12

本文主要是介绍linux桌面小程序开发日记2(pyqt5+yolov5),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

linux桌面小程序开发日记2

使用Pyqt5 制作一个界面,并连接摄像头

前言

承接上回,我们把环境装好啦,那么接下来就要开始我们的UI啦,预计完成连接摄像的内容

项目要求——自己想的

  1. 主要用python语言开发
  2. 能够显示摄像头的内容
  3. 能够显示识别内容的列表
  4. 能够进行计价

那我们就开始新的记录吧

第一步 设计UI界面

我就随手画了一个

在这里插入图片描述

第二步 python连接摄像头

因为我的是虚拟机,所以我首先要把我的摄像头连接到虚拟机上,因为我的是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降版本,如果该版本还是报错,那就再把版本降低

(38条消息) Uuntu20.04出现“qt.qpa.plugin: Could not load the Qt platform plugin “xcb“ in…已放弃 (核心已转储)”问题解决记录_消灭BUG鸭的博客-CSDN博客

还有一个问题是,我第一次运行的时候,上面的这个界面是很卡,而且打开相机发现直接无响应。我以为有错误,但是我第二遍运行的时候,就成功了,所以第一次不成功的话,就看看运行第二次有没有问题,有问题再看报错。

同时这个需要检测你的摄像头,如果打开摄像头,提示找不到摄像头,就需要你去修改一下你的摄像头的编号。就是下面注释的地方。至于这个编号怎么改,可以一个一个试,也可以去搜一下如何查看摄像头编号(我默认的这个0是可以的)(可以自己搜一下如何查看摄像头编号)

在这里插入图片描述

第三步 设计界面 完成功能

首先,我们把上面复制的代码自己学习解读一下,好方便我们接下来自己做一个类似的,看代码方面就不多做赘述了。

参考的文章有下面这几个

(38条消息) PyQt5高级界面控件之QTimer(十一)_jia666666的博客-CSDN博客_pyqt5 qtimer

槽函数是什么 - 搜索 (bing.com)

利用设计工具画图

里面用到了布局的组件

左边是一张表,右边就是视频,下面是对应的按钮

在这里插入图片描述

完成视频暂停的功能

简单来说,释放掉视频流时,我不清空视频显示区域,这样显示的图片就停在最后一张,就像是截取了一样

(因为我的项目与物体识别有关,所以我的设想是点击确认后,视频暂停,用户确认表中信息与图片中的信息是否有误,无误,再点击成交,所以我的设想中需要这一功能,但到后期,还需要修改,改为处理后的显示图片)

代码如下

这里我将函数名称也修改了,变量名称也修改了注意一下(就微改了改了几行代码)

  1. 我将打开摄像头放在了初始化上,一运行摄像头就是打开状态
  2. 修改了定义按钮的名称,同时将清空视频显示区域代码删除,完成截图效果
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)

在这里我重新修改了我的代码,使其成为为上面设计的图纸。同时我将表格的内容设为不可编辑

代码如下

关于摄像头的代码没有修改,所以就没有黏贴上来

修改的内容有:

  • 将总布局改为栅格布局
  • 添加了表格布局
  • 又增加了一个按键布局
  • 将表格改为不可编辑
  • 删除了退出按钮
  • 设置了label的大小
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处理后,在显示画面。

最后

总结一下:真的是什么都不会,就做完这些东西我花了两个上午的时间。有很多查的东西也看不懂,也是到了最后,才慢慢摸到了我想要的功能。真不知道,以后真的坐上了开发,这个英文开发文档看不懂会怎么办(>_<)。真的是一看到这些全英文的东西脑袋就大。

不过还是做出来了我想要的效果,还是要鼓励一下自己的嘛。

那么我们就开始我们第三章日记的记录吧。



这篇关于linux桌面小程序开发日记2(pyqt5+yolov5)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程