我试着用cv2.VideoCapture
阅读第600帧的视频。但是,我发现以下两种方法都成功地读取了图像,但是图像不同。我想知道哪一种读取第600帧的方法是正确的,为什么产生的图像是不同的?它与mp4编码有关吗?谢谢!
方法1
cap = cv2.VideoCapture("test.mp4")
print(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # 1187
cap.set(1, 600)
ret, frame1 = cap.read() # Read the frame
方法2
cap = cv2.VideoCapture("test.mp4")
print(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # 1187
for i in range(601):
ret, frame2 = cap.read() # Read the frame
发布于 2022-04-29 08:27:37
要读取/获取视频的X
第四帧或类似地确定视频文件中的帧数,有两种方法:
方法1是快速的,并且依赖OpenCV的视频属性功能,它几乎即时地确定视频文件中的帧信息。然而,由于它依赖于您的OpenCV和视频编解码器版本,所以有一个精确的折衷。从文件中:
读写属性涉及许多层。一些意想不到的结果可能会发生在这条链上。有效的行为取决于设备硬件、驱动程序和API后端。
另一方面,手动计数每个帧,直到我们达到预期的帧数将是100%的准确性,虽然它将显着地慢。这里有一个示例来演示这两种方法之间的不一致行为。默认情况下,它尝试执行方法#1,如果失败,它将自动使用方法#2。
def frame_count(video_path, manual=False):
def manual_count(handler):
frames = 0
while True:
status, frame = handler.read()
if not status:
break
frames += 1
return frames
cap = cv2.VideoCapture(video_path)
# Slow, inefficient but 100% accurate method
if manual:
frames = manual_count(cap)
# Fast, efficient but inaccurate method
else:
try:
frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
except:
frames = manual_count(cap)
cap.release()
return frames
基准测试
if __name__ == '__main__':
import timeit
import cv2
start = timeit.default_timer()
print('frames:', frame_count('testtest.mp4', manual=False))
print(timeit.default_timer() - start, '(s)')
start = timeit.default_timer()
print('frames:', frame_count('testtest.mp4', manual=True))
print(timeit.default_timer() - start, '(s)')
方法1结果
frames: 3671
0.018054921 (s)
方法2结果
frames: 3521
9.447095287 (s)
注意这两种方法是如何区别150帧的,方法2比方法1要慢得多。一般来说,如果您需要速度,但愿意牺牲准确性,请使用方法1。在有延迟但需要精确框架的情况下,请使用方法2。
因此得出的结论是:当您使用cap.get
或任何内置的VideoCaptureProperties (如cv2.CAP_PROP_FRAME_COUNT
)时,实际上使用的是方法#1,它速度快、效率高,但不准确。在您的第一个示例中,当您试图使用cap.set
读取一个确切的框架时,您实际上得到了一个接近所需的X
第四帧的“估计”帧,而不是实际的X
框架。相反,从您的第二个代码片段中,您将手动逐个遍历每个帧,因此当它降落到X
第四帧时,这是绝对正确的。这就是为什么当您尝试使用每个方法读取相同的帧号时,您可能会得到不同的图像。
https://stackoverflow.com/questions/72053674
复制相似问题