OpenCV 3.2.0读取本地视频无法限制FPS及分辨率的解决问询
解决OpenCV 3.2.0无法修改本地视频FPS和宽高的问题
嘿,我明白你遇到的麻烦了——用cap.set()去改本地视频的FPS和宽高完全没效果,对吧?这其实是个常见的坑,我来给你讲清楚原因和解决方案。
为什么cap.set()不生效?
对于本地视频文件来说,cv2.CAP_PROP_FPS、cv2.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




