• 【Opencv】Pyhton 播放上一帧,下一帧,存video,逐帧分析


    读取具体哪一帧

    这个方法可以获取某一帧:

    
    while True:
        cap.set(cv2.CAP_PROP_POS_FRAMES, current_frame)
        ret, frame = cap.read()
        if not ret:
            break
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    等待按钮

    这个方法可以显示当前帧,然后等待你的按钮:

            # 显示当前帧
            cv2.imshow('Video Frame', frame)
            # 等待按键输入
            key = cv2.waitKey(0)  # 使用较短的等待时间以确保视频正常播放
            if key == 27:  # ESC
                break
            elif key == ord('q'):  # Q 键(往回跳一帧)
                if current_frame > 0:
                    current_frame -= 1
            elif key == ord('w'):  # W 键(往前播放一帧)
                if current_frame < len(json_data) - 1:
                    current_frame += 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    这个标志打开可以让你存储一个mp4视频:

    FLAG_SAVE_VIDEOS = False
    
    • 1

    写入解码方式与文件格式对应

    不同的视频文件格式通常需要使用不同的编解码器,因此你需要根据你要创建的视频文件格式来选择合适的四字符编码标识。以下是一些常见的视频文件格式和相应的四字符编码标识示例:

    1. H.264 编码(通常用于.mp4文件):

      fourcc = cv2.VideoWriter_fourcc(*'H264')
      
      • 1
    2. XVID 编码(通常用于.avi文件):

      fourcc = cv2.VideoWriter_fourcc(*'XVID')
      
      • 1
    3. MJPG 编码(通常用于.avi文件,适用于每帧图像质量高的场景):

      fourcc = cv2.VideoWriter_fourcc(*'MJPG')
      
      • 1
    4. DIVX 编码(通常用于.avi文件):

      fourcc = cv2.VideoWriter_fourcc(*'DIVX')
      
      • 1
    5. VP8 编码(通常用于.webm文件):

      fourcc = cv2.VideoWriter_fourcc(*'VP80')
      
      • 1
    6. VP9 编码(通常用于.webm文件):

      fourcc = cv2.VideoWriter_fourcc(*'VP90')
      
      • 1

    这些是一些常见的视频文件格式和相应的四字符编码标识示例。根据你的需求和所使用的视频文件格式,选择适合的编码标识以确保视频文件可以正确编码和解码。不同的视频编辑软件和播放器也支持不同的编解码器,因此你可能需要根据最终使用情况进行调整。

    全部代码

    import logging
    import time
    
    import cv2
    import json
    
    # 读取JSON文件
    with open('../inoutdir/long.json', 'r') as f:
        json_data = json.load(f)
    
    # 打开视频文件
    cap = cv2.VideoCapture('../inoutdir/long.mp4')
    
    current_frame = 0
    # 配置日志记录
    logging.basicConfig(level=logging.INFO, format='%(asctime)s [Frame %(frame)d / %(frame_all)d] %(message)s')
    logger = logging.getLogger()
    
    FLAG_SAVE_VIDEOS = False
    if FLAG_SAVE_VIDEOS:
        output_file = '../output/long_draw.mp4'
        fourcc = cv2.VideoWriter_fourcc(*'mp4v')
        frame_width = int(cap.get(3))
        frame_height = int(cap.get(4))
        out = cv2.VideoWriter(output_file, fourcc, 30, (frame_width, frame_height))
    
    # 初始化时间统计
    start_time = time.time()
    total_frames = len(json_data)
    
    while True:
        cap.set(cv2.CAP_PROP_POS_FRAMES, current_frame)
        ret, frame = cap.read()
        if not ret:
            break
        # 记录时间戳
        frame_timestamp = time.time()
    
        # 从JSON中获取当前帧的检测结果
        if current_frame < len(json_data):
            detections = json_data[current_frame]['dets']
    
            # 在每个检测上绘制边界框
            for det in detections:
                x1, y1, x2, y2, score, class_id = det
                color = (0, 255, 0)  # 绿色边界框
                label = f'{int(class_id)},{score:.2f}'
                cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), color, 2)
    
                # 计算文本位置以确保在框内
                text_x = int(x1)
                text_y = int(y1) - 10
                if text_y - 10 < 0:
                    text_y = int(y1) + 20  # 如果文本位置超出了帧的上边界,则将其放在边界框的下方
    
                cv2.putText(frame, label, (text_x, text_y), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
    
        if FLAG_SAVE_VIDEOS:
            out.write(frame)  # 将当前帧写入输出视频
            current_frame += 1
        else:
            # 显示当前帧
            cv2.imshow('Video Frame', frame)
            # 等待按键输入
            key = cv2.waitKey(0)  # 使用较短的等待时间以确保视频正常播放
            if key == 27:  # ESC
                break
            elif key == ord('q'):  # Q 键(往回跳一帧)
                if current_frame > 0:
                    current_frame -= 1
            elif key == ord('w'):  # W 键(往前播放一帧)
                if current_frame < len(json_data) - 1:
                    current_frame += 1
        # 计算每一帧消耗的时间并记录到日志中
        frame_processing_time = time.time() - frame_timestamp
        logger.info(f'Frame processed in {frame_processing_time:.4f} seconds',extra={'frame': current_frame, 'frame_all': total_frames})
    
    # 计算总共消耗的时间
    total_processing_time = time.time() - start_time
    average_frame_time = total_processing_time / total_frames if total_frames > 0 else 0
    
    print(total_processing_time)
    print(average_frame_time)
    
    # 释放视频文件、关闭窗口和输出视频文件
    cap.release()
    if FLAG_SAVE_VIDEOS:
        out.release()
    cv2.destroyAllWindows()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
  • 相关阅读:
    ubuntu22.04 电脑声音和腾讯会议等声音很小怎么修复
    Android 从我方界面启动三方界面,如何巧妙地检测三方页面的生命周期呢?
    [论文阅读]NeurIPS 2021论文预讲会总结
    防止 PHP 应用程序中的 SQL 注入 - 简单而权威的指南
    jQuery--选择器/事件/增加/删除
    【Rust】快速教程——一直在单行显示打印、输入、文件读写
    第一节-PhotoShop基础课程-版本发展
    Error: max no of 200 conversations exceeded pyrfc
    Fake权限验证小例子
    性能测试基础理论
  • 原文地址:https://blog.csdn.net/x1131230123/article/details/132687823