PyQT5 запись видео
Я хочу написать простую программу для записи с веб камеры используя PyQt5 и OpenCV.
Мне нужно записывать видео при нажатии кнопки START. И остановить запись нажав STOP. При этом поток с камеры всегда выводится в окно.
На выходе у меня получается видео с нулевой длительностью и выглядит так, как будто захватывает только первый кадр.
import sys
import cv2
import os
from datetime import datetime
from ui_main_window import *
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QWidget
from PyQt5.QtGui import QImage
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import QTimer
class MainWindow(QWidget):
# class constructor
def __init__(self):
# call QWidget constructor
super().__init__()
self.ui = Ui_Form()
self.ui.setupUi(self)
# create a timer
self.timer = QTimer()
self.saveTimer = QTimer()
# set timer timeout callback function
self.saveTimer.timeout.connect(self.viewCam)
self.timer.timeout.connect(self.viewCam)
#always shows video in window
self.timer.start()
# set control_bt callback clicked function
self.ui.control_bt.clicked.connect(self.controlTimer)
self.cap1 = cv2.VideoCapture(cv2.CAP_DSHOW, 0)
self.cap1.set(3,480)
self.cap1.set(4,640)
self.cap1.set(5,30)
# view camera
def viewCam(self):
# read image in BGR format
ret1, image1 = self.cap1.read()
# convert image to RGB format
im1 = cv2.cvtColor(image1, cv2.COLOR_BGR2RGB)
# get image infos
height1, width1, channel1 = im1.shape
step1 = channel1 * width1
# create QImage from image
qImg1 = QImage(im1.data, width1, height1, step1, QImage.Format_RGB888)
# show image in img_label
self.ui.image_label.setPixmap(QPixmap.fromImage(qImg1))
# start/stop timer
def controlTimer(self):
# if timer is stopped
if not self.saveTimer.isActive():
# create video capture
self.path = os.makedirs('C:/camera/' + datetime.now().strftime('%Y-%m-%d__%H-%M-%S'))
self.fourcc = cv2.VideoWriter_fourcc(*'DIVX')
self.out1 = cv2.VideoWriter(os.path.join('C:/camera/' + datetime.now().strftime('%Y-%m-%d__%H-%M-%S'), 'video.avi'), self.fourcc, 30, (640,480))
#start writing
self.saveTimer.start()
self.timer.stop()
ret1, image1 = self.cap1.read()
if ret1:
self.out1.write(image1)
# update control_bt text
self.ui.control_bt.setText("STOP")
# if timer is started
else:
# stop writing
self.saveTimer.stop()
self.timer.start()
self.out1.release()
# update control_bt text
self.ui.control_bt.setText("START")
if __name__ == '__main__':
app = QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.show()
sys.exit(app.exec_())
Ответы (1 шт):
Автор решения: S. Nick
→ Ссылка
Попробуйте так:
import sys
import cv2
import os
from datetime import datetime
#from ui_main_window import *
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QVBoxLayout
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtCore import QTimer, QThread, pyqtSignal, pyqtSlot
from PyQt5 import QtWidgets, QtCore, QtGui
class Thread1(QThread):
changePixmap = pyqtSignal(QImage)
def __init__(self, *args, **kwargs):
super().__init__()
def run(self):
self.cap1 = cv2.VideoCapture(cv2.CAP_DSHOW, 0)
self.cap1.set(3,480)
self.cap1.set(4,640)
self.cap1.set(5,30)
while True:
ret1, image1 = self.cap1.read()
if ret1:
im1 = cv2.cvtColor(image1, cv2.COLOR_BGR2RGB)
height1, width1, channel1 = im1.shape
step1 = channel1 * width1
qImg1 = QImage(im1.data, width1, height1, step1, QImage.Format_RGB888)
self.changePixmap.emit(qImg1)
class Thread2(QThread):
def __init__(self, *args, **kwargs):
super().__init__()
self.active = True
def run(self):
if self.active:
# !!! # установите свой путь !!!
self.path = os.makedirs('D:/_Qt/__Qt/camera/' + datetime.now().strftime('%Y-%m-%d__%H-%M-%S'))
self.fourcc = cv2.VideoWriter_fourcc(*'DIVX')
# !!! # установите свой путь !!!
self.out1 = cv2.VideoWriter(os.path.join('D:/_Qt/__Qt/camera/' + datetime.now().strftime('%Y-%m-%d__%H-%M-%S'), 'video.avi'), self.fourcc, 30, (640,480))
self.cap1 = cv2.VideoCapture(cv2.CAP_DSHOW, 0)
self.cap1.set(3, 480)
self.cap1.set(4, 640)
self.cap1.set(5, 30)
# while True:
while self.active: # +
ret1, image1 = self.cap1.read()
if ret1:
self.out1.write(image1)
self.msleep(10) # +
def stop(self):
# if self.active == False:
self.out1.release()
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.resize(660, 520)
# self.ui = Ui_Form()
# self.ui.setupUi(self)
self.control_bt = QPushButton('START')
self.control_bt.clicked.connect(self.controlTimer)
self.image_label = QLabel()
self.saveTimer = QTimer()
self.th1 = Thread1(self)
self.th1.changePixmap.connect(self.setImage)
self.th1.start()
vlayout = QVBoxLayout(self)
vlayout.addWidget(self.image_label)
vlayout.addWidget(self.control_bt)
@QtCore.pyqtSlot(QImage)
def setImage(self, qImg1):
self.image_label.setPixmap(QPixmap.fromImage(qImg1))
def controlTimer(self):
if not self.saveTimer.isActive():
# write video
self.saveTimer.start()
self.th2 = Thread2(self)
self.th2.active = True # +
self.th2.start()
# self.active = True
# update control_bt text
self.control_bt.setText("STOP")
else:
# stop writing
self.saveTimer.stop()
# self.active = False
self.th2.active = False # +
self.th2.stop() # +
self.th2.terminate() # +
# update control_bt text
self.control_bt.setText("START")
if __name__ == '__main__':
app = QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.show()
sys.exit(app.exec_())