[Opencv] Pyhton plays the previous frame, next frame, saves the video, and analyzes frame by frame

Read specific frame

This method can get a certain frame:


while True:
    cap.set(cv2.CAP_PROP_POS_FRAMES, current_frame)
    ret, frame = cap.read()
    if not ret:
        break

wait button

This method displays the current frame and then waits for your button:

        # 显示当前帧
        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

Turning this flag on allows you to store an mp4 video:

FLAG_SAVE_VIDEOS = False

The writing decoding method corresponds to the file format

Different video file formats usually require the use of different codecs, so you need to choose the appropriate four-character encoding identifier based on the video file format you want to create. Here are some examples of common video file formats and corresponding four-character encoding identifiers:

  1. H.264 encoding (usually used for .mp4 files):

    fourcc = cv2.VideoWriter_fourcc(*'H264')
    
  2. XVID encoding (usually used for .avi files):

    fourcc = cv2.VideoWriter_fourcc(*'XVID')
    
  3. MJPG encoding (usually used for .avi files, suitable for scenes with high image quality per frame):

    fourcc = cv2.VideoWriter_fourcc(*'MJPG')
    
  4. DIVX encoding (usually used for .avi files):

    fourcc = cv2.VideoWriter_fourcc(*'DIVX')
    
  5. VP8 encoding (usually used for .webm files):

    fourcc = cv2.VideoWriter_fourcc(*'VP80')
    
  6. VP9 encoding (usually used for .webm files):

    fourcc = cv2.VideoWriter_fourcc(*'VP90')
    

These are some examples of common video file formats and corresponding four-character encoding identifiers. Depending on your needs and the video file format used, choose the appropriate encoding flag to ensure that the video file can be encoded and decoded correctly. Different video editing software and players also support different codecs, so you may need to adjust based on your end use.

All code

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()

Guess you like

Origin blog.csdn.net/x1131230123/article/details/132687823