[英]Why does OpenCV read video faster than FFMPEG?
I noticed that OpenCV reads video frames almost 2x faster than FFMPEG.我注意到 OpenCV 读取视频帧的速度几乎比 FFMPEG 快 2 倍。
Why is that?这是为什么? I thought all OpenCV does is call FFMPEG under the hood, possibly adding its own overhead.
我认为所有 OpenCV 所做的都是在引擎盖下调用 FFMPEG,可能会增加它自己的开销。
Here's the code I use to obtain these results这是我用来获得这些结果的代码
import cv2
import time
import numpy as np
cap = cv2.VideoCapture("BigBuckBunny.mp4", apiPreference=cv2.CAP_FFMPEG)
frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
start = time.perf_counter()
while True:
ret, frame = cap.read()
if ret is False:
break
assert frame.shape == (720, 1280, 3)
assert frame.dtype == np.uint8
end = time.perf_counter()
print(f"{frames/(end-start):.1f} frames per second")
# Output: 692.3 frames per second
cap.release()
For FFMPEG (using the python-ffmpeg
library:对于 FFMPEG(使用
python-ffmpeg
库:
import ffmpeg
import numpy as np
import time
vid_info = ffmpeg.probe("BigBuckBunny.mp4")['streams'][1]
frames = int(vid_info['nb_frames'])
process1 = (
ffmpeg
.input("BigBuckBunny.mp4")
.output('pipe:', format='rawvideo', pix_fmt='bgr24')
)
print(process1.compile())
# Output: ['ffmpeg', '-i', 'BigBuckBunny.mp4', '-f', 'rawvideo', '-pix_fmt', 'bgr24', 'pipe:']
process1 = process1.run_async(pipe_stdout=True)
start = time.perf_counter()
while True:
in_bytes = process1.stdout.read(1280 * 720 * 3)
if not in_bytes:
break
frame = np.frombuffer(in_bytes, np.uint8).reshape([720, 1280, 3])
end = time.perf_counter()
print(f"{frames/(end-start):.1f} frames per second")
# Output: 373.6 frames per second
process1.wait()
Here's information about the video (~10 minutes length)这是有关视频的信息(约 10 分钟长度)
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'BigBuckBunny.mp4':
Metadata:
major_brand : mp42
minor_version : 0
compatible_brands: isomavc1mp42
creation_time : 2010-01-10T08:29:06.000000Z
Duration: 00:09:56.47, start: 0.000000, bitrate: 2119 kb/s
Stream #0:0(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 125 kb/s (default)
Metadata:
creation_time : 2010-01-10T08:29:06.000000Z
handler_name : (C) 2007 Google Inc. v08.13.2007.
vendor_id : [0][0][0][0]
Stream #0:1(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 1991 kb/s, 24 fps, 24 tbr, 24k tbn, 48 tbc (default)
Metadata:
creation_time : 2010-01-10T08:29:06.000000Z
handler_name : (C) 2007 Google Inc. v08.13.2007.
vendor_id : [0][0][0][0]
And FFMPEG and OpenCV versions:以及 FFMPEG 和 OpenCV 版本:
ffmpeg version 4.4.2-0ubuntu0.22.04.1 Copyright (c) 2000-2021 the FFmpeg developers
opencv-python-headless 4.6.0.66
It may be due to the fact how the libraries are implemented and the overhead of pipes.这可能是由于库的实现方式和管道的开销。
cv2 implemented in c++ and uses libavcodec
library (part of ffmpeg) for decoding frames: cv2 在 c++ 中实现,并使用
libavcodec
库(ffmpeg 的一部分)来解码帧:
https://github.com/opencv/opencv/blob/97c6ec6d49cb78321eafe6fa220ff80ebdc5e2f4/modules/videoio/src/cap_ffmpeg_impl.hpp#L1299 https://github.com/opencv/opencv/blob/97c6ec6d49cb78321eafe6fa220ff80ebdc5e2f4/modules/videoio/src/cap_ffmpeg_impl.hpp#L1299
cv2 does not use ffmpeg
as binary executable and uses the part of ffmpeg specifically designed for reading/decoding frames. cv2 不使用
ffmpeg
作为二进制可执行文件,而是使用专为读取/解码帧而设计的 ffmpeg 的一部分。
libavcodec
under the hood too) that calls ffmpeg
with subprocess
and returns results through the pipes. libavcodec
),它使用subprocess
进程调用ffmpeg
并通过管道返回结果。 Good stuff.好东西。 Interestingly, under Windows 10 & FFmpeg 5.0.1, my results are the reverse of yours (but much closer):
有趣的是,在 Windows 10 & FFmpeg 5.0.1 下,我的结果与你的相反(但更接近):
491.9 frames per second
491.9 frames per second
519.4 frames per second
519.4 frames per second
And out of curiosity, I tried my ffmpegio
package to see how much overhead it incurs, it came out: 507.5 frames per second
(code below) Both FFmpeg-Python and FFmpegIO scoring in the same ballpark indicates these numbers aren't fluke.出于好奇,我尝试了我的
ffmpegio
package 来查看它会产生多少开销,结果是: 507.5 frames per second
(代码如下) FFmpeg-Python 和 FFmpegIO 在同一个球场上的得分表明这些数字并非侥幸。
So, it's likely Win/Linux or 4.4/5.0 differences or both.因此,很可能是 Win/Linux 或 4.4/5.0 差异或两者兼而有之。 I retested FFmpeg-Python with FFmpeg 4.4.1 and got:
428.1 frames per second
(log reporting speed=17.9x
down from x21.7
. I'd say FFmpeg devs optimized the color conversion codebase in v5 releases to match or surpass OpenCV. (Or the tested OpenCV version uses the libav
libraries associated with FFmpeg v5) I retested FFmpeg-Python with FFmpeg 4.4.1 and got:
428.1 frames per second
(log reporting speed=17.9x
down from x21.7
. I'd say FFmpeg devs optimized the color conversion codebase in v5 releases to match or surpass OpenCV. (或者测试的 OpenCV 版本使用与libav
v5 关联的 libav 库)
test_ffmpegio.py
import ffmpegio
import time
frames = ffmpegio.probe.video_streams_basic("BigBuckBunny.mp4")[0]['nb_frames']
print(frames)
with ffmpegio.open("BigBuckBunny.mp4",'rv') as f:
start = time.perf_counter()
for frame in f:
pass # frame is 1x1280x720x3 rgb np array
end = time.perf_counter()
print(f"{frames/(end-start):.1f} frames per second")
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.