简体   繁体   English

从两个视频源读取帧不同步 | OpenCV

[英]Reading frames from two video sources is not in sync | OpenCV

I am working on a python OpenCV script that will read from two video streams and put one onto the other one (Picture-In-Picture) and both are supposed to be in sync on the final video.我正在研究 python OpenCV 脚本,该脚本将从两个视频流中读取并将一个放在另一个上(画中画),并且两者都应该在最终视频上同步。 My goal is to put one video on the bottom-left corner of the other one.我的目标是将一个视频放在另一个视频的左下角。 It's somewhat working but the problem is that, even though I initialized both video sources and read frames from them at the same time, the videos are not in sync when I show the processed frames.它有点工作,但问题是,即使我同时初始化了两个视频源并从中读取帧,当我显示处理后的帧时,视频并不同步。 I created a dedicated thread that reads frames from both videos at the same time and appends both (as a tuple) to a list of frame pairs (buffer).我创建了一个专用线程,它同时从两个视频中读取帧,并将两者(作为元组)附加到帧对列表(缓冲区)中。 Then the main thread gets the frame pair from the buffer, processes the final frame, and shows it using imshow .然后主线程从缓冲区中获取帧对,处理最后一帧,并使用imshow显示它。 But one video is several seconds ahead of the other one.但是一个视频比另一个视频早了几秒钟。 I tried reading frames in the main thread but the same problem.我尝试在主线程中读取帧,但同样的问题。 The program also reads some information from subtitle file and adds text to the final frame.该程序还从字幕文件中读取一些信息并将文本添加到最后一帧。 But that is working fine.但这工作正常。 So just ignore the getTelemetry() function.所以只需忽略getTelemetry() function。 I would really appreciate some help.我真的很感激一些帮助。 Thanks谢谢

import cv2
import time
import _thread

telemetry = []
tel = []


def getTelemetry():
    global telemetry, tel
    file = open("subs.srt", "r")
    lines = file.readlines()
    chars = '-.0123456789'
    distance, altitude, horizontal_speed, vertical_speed = None, None, None, None
    for line in lines:
        if line.startswith("F"):
            # print(line.strip('\n'))
            distance = line[line.index('D ')+2:line.index(', H') - 1]
            altitude = line[line.index('H ')+2:line.index(', H.S') - 1]
            horizontal_speed = line[line.index(
                'H.S ')+4:line.index(', V.S') - 3]
            vertical_speed = line[line.index('V.S ')+4:-5]
            for char in distance:
                if char not in chars:
                    distance = '0'
            for char in altitude:
                if char not in chars:
                    altitude = '0'
            for char in horizontal_speed:
                if char not in chars:
                    horizontal_speed = '0'
            for char in vertical_speed:
                if char not in chars:
                    vertical_speed = '0'

            distance_float = float(distance)
            altitude_float = float(altitude)
            horizontal_speed_float = float(horizontal_speed)
            vertical_speed_float = float(vertical_speed)
            telemetry.append([distance_float, altitude_float,
                              horizontal_speed_float, vertical_speed_float])
            # print(distance_float, altitude_float, horizontal_speed_float,
            #      vertical_speed_float)

    # Put each element of telemetry 60 times in tel
    for i in range(0, len(telemetry)):
        for j in range(0, 60):
            tel.append(telemetry[i])
    # print(len(tel))


frame_buffer = []


def fil_buffer():
    global frame_buffer
    video = cv2.VideoCapture("Input_File.avi")
    video2 = cv2.VideoCapture("Screenrecorder-2021-12-07-16-15-26-217.mp4")
    # For each frame in the video
    while(video.isOpened() and video2.isOpened()):
        ret, frame = video.read()
        ret2, frame2 = video2.read()
        if ret == True and ret2 == True:
            frame_buffer.append((frame, frame2))

    video.release()
    video2.release()


if __name__ == '__main__':
    getTelemetry()
    _thread.start_new_thread(fil_buffer, ())
    time.sleep(5)
    print(len(frame_buffer))
    j = 0
    while len(frame_buffer) != 0:
        x = frame_buffer.pop(0)
        frame1 = x[0]
        frame2 = x[1]
        # print(tel[j][0])
        cv2.putText(frame1, "Distance: " + str(tel[j][0]), (10, 30),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
        cv2.putText(frame1, "Altitude: " + str(tel[j][1]), (10, 60),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
        cv2.putText(frame1, "Horizontal Speed: " + str(tel[j][2]), (10, 90),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
        cv2.putText(frame1, "Vertical Speed: " + str(tel[j][3]), (10, 120),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
        # Resize frame2 to 25%
        frame2 = cv2.resize(frame2, (0, 0), fx=0.25, fy=0.25)
        # Put frame2 over frame1
        frame1[500:frame2.shape[0]+500, 0:frame2.shape[1]] = frame2
        cv2.imshow('frame', frame1)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

As mentioned in the comments by Mark, the cameras need not be in be sync, to begin with.正如 Mark 在评论中提到的,相机不需要同步,首先。 They can have different FPS even after having identical hardware.即使拥有相同的硬件,它们也可能具有不同的 FPS。 Also, in your fil_buffer() function, the reading of frames from both cameras is sequential, ie you read camera A first and then camera B. This will definitely increase some level of lag for camera A. I would like to approach the problem this way.此外,在您的 fil_buffer() function 中,从两个摄像头读取帧是顺序的,即您先读取摄像头 A,然后读取摄像头 B。这肯定会增加摄像头 A 的一定程度的延迟。我想解决这个问题方法。

  1. Run the frame reading task for each camera in a separate thread of their own.在各自的单独线程中为每个相机运行帧读取任务。
  2. In the same thread, you can push the read camera frame in their own STACK(not queue/list).在同一个线程中,您可以将读取的相机帧推送到自己的堆栈(不是队列/列表)中。
  3. In your main function, you should read that stack, and clear it instantly.在您的主要 function 中,您应该读取该堆栈并立即清除它。 This makes sure you are always reading the latest available frame in the stack.这可确保您始终读取堆栈中最新的可用帧。

I am assuming that the processing time in your main function will be greater than the time taken to read the frame.我假设您的主 function 中的处理时间将大于读取帧所需的时间。 This should hold true for your application.这应该适用于您的应用程序。

(A few months back, I wrote this article about getting a higher FPS with cameras. Its implementation is in C++ but it has a structure to run multiple cameras in separate threads of their own. I have been using the same structure to read multiple FLIR cameras to read them at FPS of 50-55 and in sync with each other.) (几个月前,我写了这篇关于通过摄像头获得更高 FPS 的文章。它的实现在 C++ 中,但它具有在各自的单独线程中运行多个摄像头的结构。我一直在使用相同的结构来读取多个 FLIR相机以 50-55 的 FPS 读取它们并彼此同步。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM