Implementation of a simple camera based on pyqt5

1. First, the ui layout is carried out. The initialization interface is set with four keys and a black background cloth. The functions of the four keys are set to turn on the camera, turn off the camera, take photos and record videos, as shown in the figure:

Open and close are optional. After clicking open, in addition to opening and displaying the camera image, you must also enable the close button to stop open

Click close again to return to the black background, and close the open camera to release the memory occupied by the camera so that it can be opened next time

The two keys can alternately control camera reading, memory occupation and release.
The implementation process is:
self.openCameraBtn = QPushButton('open ') this is the key named open
self.openCameraBtn.clicked.connect(self.openCamera) this is the function connection promoted after the setting key is pressed, that is, the setting key open is pressed to promote the execution of the openCamera function.
self.openCameraBtn.setEnabled(True) this is to enable the key
self.openCameraBtn.setEnabled(False) this is to turn off the key

The camera image display here also involves the problem of timing refresh. Therefore, when the program starts, in addition to initializing the UI, a timer will also be initialized:

    def initTimer(self):
        self.timer = QTimer(self)#Import timer
        self.timer.timeout.connect(self.show_pic)#Timeout refresh function self show_ pic
            
    def show_pic(self):
        ret, img = self.camera.read()
        if not ret:
            print('read error!\n')
            self.closeCamera()
            csbox = QMessageBox(QMessageBox.Warning, self.tr("read failure"), self.tr("Failed to open the camera, please check the connection!"), QMessageBox.NoButton, self)
            csbox.exec_() 
            return
        # cv2.flip(img, 1, img)#Parameters: original image, flip type, new image flip type: horizontal (left and right) flip >0, vertical (up and down) flip =0, horizontal and vertical flip <0
        frame = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        print(frame.shape)#(480, 640, 3) number of rows, columns, color channels (i.e. RGB) img Shape[0] gets the height of the picture, img Shape[1] gets the width of the picture   
        heigt, width = frame.shape[:2]#[0] and [1]
        pixmap = QImage(frame, width, heigt, QImage.Format_RGB888)#Read image
        # print(pixmap)
        pixmap = QPixmap.fromImage(pixmap)
        self.showcamera.setPixmap(pixmap)#Set pixel
        
        self.imgsave=img
        
        if self.opencameras==True and self.openvideo==True:
            self.out.write(frame)
            self.videoCameraBtn.setEnabled(False)
        else:
            print(self.openvideo)
            self.openvideo=False
            self.videoCameraBtn.setEnabled(True)

2. Next, set the photographing function. Press the photographing button to enter the pictureCamera function. The content of the function is as follows. It can be seen that the image data is read and written only after the camera is turned on. If the camera is not turned on and the data is empty, an error will be reported when the image is written. Before photographing and video recording, it is necessary to ensure that the camera is turned on.

        if self.opencameras==True:#The camera is on
            img_name = 'pictures/%d.jpg'%self.count
            cv2.imwrite(img_name, self.imgsave) #Training set write path
            self.count += 1
            cv2.imshow("camera", self.imgsave)


It can be seen that the current camera status will be saved and written into a picture named in sequence after pressing the button to take pictures, and a captured image screen will pop up.

3. The following is how to set the video recording function. After pressing the video button, you will enter the videoCamera function. The content of the function is as follows. You can see that there is also detection to ensure that the camera is turned on before reading and writing image data.

        if self.opencameras==True:#The camera is on
            self.nowtimes = time.strftime("%Y-%m-%d_%H_%M_%S_%p",time.localtime())+"_"+time.strftime("%u",time.localtime())
            videos='./videos/'+self.nowtimes+'.avi'
            print(videos)
            self.out = cv2.VideoWriter(videos,self.fourcc, 20.0, (640,480))#Create a video file
            self.openvideo=True #Open the tag of the video file
            
            self.videoCameraBtn.setEnabled(False)

In addition to the normal process of creating a video file, there is also a close video button, which also indicates that only one avi file can be generated when the video is pressed. Each time the image is refreshed regularly, it will be judged whether it is in the process of recording. If it is in the process of recording, the frame read from the camera will be written to the video file

        if self.opencameras==True and self.openvideo==True:
            self.out.write(frame)
            self.videoCameraBtn.setEnabled(False)
        else:
            print(self.openvideo)
            self.openvideo=False
            self.videoCameraBtn.setEnabled(True)

