我需要一种方法,可以每N秒捕获一帧和一帧。我以为,所有需要的是用VideoCapture
创建cap = cv2.VideoCapture(1)
对象并每N秒调用_, frame = cap.read()
。
但是,如图所示,VideoCapture
拥有自己的缓冲区,默认情况下设置为4。这意味着,我必须打电话给cap.read
4次,然后才能从另一个时间跨度获取帧。
我发现,我可以使用cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
缩小缓冲区大小,但是不能为0。这意味着,我仍然需要丢弃1帧才能得到所需的帧。< / p>
除了这样的解决方案是a部之外,每次cap.read()
的调用都非常慢-在我的计算机上为68 ms-我需要每次调用两次。
video = cv2.VideoCapture(0)
video.set(cv2.CAP_PROP_BUFFERSIZE, 1)
### read() is actually grab() + retrieve()
########## Tests
# %%timeit
# 68 ms ± 30.5 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
# video.read()
# %%timeit
# 68 ms ± 51.9 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
# video.grab()
# video.retrieve()
# %%timeit
# 68 ms ± 2.25 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
# video.grab()
# %%timeit
# 134 ms ± 4.71 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# video.grab()
# video.grab()
# %%timeit
# 1.06 s ± 2.13 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# video = cv2.VideoCapture(1)
# video.read()
# video.release()
##########
def frame_generator(video):
while (video.isOpened()):
video.grab()
video.grab()
success, frame = video.retrieve()
if success:
yield frame
else:
yield False
gen_frame = frame_generator(cap)
# %%timeit
# 136 ms ± 17.9 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
# next(gen_frame)