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