linux desktop applet development diary 2 (pyqt5+yolov5)

linux desktop applet development diary 2

Use Pyqt5 to make an interface and connect the camera

preface

After the last time, we installed the environment, then we will start our UI, and it is expected to complete the content of connecting the camera

Project requirements - what you think

  1. It is mainly developed in python language
  2. Able to display the contents of the camera
  3. Able to display a list of recognized contents
  4. Can be priced

Let's start a new record

Step 1: design UI interface

I drew one casually

Step 2 connect the camera with python

Because my camera is a virtual machine, I should first connect my camera to the virtual machine. Because my camera is a usb camera, I should turn on the corresponding service, as shown in the figure below

Then let's connect

Install the OpenCV library we need

#Activate virtual environment
conda activate yolo
#Update pip
python3 -m pip install --upgrade pip
#Install the opencv library. This version is applicable to my pyqt5
pip3 install opencv-python==4.3.0.36

In this way, the library we need is installed (I have a problem here: after I install it, my vscode is not detected, and then I restart vscode, so if I encounter the same problem, I suggest restarting the software, but first check whether I have successfully installed it)

After restart, the reference library is blue-green, indicating that vscode has detected these libraries

Then let's test whether the camera is connected

I copied and pasted the code of the blog and tested it

python3+pyqt5+pycharm turn on the camera display_ ZJE-CSDN blog_ Pyqt5 turn on the camera

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) #Constructor of parent class
 
        self.timer_camera = QtCore.QTimer() #Define a timer to control the frame rate of the displayed video
        self.cap = cv2.VideoCapture()       #Video stream
        self.CAM_NUM = 0                    #0 indicates that the video stream comes from the built-in camera of the notebook
 
        self.set_ui()                       #Initialization program interface
        self.slot_init()                    #Initialize slot function
 
    '''Program interface layout'''
    def set_ui(self):
        self.__layout_main = QtWidgets.QHBoxLayout()           #General layout
        self.__layout_fun_button = QtWidgets.QVBoxLayout()      #Key layout
        self.__layout_data_show = QtWidgets.QVBoxLayout()       #Data (video) display layout
        self.button_open_camera = QtWidgets.QPushButton('Turn on the camera') #Create a key to turn on the camera
        self.button_close = QtWidgets.QPushButton('sign out')           #Create a key to exit the program
        self.button_open_camera.setMinimumHeight(50)                #Set key size
        self.button_close.setMinimumHeight(50)
 
        self.button_close.move(10,100)                      #Move key
        '''information display '''
        self.label_show_camera = QtWidgets.QLabel()   #Define the Label that displays the video
        self.label_show_camera.setFixedSize(641,481)    #Set the size of the Label for video display to 641x481
        '''Add keys to key layout'''
        self.__layout_fun_button.addWidget(self.button_open_camera) #Put the key to open the camera into the key layout
        self.__layout_fun_button.addWidget(self.button_close)       #Put the key to exit the program into the key layout
        '''Add some controls to the general layout'''
        self.__layout_main.addLayout(self.__layout_fun_button)      #Add the key layout to the general layout
        self.__layout_main.addWidget(self.label_show_camera)        #Add the Label used to display video to the general layout
        '''After the general layout is arranged, the general layout can be passed into the following functions as parameters'''
        self.setLayout(self.__layout_main) #All controls will not be displayed until this step
 
    '''Initialize all slot functions'''
    def slot_init(self):
        self.button_open_camera.clicked.connect(self.button_open_camera_clicked)    #If the key is clicked, the button is called_ open_ camera_ clicked()
        self.timer_camera.timeout.connect(self.show_camera) #If the timer ends, call show_camera()
        self.button_close.clicked.connect(self.close)#If the key is clicked, close() will be called. Note that this close is the parent qtwidgets QWidget comes with it. It will close the program
 
    '''One of the slot functions'''
    def button_open_camera_clicked(self):
        if self.timer_camera.isActive() == False:   #If the timer does not start
            flag = self.cap.open(self.CAM_NUM) #If the parameter is 0, it means to open the built-in camera of the notebook. If the parameter is the path of the video file, it means to open the video
            if flag == False:       #flag indicates whether open() is successful
                msg = QtWidgets.QMessageBox.warning(self,'warning',"Please check whether the camera is connected to the computer correctly",buttons=QtWidgets.QMessageBox.Ok)
            else:
                self.timer_camera.start(30)  #The timer starts to count for 30ms, and the result is to take a frame from the camera for display every 30ms
                self.button_open_camera.setText('Turn off the camera')
        else:
            self.timer_camera.stop()  #off timer 
            self.cap.release()        #Release video stream
            self.label_show_camera.clear()  #Clear video display area
            self.button_open_camera.setText('Turn on the camera')
 
    def show_camera(self):
        flag,self.image = self.cap.read()  #Read from video stream
 
        show = cv2.resize(self.image,(640,480))     #Reset the size of the read frame to 640x480
        show = cv2.cvtColor(show,cv2.COLOR_BGR2RGB) #The video color is converted back to RGB, which is the real color
        showImage = QtGui.QImage(show.data,show.shape[1],show.shape[0],QtGui.QImage.Format_RGB888) #Convert the read video data into QImage form
        self.label_show_camera.setPixmap(QtGui.QPixmap.fromImage(showImage))  #Display QImage in the Label displaying the video
