Запись видео с помощью многопоточности Opencv Python - PullRequest
0 голосов
/ 03 апреля 2019

Я пытаюсь записать видео, используя opencv в python, когда выполняю многопоточность в потоке, который отображает поток в окне. Я довольно новичок в многопоточности и не уверен, по какой причине я не могу записать видео. Я сохраняю файл, но в нем нет потока. Указатели очень ценятся. Это мой код:

import cv2
import os
import threading
import shutil
import json
import re
import datetime
import time
now=datetime.datetime.now()



class camThread(threading.Thread):
    def __init__(self, previewName, camID):
        threading.Thread.__init__(self)
        self.previewName = previewName

        self.camID = camID

    def run(self):
        print("Starting " + self.previewName)
        camPreview(self.previewName, self.camID)

def camPreview(previewName, camID):
    cv2.namedWindow(previewName)
    cam = cv2.VideoCapture(camID)
    cam.set(cv2.CAP_PROP_FRAME_WIDTH, 480)
    cam.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
    if cam.isOpened():
        rval, frame = cam.read()
        frame_width = int(cam.get(3))
        frame_height = int(cam.get(4))

    else:
        rval = False

    while rval:
        cv2.namedWindow(previewName, cv2.WINDOW_NORMAL)
        if (camID == 2):
            frame= cv2.flip(frame,-1)
       # cv2.setWindowProperty(previewName, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
        cv2.imshow(previewName, frame)
      # cam.set(CV_CAP_PROP_SETTINGS, 0)
        rval, frame = cam.read()

        key = cv2.waitKey(20)
        if key == 115 :
            Cam1="Cam"+str(camID)+"_"+timestr
            ts=datetime.datetime.now()
            filename="{}.avi".format(Cam1+ts.strftime("%Y%m%d_%H-%M-%S"))
            out=cv2.VideoWriter(filename,cv2.VideoWriter_fourcc('M','J', 'P','G'),10,(480,720))
            out.write(frame)
            if key == 27:
              print("Stopping recording")
              break
        if key == 27:  # exit on ESC
            break
    cv2.destroyWindow(previewName)

# Create threads as follows
thread1 = camThread("Camera 1", 0)
thread2 = camThread("Camera 2", 2)
thread3 = camThread("Camera 3", 3)
timestr=str(now.strftime("%Y%m%d_%H-%M-%S"))

print("Working Directory:")
print(timestr)

#thread1.start()
thread2.start()
thread3.start()
print()
print("Active threads", threading.activeCount())

Ответы [ 2 ]

1 голос
/ 04 апреля 2019

Я думаю, вы на правильном пути, но мне не удалось сохранить файл с вашим кодом. Вот виджет видео-поток-видео, использующий многопоточность для получения кадров. Для каждого потока камеры есть два потока:

  • Тема # 1 - предназначена только для чтения кадров из потока камеры.
  • Тема № 2 - предназначена для обработки кадров (показ и запись).

Мы отделяем рамки чтения от показа / записи, потому что cv2.VideoCapture.read() является операцией блокировки. Таким образом, мы читаем кадры в своем собственном независимом потоке, чтобы «улучшить» FPS за счет уменьшения задержки из-за операций ввода-вывода. Кроме того, изолируя захват кадра в его собственном потоке, всегда будет кадр, готовый к обработке, вместо того, чтобы ждать завершения операции ввода-вывода и возврата нового кадра. Во втором нашем потоке, посвященном обработке, мы теперь можем свободно показывать и сохранять каждый кадр в нашем выходном файле.

Также, инкапсулируя все это в один объект, мы можем создать набор потоков для каждой камеры, который легко масштабируется независимо от того, сколько камер используется. Поскольку каждый поток с камеры создается в фоновом потоке, мы должны поддерживать основной поток живым. Обязательно замените строку src на вашу собственную камеру. Вот пример записи трех видеопотоков одновременно.

image

from threading import Thread
import cv2
import time

