快速 Python 绘图库直接在 2D numpy 数组图像缓冲区上绘制绘图?
回答问题 我经常使用 opencv 绘图函数直接在来自 opencv 网络摄像头流的 2D numpy 数组图像缓冲区上绘制 2D 图。而且,我将 numpy 数组发送给 imshow 和视频编写器以监视和创建视频。 import cv2 import numpy as np cap = cv2.VideoCapture(0) ret, frame = cap.read() # frame is
回答问题
我经常使用 opencv 绘图函数直接在来自 opencv 网络摄像头流的 2D numpy 数组图像缓冲区上绘制 2D 图。而且,我将 numpy 数组发送给 imshow 和视频编写器以监视和创建视频。
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
ret, frame = cap.read() # frame is a 2D numpy array w640 h480
h,w,_ = frame.shape # (480,640,3)
x = np.arange(w)
writer = cv2.VideoWriter( 'out.avi', cv2.cv.FOURCC('D','I','V','3'),
fps=30, frameSize=(w,h), isColor=True )
while True:
ret, frame = cap.read() # frame is a 2D numpy array w640 h480
B = frame[:,:,0].sum(axis=0)
B = h - h * B / B.max()
G = frame[:,:,1].sum(axis=0)
G = h - h * G / G.max()
R = frame[:,:,2].sum(axis=0)
R = h - h * R / R.max()
pts = np.vstack((x,B)).astype(np.int32).T
cv2.polylines(frame, [pts], isClosed=False, color=(255,0,0))
pts = np.vstack((x,G)).astype(np.int32).T
cv2.polylines(frame, [pts], isClosed=False, color=(0,255,0))
pts = np.vstack((x,R)).astype(np.int32).T
cv2.polylines(frame, [pts], isClosed=False, color=(0,0,255))
writer.write(frame)
cv2.imshow('frame', frame)
key = cv2.waitKey(33) & 0xFF # for 64 bit PC
if key in 27: # ESC key
break
cap.release()
writer.release()
这很好用,但我想知道我是否可以做更多的事情,比如 matplotlib 可以做的事情,比如轴、刻度、网格、标题、条形图等,而无需基于基本的 cv2 绘图函数推出我自己的绘图库,这将是可能的,但我不想重新发明轮子。
查看https://wiki.python.org/moin/NumericAndScientific/Plotting,有很多绘图库。所以,我觉得他们中的一个可能已经这样做了。
我考虑过使用 matplotlib 并将绘图导出为savefig
的图像。但这对于视频捕获来说会很慢。
(编辑)按照接受的答案中的建议,我可以使用mplfig_to_npimage
将 matplotlib 图嵌入到框架中!对于视频速率来说,它似乎足够快。
import cv2
from pylab import *
from moviepy.video.io.bindings import mplfig_to_npimage
fp = r'C:/Users/Public/Videos/Sample Videos/Wildlife.wmv'
cap = cv2.VideoCapture(fp)
ret, frame = cap.read() # frame is a 2D numpy array
h,w,_ = frame.shape
writer = cv2.VideoWriter( 'out.avi', cv2.cv.FOURCC('D','I','V','3'),
fps=30, frameSize=(w,h), isColor=True )
# prepare a small figure to embed into frame
fig, ax = subplots(figsize=(4,3), facecolor='w')
B = frame[:,:,0].sum(axis=0)
line, = ax.plot(B, lw=3)
xlim([0,w])
ylim([40000, 130000]) # setup wide enough range here
box('off')
tight_layout()
graphRGB = mplfig_to_npimage(fig)
gh, gw, _ = graphRGB.shape
while True:
ret, frame = cap.read() # frame is a 2D numpy array
B = frame[:,:,0].sum(axis=0)
line.set_ydata(B)
frame[:gh,w-gw:,:] = mplfig_to_npimage(fig)
cv2.imshow('frame', frame)
writer.write(frame)
key = cv2.waitKey(33) & 0xFF # for 64 bit
if key in 27: # ESC key
break
cap.release()
writer.release()
Answers
所以,如果我做对了,你想要:
-
在图像上绘制概念图(路径、多边形),并带有开箱即用的指示符(轴,自动封闭图)
-
视频转储和_希望_实时流。
如果是这样,我建议将matplotlib 与 moviepy一起使用。
确实做savefig
流视频不是最好的方法,但你可以让这两个工作相当容易。
包括上面链接中的小例子以供记录(头脑许可证):
import matplotlib.pyplot as plt
import numpy as np
from moviepy.video.io.bindings import mplfig_to_npimage
import moviepy.editor as mpy
# DRAW A FIGURE WITH MATPLOTLIB
duration = 2
fig_mpl, ax = plt.subplots(1,figsize=(5,3), facecolor='white')
xx = np.linspace(-2,2,200) # the x vector
zz = lambda d: np.sinc(xx**2)+np.sin(xx+d) # the (changing) z vector
ax.set_title("Elevation in y=0")
ax.set_ylim(-1.5,2.5)
line, = ax.plot(xx, zz(0), lw=3)
# ANIMATE WITH MOVIEPY (UPDATE THE CURVE FOR EACH t). MAKE A GIF.
def make_frame_mpl(t):
line.set_ydata( zz(2*np.pi*t/duration)) # <= Update the curve
return mplfig_to_npimage(fig_mpl) # RGB image of the figure
animation =mpy.VideoClip(make_frame_mpl, duration=duration)
animation.write_gif("sinc_mpl.gif", fps=20)
更多推荐
所有评论(0)