The following figure shows the process of video recording:
To stop recording, press Clos to turn off the camera. The function to close the key connection is as follows:

        self.camera.release()#Release the occupied camera
        if self.openvideo==True:
            self.out.release()      
        self.openCameraBtn.setEnabled(True)
        self.closeCameraBtn.setEnabled(False)#Off key enable
        self.videoCameraBtn.setEnabled(True)#Enable key
        self.showcamera.setStyleSheet("background:black;")#Style: black background
        self.showcamera.setPixmap(QPixmap())#Set pixel
        self.timer.stop()#Timer stop
        self.opencameras=False
        self.openvideo=False

You can see that the function contains several parts. One is to process the camera and release the memory occupied by the camera; The second is the ui processing of keys. Even if the keys and video buttons can be opened, the camera keys can be disabled; The third is the clock processing. The timer is stopped to stop displaying the images collected by the camera. If it is not stopped, an error will be reported. Because the memory of the camera has been released, so the images refreshed regularly by the clock have failed to collect content, and all will be reported as errors.

The following is the project source code:

#!/usr/bin/python3
# -*- coding: utf-8 -*-

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import cv2
import sys
import os
import time

def chdir(path):
    # Lead in module
    import os
    # Remove first space
    path = path.strip()
    # Remove tail \ symbol
    path = path.rstrip("\\")
    # Determine whether the path exists
    # True exists
    # False does not exist
    isExists = os.path.exists(path)
    # Judgment result
    if not isExists:
        # Create directory if it does not exist
        # Create directory operation function
        print(path + ' directory does not exist')
        return False
    else:
        # If the directory exists, do not create it, and prompt that the directory already exists
        print(path + ' directory already exists')
        return True
 
#Read backup file list
def read_filename(filePath):
    import os
    name = os.listdir(filePath)#Get the file list of filepath
    print(name)
    return name

    