if __name__ =='__main__':
    app = QtWidgets.QApplication(sys.argv)  #Fixed, indicating application
    ui = Ui_MainWindow()                    #Instantiate Ui_MainWindow
    ui.show()                               #Call show() of ui to display. Similarly, show () is derived from the parent class qtwidgets QWidget
    sys.exit(app.exec_())                   #Without this sentence, the program interface will flash by

Then I succeeded. I'm still very happy (* ▽ *)

problem

Click start to find that there is an error and the prompt has been abandoned (the core has been dumped). I refer to this blog and reduce the version of opencv. If the version still reports an error, then reduce the version again

(38 messages) uuntu20 04 the problem solving record of "qt.qpa.plugin: Could not load the Qt platform plugin" xcb "in... Abandoned (core dumped)" appears_ Blog to eliminate BUG duck - CSDN blog

Another problem is that is too laggy on the interface when I first run, and the camera is opened without response. I thought there was an error, but when I ran the second time, I succeeded, so if I failed the first time, I'll see if there is a problem in the second time. If there is a problem, I'll read the error report again.

At the same time, you need to check your camera. If you open the camera and prompt that you can't find the camera, you need to modify the number of your camera. This is the place noted below. As for how to change this number, you can try one by one, or you can search how to view the camera number (my default 0 is OK) (you can search how to view the camera number by yourself)

The third step is to design the interface to complete the function

First of all, let's learn and interpret the code copied above, so that we can make a similar one by ourselves. We won't repeat it when looking at the code.

Reference articles include the following

(38 messages) QTimer of PyQt5 advanced interface control (11)_ jia666666 blog - CSDN blog_ pyqt5 qtimer

What is the slot function - Search (bing.com)

Drawing with design tools

The layout components are used

On the left is a table, on the right is a video, and below is the corresponding button

Complete the function of video pause

In short, when releasing the video stream, I don't empty the video display area, so the displayed image will stop at the last one, just like intercepting it

(because my project is related to object recognition, my assumption is that after clicking confirm, the video will be suspended, and the user will confirm whether the information in the table and the information in the picture are correct, and then click to clinch a deal. Therefore, this function is required in my assumption, but it needs to be modified to display the picture after processing in the later stage)

The code is as follows

Here, I have also modified the function name and variable name. Please pay attention to it (slightly changed and changed a few lines of code)

  1. I put the open camera on the initialization. As soon as I run the camera, it is open
  2. The name of the definition button is modified, and the code for clearing the video display area is deleted to complete the screenshot effect
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) #Constructor of parent class
 
        self.timer_camera = QtCore.QTimer() #Define a timer to control the frame rate of the displayed video
        self.cap = cv2.VideoCapture()       #Video stream
        self.CAM_NUM = 0                    #0 indicates that the video stream comes from the built-in camera of the notebook
 
        self.set_ui()                       #Initialization program interface
        ''' Check whether the camera is connected and started'''
        self.open_camera()
        self.slot_init()                    #Initialize slot function
        

 
    '''Program interface layout'''
    def set_ui(self):
        self.__layout_main = QtWidgets.QHBoxLayout()           #General layout
        self.__layout_fun_button = QtWidgets.QVBoxLayout()      #Key layout
        self.__layout_data_show = QtWidgets.QVBoxLayout()       #Data (video) display layout
        self.button_confirm = QtWidgets.QPushButton('Reconfirmation') #Create a key to turn on the camera
        self.button_close = QtWidgets.QPushButton('sign out')           #Create a key to exit the program
        self.button_confirm.setMinimumHeight(50)                #Set key size
        self.button_close.setMinimumHeight(50)
     
        self.button_close.move(10,100)                      #It doesn't seem to matter to remove the sentence of moving the button
        '''information display '''
        self.label_show_camera = QtWidgets.QLabel()   #Define the Label that displays the video
        self.label_show_camera.setFixedSize(641,481)    #Set the size of the Label for video display to 641x481
        '''Add keys to key layout'''
        self.__layout_fun_button.addWidget(self.button_confirm) #Put the key to open the camera into the key layout
        self.__layout_fun_button.addWidget(self.button_close)       #Put the key to exit the program into the key layout
        '''Add some controls to the general layout'''
        self.__layout_main.addLayout(self.__layout_fun_button)      #Add the key layout to the general layout
        self.__layout_main.addWidget(self.label_show_camera)        #Add the Label used to display video to the general layout
        '''After the general layout is arranged, the general layout can be passed into the following functions as parameters'''
        self.setLayout(self.__layout_main) #All controls will not be displayed until this step
 
    '''Initialize all slot functions'''
    def slot_init(self):
        self.button_confirm.clicked.connect(self.open_camera)    #If the key is clicked, the button is called_ confirm()
        self.timer_camera.timeout.connect(self.show_camera) #If the timer ends, call show_camera()
        self.button_close.clicked.connect(self.close) #If the key is clicked, close() will be called. Note that this close is the parent qtwidgets QWidget comes with it. It will close the program
 
    '''One of the slot functions'''
    def open_camera(self):
        if self.timer_camera.isActive() == False:   #If the timer does not start
            flag = self.cap.open(self.CAM_NUM) #If the parameter is 0, it means to open the built-in camera of the notebook. If the parameter is the path of the video file, it means to open the video
            if flag == False:       #flag indicates whether open() is successful
                msg = QtWidgets.QMessageBox.warning(self,'warning',"Please check whether the camera is connected to the computer correctly",buttons=QtWidgets.QMessageBox.Ok)
            else:
                self.timer_camera.start(30)  #The timer starts to count for 30ms, and the result is to take a frame from the camera for display every 30ms
                self.button_confirm.setText('determine')
        else:
            self.timer_camera.stop()  #off timer 
            self.cap.release()        #Release video stream
            # self.label_show_camera.clear()  #Clear video display area
            self.button_confirm.setText('Reconfirmation')
 
    def show_camera(self):
        flag,self.image = self.cap.read()  #Read from video stream
 
        show = cv2.resize(self.image,(640,480))     #Reset the size of the read frame to 640x480
        show = cv2.cvtColor(show,cv2.COLOR_BGR2RGB) #The video color is converted back to RGB, which is the real color
        showImage = QtGui.QImage(show.data,show.shape[1],show.shape[0],QtGui.QImage.Format_RGB888) #Convert the read video data into QImage form
        self.label_show_camera.setPixmap(QtGui.QPixmap.fromImage(showImage))  #Display QImage in the Label displaying the video
        
if __name__ =='__main__':
    app = QtWidgets.QApplication(sys.argv)  #Fixed, indicating application
    ui = Ui_MainWindow()                    #Instantiate Ui_MainWindow
    ui.show()                               #Call show() of ui to display. Similarly, show () is derived from the parent class qtwidgets QWidget
    sys.exit(app.exec_())                   #Without this sentence, the program interface will flash by

Add display table function

The reference articles are as follows

PyQt5 control QTableWidget for graphical interface development of python GUI library detailed usage and properties - cloud + community - Tencent cloud (tencent.com)

Here I revised my code to make it a drawing designed for the above. At the same time, I set the contents of the form as non editable

The code is as follows

The code for the camera has not been modified, so it has not been pasted

