快速Python绘图库直接在2D numpy数组图像缓冲区上绘制绘图?

快速Python绘图库直接在2D numpy数组图像缓冲区上绘制绘图?,python,opencv,numpy,matplotlib,Python,Opencv,Numpy,Matplotlib,我经常使用opencv绘图函数直接在来自opencv网络摄像头流的2D numpy数组图像缓冲区上绘制2D绘图。然后,我将numpy数组发送给imshow和video writer来监视和创建视频 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,

我经常使用opencv绘图函数直接在来自opencv网络摄像头流的2D numpy数组图像缓冲区上绘制2D绘图。然后,我将numpy数组发送给imshow和video writer来监视和创建视频

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绘图功能的自己的绘图库,这是可能的,但我不想重新发明轮子

展望未来,有很多绘图库。所以,我觉得其中一个可能已经这样做了

我考虑使用matplotlib并通过
savefig
将绘图导出为图像。但这对于视频捕获来说会很慢

(编辑)我可以按照公认答案中的建议,使用
mplfig\u to\u 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()

所以,如果我没弄错,你想:

  • 在图像上使用开箱即用的指示器(轴、自动封闭打印)打印概念图形(路径、多边形)
  • 视频转储和实时流媒体
如果是这样,我建议使用

实际上,使用
savefig
来流式传输视频并不是最好的方法,但是您可以使这两种方法非常容易地工作

包括上面链接中记录的小示例(mind许可证):


查看并感谢您的评论,但opencv有一组非常类似的原始绘图功能,如scikit image和PIL/pillow中的功能。我所想的是比用于绘图的直线、多边形和圆更高级的函数。例如,自动设置x轴和y轴的间隔刻度等。我注意到另一个解决方案是opencv_contrib绘图模块,它最近被合并。听起来太棒了!谢谢你的分享。这个
mplfig\u to\u npimage
似乎正是我想要的。。。我要试试看!
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)