在 macOS 上有效地将 3D numpy 位图数组(y、x、RGB)渲染为 window(使用 openCV 或其他方式)
Efficiently render 3D numpy bitmap array (y, x, RGB) to window on macOS (using openCV or otherwise)
我正在渲染一个动态变化的 numpy 位图数组并尝试提高我的帧率。
目前我正在使用 openCV:
cv2.imshow(WINDOW_NAME, )
cv2.waitKey(1)
这需要大约 20 毫秒,这还不错。
但是我可以做得更好吗?
cv2.setWindowProperty(WINDOW_NAME, cv2.WND_PROP_OPENGL, cv2.WINDOW_OPENGL)
设置此项没有明显效果。但是 openCV 是否提供了比 imshow
更好的技术来利用 GL 绘图表面?
有什么可行的 openCV 替代品吗? import OpenGL
是经过验证的蠕虫。
REF:
您可以使用外部子进程视频渲染器渲染视频。
我通过将视频帧传输到 FFplay 来测试建议的解决方案。
该解决方案效果不佳 - 未显示最后几帧。
将解决方案视为概念解决方案。
代码打开 FFplay 作为子进程,并将原始帧写入 FFplay 的 stdin
管道。
代码如下:
import cv2
import numpy as np
import subprocess as sp
import shlex
import time
# Synthetic "raw BGR" image for testing
width, height, n_frames = 1920, 1080, 1000 # 1000 frames, resolution 1920x1080
img = np.full((height, width, 3), 60, np.uint8)
def make_bgr_frame(i):
""" Draw a blue number in the center of img """
cx, cy = width//2, height//2
l = len(str(i+1))
img[cy-20:cy+20, cx-15*l:cx+15*l, :] = 0
# Blue number
cv2.putText(
img,
str(i+1),
(cx-10*l, h+10),
cv2.FONT_HERSHEY_DUPLEX,
1,
(255, 30, 30),
2
)
# FFplay input: raw video frames from stdin pipe.
ffplay_process = sp.Popen(
shlex.split(
f'ffplay -hide_banner -loglevel error'
f' -exitonkeydown -framerate 1000 -fast'
f' -probesize 32 -flags low_delay'
f' -f rawvideo -video_size {width}x{height}'
f' -pixel_format bgr24 -an -sn -i pipe:'
),
stdin=sp.PIPE
)
t = time.time()
for i in range(n_frames):
make_bgr_frame(i)
if ffplay_process.poll() is not None:
break # Break if FFplay process is closed
try:
# Write raw video frame to stdin pipe of FFplay sub-process.
ffplay_process.stdin.write(img.tobytes())
# ffplay_process.stdin.flush()
except Exception as e:
break
elapsed = time.time() - t
arg_fps = n_frames / elapsed
print(f'FFplay elapsed time = {elapsed:.2f}')
print(f'FFplay average fps = {arg_fps:.2f}')
ffplay_process.stdin.close()
ffplay_process.terminate()
# OpenCV
##########################################################
t = time.time()
for i in range(n_frames):
make_bgr_frame(i)
cv2.imshow("img", img)
cv2.waitKey(1)
elapsed = time.time() - t
arg_fps = n_frames / elapsed
print(f'OpenCV elapsed time = {elapsed:.2f}')
print(f'OpenCV average fps = {arg_fps:.2f}')
cv2.destroyAllWindows()
##########################################################
结果(Windows 10):
FFplay elapsed time = 5.53
FFplay average fps = 180.98
OpenCV elapsed time = 6.16
OpenCV average fps = 162.32
在我的机器上差异很小。
我正在渲染一个动态变化的 numpy 位图数组并尝试提高我的帧率。
目前我正在使用 openCV:
cv2.imshow(WINDOW_NAME, )
cv2.waitKey(1)
这需要大约 20 毫秒,这还不错。
但是我可以做得更好吗?
cv2.setWindowProperty(WINDOW_NAME, cv2.WND_PROP_OPENGL, cv2.WINDOW_OPENGL)
设置此项没有明显效果。但是 openCV 是否提供了比 imshow
更好的技术来利用 GL 绘图表面?
有什么可行的 openCV 替代品吗? import OpenGL
是经过验证的蠕虫。
REF:
您可以使用外部子进程视频渲染器渲染视频。
我通过将视频帧传输到 FFplay 来测试建议的解决方案。
该解决方案效果不佳 - 未显示最后几帧。
将解决方案视为概念解决方案。
代码打开 FFplay 作为子进程,并将原始帧写入 FFplay 的 stdin
管道。
代码如下:
import cv2
import numpy as np
import subprocess as sp
import shlex
import time
# Synthetic "raw BGR" image for testing
width, height, n_frames = 1920, 1080, 1000 # 1000 frames, resolution 1920x1080
img = np.full((height, width, 3), 60, np.uint8)
def make_bgr_frame(i):
""" Draw a blue number in the center of img """
cx, cy = width//2, height//2
l = len(str(i+1))
img[cy-20:cy+20, cx-15*l:cx+15*l, :] = 0
# Blue number
cv2.putText(
img,
str(i+1),
(cx-10*l, h+10),
cv2.FONT_HERSHEY_DUPLEX,
1,
(255, 30, 30),
2
)
# FFplay input: raw video frames from stdin pipe.
ffplay_process = sp.Popen(
shlex.split(
f'ffplay -hide_banner -loglevel error'
f' -exitonkeydown -framerate 1000 -fast'
f' -probesize 32 -flags low_delay'
f' -f rawvideo -video_size {width}x{height}'
f' -pixel_format bgr24 -an -sn -i pipe:'
),
stdin=sp.PIPE
)
t = time.time()
for i in range(n_frames):
make_bgr_frame(i)
if ffplay_process.poll() is not None:
break # Break if FFplay process is closed
try:
# Write raw video frame to stdin pipe of FFplay sub-process.
ffplay_process.stdin.write(img.tobytes())
# ffplay_process.stdin.flush()
except Exception as e:
break
elapsed = time.time() - t
arg_fps = n_frames / elapsed
print(f'FFplay elapsed time = {elapsed:.2f}')
print(f'FFplay average fps = {arg_fps:.2f}')
ffplay_process.stdin.close()
ffplay_process.terminate()
# OpenCV
##########################################################
t = time.time()
for i in range(n_frames):
make_bgr_frame(i)
cv2.imshow("img", img)
cv2.waitKey(1)
elapsed = time.time() - t
arg_fps = n_frames / elapsed
print(f'OpenCV elapsed time = {elapsed:.2f}')
print(f'OpenCV average fps = {arg_fps:.2f}')
cv2.destroyAllWindows()
##########################################################
结果(Windows 10):
FFplay elapsed time = 5.53
FFplay average fps = 180.98
OpenCV elapsed time = 6.16
OpenCV average fps = 162.32
在我的机器上差异很小。