class VideoWriterWidget(object):
    def __init__(self, video_file_name, src=0):
        # Create a VideoCapture object
        self.frame_name = str(src)
        self.video_file = video_file_name
        self.video_file_name = video_file_name + '.avi'
        self.capture = cv2.VideoCapture(src)

        # Default resolutions of the frame are obtained (system dependent)
        self.frame_width = int(self.capture.get(3))
        self.frame_height = int(self.capture.get(4))

        # Set up codec and output video settings
        self.codec = cv2.VideoWriter_fourcc('M','J','P','G')
        self.output_video = cv2.VideoWriter(self.video_file_name, self.codec, 30, (self.frame_width, self.frame_height))

        # Start the thread to read frames from the video stream
        self.thread = Thread(target=self.update, args=())
        self.thread.daemon = True
        self.thread.start()

        # Start another thread to show/save frames
        self.start_recording()
        print('initialized {}'.format(self.video_file))

    def update(self):
        # Read the next frame from the stream in a different thread
        while True:
            if self.capture.isOpened():
                (self.status, self.frame) = self.capture.read()

    def show_frame(self):
        # Display frames in main program
        if self.status:
            cv2.imshow(self.frame_name, self.frame)

        # Press Q on keyboard to stop recording
        key = cv2.waitKey(1)
        if key == ord('q'):
            self.capture.release()
            self.output_video.release()
            cv2.destroyAllWindows()
            exit(1)

    def save_frame(self):
        # Save obtained frame into video output file
        self.output_video.write(self.frame)

    def start_recording(self):
        # Create another thread to show/save frames
        def start_recording_thread():
            while True:
                try:
                    self.show_frame()
                    self.save_frame()
                except AttributeError:
                    pass
        self.recording_thread = Thread(target=start_recording_thread, args=())
        self.recording_thread.daemon = True
        self.recording_thread.start()

if __name__ == '__main__':
    src1 = 'Your link1'
    video_writer_widget1 = VideoWriterWidget('Camera 1', src1)
    src2 = 'Your link2'
    video_writer_widget2 = VideoWriterWidget('Camera 2', src2)
    src3 = 'Your link3'
    video_writer_widget3 = VideoWriterWidget('Camera 3', src3)

    # Since each video player is in its own thread, we need to keep the main thread alive.
    # Keep spinning using time.sleep() so the background threads keep running
    # Threads are set to daemon=True so they will automatically die 
    # when the main thread dies
    while True:
        time.sleep(5)
0 голосов
/ 09 апреля 2019
from threading import Thread
import cv2
import time

class VideoWriterWidget(object):
    def __init__(self, video_file_name, src=0):
        # Create a VideoCapture object
        self.frame_name = str(src) # if using webcams, else just use src as it is.
        self.video_file = video_file_name
        self.video_file_name = video_file_name + '.avi'
        self.capture = cv2.VideoCapture(src)

        # Default resolutions of the frame are obtained (system dependent)
        self.frame_width = int(self.capture.get(3))
        self.frame_height = int(self.capture.get(4))

        # Set up codec and output video settings
        self.codec = cv2.VideoWriter_fourcc('M','J','P','G')
        self.output_video = cv2.VideoWriter(self.video_file_name, self.codec, 30, (self.frame_width, self.frame_height))

        # Start the thread to read frames from the video stream
        self.thread = Thread(target=self.update, args=())
        self.thread.daemon = True
        self.thread.start()

        # Start another thread to show/save frames
        self.start_recording()
        print('initialized {}'.format(self.video_file))

    def update(self):
        # Read the next frame from the stream in a different thread
        while True:
            if self.capture.isOpened():
                (self.status, self.frame) = self.capture.read()

    def show_frame(self):
        # Display frames in main program
        if self.status:
            cv2.imshow(self.frame_name, self.frame)

        # Press Q on keyboard to stop recording
        key = cv2.waitKey(1)
        if key == ord('q'):
            self.capture.release()
            self.output_video.release()
            cv2.destroyAllWindows()
            exit(1)

    def save_frame(self):
        # Save obtained frame into video output file
        self.output_video.write(self.frame)

    def start_recording(self):
        # Create another thread to show/save frames
        def start_recording_thread():
            while True:
                try:
                    self.show_frame()
                    self.save_frame()
                except AttributeError:
                    pass
        self.recording_thread = Thread(target=start_recording_thread, args=())
        self.recording_thread.daemon = True
        self.recording_thread.start()

if __name__ == '__main__':
    src1 = 'Your link1'
    video_writer_widget1 = VideoWriterWidget('Camera 1', src1)
    src2 = 'Your link2'
    video_writer_widget2 = VideoWriterWidget('Camera 2', src2)
    src3 = 'Your link3'
    video_writer_widget3 = VideoWriterWidget('Camera 3', src3)

    # Since each video player is in its own thread, we need to keep the main thread alive.
    # Keep spinning using time.sleep() so the background threads keep running
    # Threads are set to daemon=True so they will automatically die 
    # when the main thread dies
    while True:
        time.sleep(5)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...