You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

OpenCV 3.2.0读取本地视频无法限制FPS及分辨率的解决问询

解决OpenCV 3.2.0无法修改本地视频FPS和宽高的问题

嘿,我明白你遇到的麻烦了——用cap.set()去改本地视频的FPS和宽高完全没效果,对吧?这其实是个常见的坑,我来给你讲清楚原因和解决方案。

为什么cap.set()不生效?

对于本地视频文件来说,cv2.CAP_PROP_FPScv2.CAP_PROP_FRAME_WIDTH这些属性本质是只读的。因为视频文件在编码时就已经固定了帧率、分辨率这些参数,OpenCV只能读取这些值,没法直接修改视频文件本身的属性,所以你调用set()之后再get(),返回的还是原始参数。

可行的解决方案

我们得换个思路:不在读取阶段修改,而是在读取到帧之后手动处理,来实现你要的效果。

1. 控制读取的FPS

有两种常用方式:

方式一:通过等待时间控制实时显示的帧率

计算目标FPS对应的帧间隔,用cv2.waitKey()来控制每帧的显示时长,适合需要实时预览的场景:

import cv2
import time

cap = cv2.VideoCapture('aa.mp4')
# 获取视频原始参数
original_fps = cap.get(cv2.CAP_PROP_FPS)
original_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
original_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)

# 设置目标参数
target_fps = 10
target_width = 640
# 按原始宽高比计算目标高度,避免拉伸
target_height = int(original_height * target_width / original_width)

# 计算每帧的理论等待时间(毫秒)
frame_delay = int(1000 / target_fps)

while cap.isOpened():
    start_time = time.time()
    ret, frame = cap.read()
    if not ret:
        break
    
    # 调整帧的分辨率
    resized_frame = cv2.resize(frame, (target_width, target_height))
    
    # 显示处理后的帧
    cv2.imshow('Controlled Video', resized_frame)
    
    # 补全等待时间:扣除帧处理耗时,避免因计算拖慢帧率
    elapsed_time = int((time.time() - start_time) * 1000)
    actual_delay = max(frame_delay - elapsed_time, 1)
    if cv2.waitKey(actual_delay) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()
方式二:跳过帧来精准控制提取的帧率

如果不需要实时预览,只是想按目标FPS提取帧,这种方法更准确:

import cv2

cap = cv2.VideoCapture('aa.mp4')
original_fps = cap.get(cv2.CAP_PROP_FPS)
target_fps = 10

# 计算需要跳过的帧数:每original_fps帧中保留target_fps帧
frame_skip = int(original_fps // target_fps)
current_frame = 0

# 设置目标分辨率
target_width = 640
original_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
original_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
target_height = int(original_height * target_width / original_width)

while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        break
    
    # 只处理指定间隔的帧
    if current_frame % frame_skip == 0:
        resized_frame = cv2.resize(frame, (target_width, target_height))
        cv2.imshow('Frame-Skipped Video', resized_frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    current_frame += 1

cap.release()
cv2.destroyAllWindows()

2. 调整视频宽高

不管哪种FPS控制方式,都可以用cv2.resize()在读取帧后手动调整分辨率,上面的代码里已经包含了这一步——按原始宽高比计算目标高度,避免画面拉伸变形。

总结

记住:本地视频的编码参数是固定的,OpenCV没法直接修改,必须在读取帧之后做二次处理。上面两种方法都能实现你要的限制FPS和调整宽高的效果,根据你的使用场景选就行~

内容的提问来源于stack exchange,提问作者Ramineni Ravi Teja

火山引擎 最新活动