【Python】OpenCV 同时读取视频和摄像头画面,帧率不同步问题

2023-12-26 16:38:26

背景

同时读取视频画面 和 摄像头画面, 并实现同步处理时,出现两种情景

    1. 视频 fps <= 摄像头 fps , 播放视频和读取摄像头,画面同步;
    1. 视频 fps > 摄像头 fps , 播放视频快, 导致读取摄像头画面时, 跟不上播放速度, 画面不同步或将视频画面阻塞为摄像头帧率;

简而言之

同步执行时,谁的 fps 帧率低,使用谁的帧率,因为高的获取不到帧数据啊!

帧同步(假象)

首先需要确定帧同步基准,如以视频帧率为基准,同步摄像头帧率与视频帧率一致

原理:

摄像头帧率没变,读取显示的时候,以摄像头帧和视频帧时间差,进行摄像头帧填充,即延用摄像头上一帧数据

代码

C++ 实现原理类似,假象帧同步,表现一致性

import cv2
import time

if __name__ == "__main__":
    """
    视频和摄像头, 帧同步问题
    ---
    背景: 同时读取视频画面 和 摄像头画面, 并实现同步处理时,出现两种情景
    1) 视频 fps <= 摄像头 fps , 播放视频和读取摄像头,画面同步
    2) 视频 fps > 摄像头 fps  , 播放视频快, 导致读取摄像头画面时, 跟不上播放速度, 画面不同步或将视频画面阻塞为摄像头帧率
    """
    # 视频
    course_cap = cv2.VideoCapture("datasets/video.mp4")
    course_fps = course_cap.get(cv2.CAP_PROP_FPS)
    course_height = int(course_cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    course_width = int(course_cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    # 摄像头
    camera_cap = cv2.VideoCapture(0)
    camera_fps = camera_cap.get(cv2.CAP_PROP_FPS)
    camera_height = int(camera_cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    camera_width = int(camera_cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    # 日志
    print("course cap: ", course_fps, "camera_cap:", camera_fps)
    # 帧同步:以视频帧率为基准,同步摄像头帧率与视频帧率一致
    # 假象帧同步:摄像头帧率没变,读取显示的时候,以摄像头帧和视频帧时间差,进行摄像头帧填充,即延用摄像头上一帧数据
    camera_wait_ns = 0
    if course_fps > camera_fps:
        # 摄像头帧率下, 需要等待时间差
        camera_wait_ns = abs(
            (int(1000 / course_fps) - int(1000 / camera_fps)) * 1000 * 1000
        )
    camera_frame_ns = 0
    camera_frame = None
    # 循环
    while True:
        # 视频帧
        has_course_frame, course_frame = course_cap.read()
        if not has_course_frame:
            break
        # 判断时间差,更新摄像头画面
        frame_ns = time.perf_counter_ns() - camera_frame_ns
        if frame_ns > camera_wait_ns:
            # 读取摄像头画面
            has_camera_frame, camera_frame = camera_cap.read()
            if not has_camera_frame:
                break
            # 更新时间
            camera_frame_ns = time.perf_counter_ns()
        # 视频图像和摄像头图像处理
        if camera_frame is not None:
            course_frame[0:camera_height, 0:camera_width] = camera_frame
        course_frame = cv2.resize(
            course_frame, (int(course_height / 3), int(course_width / 3))
        )
        # 画面显示
        cv2.imshow("test", course_frame)
        cv2.waitKey(1)

文章来源:https://blog.csdn.net/LABLENET/article/details/135223569
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。