class Example(QWidget):
    def __init__(self):
        super().__init__()
        #Checking and creating folders
        if chdir('pictures')==False:
            os.mkdir('pictures')
        if chdir('videos')==False:
            os.mkdir('videos')
            
        print(len(read_filename('pictures')))
        # self.fourcc = cv2.VideoWriter_fourcc(*'XVID')#FourCC is a 4-byte code used to determine the video coding format
        self.fourcc = cv2.VideoWriter_fourcc(*'MJPG')
        
        self.nowtimes=' '
        self.opencameras=False
        self.openvideo=False
        self.count = int(len(read_filename('pictures')))
        self.initUI()
        self.initTimer()
        
    def initTimer(self):
        self.timer = QTimer(self)#Import timer
        self.timer.timeout.connect(self.show_pic)#Timeout refresh function self show_ pic
            
    def show_pic(self):
        ret, img = self.camera.read()
        if not ret:
            print('read error!\n')
            self.closeCamera()
            csbox = QMessageBox(QMessageBox.Warning, self.tr("read failure"), self.tr("Failed to open the camera, please check the connection!"), QMessageBox.NoButton, self)
            csbox.exec_() 
            return
        # cv2.flip(img, 1, img)#Parameters: original image, flip type, new image flip type: horizontal (left and right) flip >0, vertical (up and down) flip =0, horizontal and vertical flip <0
        frame = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        print(frame.shape)#(480, 640, 3) number of rows, columns, color channels (i.e. RGB) img Shape[0] gets the height of the picture, img Shape[1] gets the width of the picture   
        heigt, width = frame.shape[:2]#[0] and [1]
        pixmap = QImage(frame, width, heigt, QImage.Format_RGB888)#Read image
        # print(pixmap)
        pixmap = QPixmap.fromImage(pixmap)
        self.showcamera.setPixmap(pixmap)#Set pixel
        
        self.imgsave=img
        
        if self.opencameras==True and self.openvideo==True:
            self.out.write(frame)
            self.videoCameraBtn.setEnabled(False)
        else:
            print(self.openvideo)
            self.openvideo=False
            self.videoCameraBtn.setEnabled(True)
            
    def openCamera(self):
        self.showcamera.setEnabled(True)
        self.camera = cv2.VideoCapture(0) #'http://admin:admin@192.168.100.245:8081'
        # self.camera = cv2.VideoCapture('http://admin:admin@192.168.100.245:8081')
        self.openCameraBtn.setEnabled(False)#Close key
        self.closeCameraBtn.setEnabled(True)#Enable key
        self.timer.start(3)#Timing 3 start timing
        self.opencameras=True
  
    def closeCamera(self):
        self.camera.release()#Release the occupied camera
        if self.openvideo==True:
            self.out.release()      
        self.openCameraBtn.setEnabled(True)
        self.closeCameraBtn.setEnabled(False)#Off key enable
        self.videoCameraBtn.setEnabled(True)#Enable key
        self.showcamera.setStyleSheet("background:black;")#Style: black background
        self.showcamera.setPixmap(QPixmap())#Set pixel
        self.timer.stop()#Timer stop
        self.opencameras=False
        self.openvideo=False
        
    def pictureCamera(self):
        print('picture')
        if self.opencameras==True:#The camera is on
            img_name = 'pictures/%d.jpg'%self.count
            cv2.imwrite(img_name, self.imgsave) #Training set write path
            self.count += 1
            cv2.imshow("camera", self.imgsave)
        
    def videoCamera(self):
        print('video')
        if self.opencameras==True:#The camera is on
            self.nowtimes = time.strftime("%Y-%m-%d_%H_%M_%S_%p",time.localtime())+"_"+time.strftime("%u",time.localtime())
            videos='./videos/'+self.nowtimes+'.avi'
            print(videos)
            self.out = cv2.VideoWriter(videos,self.fourcc, 20.0, (640,480))#Create a video file
            self.openvideo=True #Open the tag of the video file
            
            self.videoCameraBtn.setEnabled(False)
        
    def initUI(self):
        self.openCameraBtn = QPushButton('open')
        self.openCameraBtn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)  #Set the qsizepolicy Fixed: fixed size, can not be stretched or compressed
        self.openCameraBtn.clicked.connect(self.openCamera)
        
        self.closeCameraBtn = QPushButton('close')
        self.closeCameraBtn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.closeCameraBtn.clicked.connect(self.closeCamera)
        
        self.pictureCameraBtn = QPushButton('photograph')
        self.pictureCameraBtn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)  #Set the qsizepolicy Fixed: fixed size, can not be stretched or compressed
        self.pictureCameraBtn.clicked.connect(self.pictureCamera)
        
        self.videoCameraBtn = QPushButton('videotape')
        self.videoCameraBtn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
        self.videoCameraBtn.clicked.connect(self.videoCamera)
        
        self.openCameraBtn.setEnabled(True)
        self.closeCameraBtn.setEnabled(False)
        self.showcamera = QLabel(self)
        self.showcamera.resize(640, 480)
     
        self.hbox = QHBoxLayout(self)#Horizontal layout
        self.hbox.addWidget(self.showcamera)#Add a control based on the horizontal layout the addwidget() method is used to add a control to the layout
        
        self.vbox = QVBoxLayout(self)#Vertical layout
        self.vbox.addWidget(self.openCameraBtn)
        self.vbox.addWidget(self.closeCameraBtn)
        self.vbox.addWidget(self.pictureCameraBtn)
        self.vbox.addWidget(self.videoCameraBtn)
        
        self.hbox.addLayout(self.vbox)
 
        self.setLayout(self.hbox)#setLayout is to apply the set layout to the control
        self.showcamera.setStyleSheet("background:black;")#Style: black background
        self.showcamera.setPixmap(QPixmap())#Set pixel
        # self.move(300, 300)
        self.setWindowTitle('camera')
        self.setGeometry(600, 200, 760, 510)
        self.show()
 
    def closeEvent(self, event):
        reply = QMessageBox.question(self, 'Tips', "Are you sure to exit?", QMessageBox.Yes |QMessageBox.No, QMessageBox.No)
        if reply == QMessageBox.Yes:
            event.accept()
        else:
            event.ignore()
    
if __name__=='__main__':
    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

Here is the running video:
[cameras Bili Bili] https://b23.tv/DY6bOAM

cameras

Tags: Qt programming language

Posted by MikeDXUNL on Thu, 02 Jun 2022 11:00:46 +0530