The revised contents include:

  • Change general layout to grid layout
  • Added table layout
  • Another key layout is added
  • Change table to non editable
  • Exit button deleted
  • Set the size of the 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) #Constructor of parent class
 
        self.timer_camera = QtCore.QTimer() #Define a timer to control the frame rate of the displayed video
        self.cap = cv2.VideoCapture()       #Video stream
        self.CAM_NUM = 0                    #0 indicates that the video stream comes from the built-in camera of the notebook
 
        self.set_ui()                       #Initialization program interface
        ''' Check whether the camera is connected and started'''
        self.open_camera()
        self.slot_init()                    #Initialize slot function


    '''Program interface layout'''
    def set_ui(self):
        self.__layout_main = QtWidgets.QGridLayout()           #General layout
        self.__layout_fun_button1 = QtWidgets.QHBoxLayout()      #Key layout 1
        self.__layout_fun_button2 = QtWidgets.QHBoxLayout()      #Key layout 2
        self.__layout_data_show = QtWidgets.QVBoxLayout()       #Data (video) display layout
        self.__layout_list_show  = QtWidgets.QVBoxLayout()          #Table layout

        self.button_confirm = QtWidgets.QPushButton('Reconfirmation') #Create a key to turn on the camera
        # self.button_close = QtWidgets.QPushButton('sign out')               #Create a key to exit the program
        self.button_settle_accounts = QtWidgets.QPushButton('Check out') #Create closing button
        self.list_show =  QtWidgets.QTableWidget(6,3)                          #Create table
        self.label_account = QtWidgets.QLabel("Total price")                          #Create label

        '''set butten size '''
        self.button_confirm.setMinimumHeight(50)                #Set key size
        # self.button_close.setMinimumHeight(50)
        self.button_settle_accounts.setMinimumHeight(50)
        self.label_account.setMinimumHeight(50)
        

        # self.button_close.move(10,100)                      #It doesn't seem to matter to remove the sentence of moving the button
        '''set label font'''
        font = QtGui.QFont()
        font.setPixelSize(18)
        self.label_account.setFont(font)

        '''set list'''
        self.list_show.setHorizontalHeaderLabels(["name","quantity","Unit Price"])
        self.list_show.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)# adaptive size
        self.list_show.setEditTriggers(QAbstractItemView.EditTrigger(False))    #Make the contents of the table non editable
        '''information display '''
        self.label_show_camera = QtWidgets.QLabel()   #Define the Label that displays the video
        self.label_show_camera.setFixedSize(641,481)    #Set the size of the Label for video display to 641x481
        '''Add keys to key layout'''
        self.__layout_fun_button1.addWidget(self.button_confirm) #Put the reconfirmed key into the key layout
        # self.__layout_fun_button1.addWidget(self.button_close)       #Put the key to exit the program into the key layout
        self.__layout_fun_button2.addWidget(self.button_settle_accounts) #Put the checkout key into the key layout
        '''Add table to table layout'''
        self.__layout_list_show.addWidget(self.list_show)           #Add table to table layout
        self.__layout_list_show.addWidget(self.label_account) #Add total price label to table layout


        '''Add some controls to the general layout'''
        self.__layout_main.addLayout(self.__layout_list_show,0,0)            #Add table layout to general layout
        self.__layout_main.addLayout(self.__layout_fun_button1,1,1)      #Add the key layout to the general layout
        self.__layout_main.addLayout(self.__layout_fun_button2,1,0)      #Add the key layout to the general layout
        self.__layout_main.addWidget(self.label_show_camera,0,1)        #Add the Label used to display video to the general layout
        
        '''After the general layout is arranged, the general layout can be passed into the following functions as parameters'''
        self.setLayout(self.__layout_main) #All controls will not be displayed until this step
 
    '''Initialize all slot functions'''
    def slot_init(self):
        self.button_confirm.clicked.connect(self.open_camera)    #If the key is clicked, the button is called_ confirm()
        self.timer_camera.timeout.connect(self.show_camera) #If the timer ends, call show_camera()

The overall effect is shown in the figure below. It can be enlarged or reduced freely

The possible problem is that it took a long time to find out how to prohibit editing.

There are also things that need to know a little about the layout of the interface.

ok, the diary of the second episode is over. After the next chapter, let's try to connect to the next chapter.

last

To sum up: I really can't do anything. It took me two mornings to finish these things. There are many things I can't understand. In the end, I slowly felt the function I wanted. I really don't know. If I really sit on the development platform in the future, what will I do if I can't understand the English development document (> <). It's really a big head at the sight of these all English things.

However, I have achieved the effect I want. I still need to encourage myself.

Then let's start the record of our third chapter diary.

Keywords: Python Linux Qt

Added by Calcartman on Sun, 13 Feb 2022 10:31:25 +0200