使用实时相机预览更新 matplotlib 中的帧

Posted

技术标签:

【中文标题】使用实时相机预览更新 matplotlib 中的帧【英文标题】:update frame in matplotlib with live camera preview 【发布时间】:2017-11-19 18:07:20 【问题描述】:

我是 Python 和 Matplotlib 的新手。我的计算机连接到两个 USB 摄像头,我打算使用 matplotlib 中的 subplot(1,2,1) 和 subplot(1,2,2) 以时间序列绘制来自两个摄像头的帧。当我使用我的代码执行此操作时,我要么只绘制一帧,要么在绘图区域出现黑屏。

我的代码如下所示

#import
import cv2
import matplotlib.pyplot as plt

#Initiate the two cameras
cap1 = cv2.VideoCapture(0)
cap2 = cv2.VideoCapture(1)

#Capture the frames from camera 1 and 2 and display them over time using matplotlib

while True:
    #grab frame from camera 1 and 2
    ret1,frame1 = cap1.read()
    ret2,frame2 = cap2.read()

    plt.subplot(1,2,1), plt.imshow(cv2.cvtColor(frame1,cv2.COLOR_BGR2RGB))
    plt.subplot(1,2,2), plt.imshow(cv2.cvtColor(frame2,cv2.COLOR_BGR2RGB))

    #draw the plot
    plt.show(False)
    #Result is black screen. If plt.show() is called, I see the frames but then it freezes.

【问题讨论】:

这不是您问题的直接答案,但如果您愿意放弃使用 matplotlib,请考虑以下事项:***.com/questions/5089927/… 感谢您的评论。我实际上已经看到了您提到的功能。这里的目的是在相机视图中放置一些对象,因此,在正确放置对象的同时能够实时查看图像至关重要。用 matplotlib 不能做到这一点真的是真的吗? 【参考方案1】:

交互模式

在 matplotlib 中更新绘图的一种方法是使用交互模式 (plt.ion())。 然后,您不应为捕获的每一帧重新创建新的子图,而是使用图像创建一次图,然后再更新它。

import cv2
import matplotlib.pyplot as plt

def grab_frame(cap):
    ret,frame = cap.read()
    return cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)

#Initiate the two cameras
cap1 = cv2.VideoCapture(0)
cap2 = cv2.VideoCapture(1)

#create two subplots
ax1 = plt.subplot(1,2,1)
ax2 = plt.subplot(1,2,2)

#create two image plots
im1 = ax1.imshow(grab_frame(cap1))
im2 = ax2.imshow(grab_frame(cap2))

plt.ion()

while True:
    im1.set_data(grab_frame(cap1))
    im2.set_data(grab_frame(cap2))
    plt.pause(0.2)

plt.ioff() # due to infinite loop, this gets never called.
plt.show()

FuncAnimation

当然,另一种选择是使用 matplotlib 内置的 FuncAnimation,它专门用于动画绘图。

import cv2
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

def grab_frame(cap):
    ret,frame = cap.read()
    return cv2.cvtColor(frame,cv2.COLOR_BGR2RGB)

#Initiate the two cameras
cap1 = cv2.VideoCapture(0)
cap2 = cv2.VideoCapture(1)

#create two subplots
ax1 = plt.subplot(1,2,1)
ax2 = plt.subplot(1,2,2)

#create two image plots
im1 = ax1.imshow(grab_frame(cap1))
im2 = ax2.imshow(grab_frame(cap2))

def update(i):
    im1.set_data(grab_frame(cap1))
    im2.set_data(grab_frame(cap2))
    
ani = FuncAnimation(plt.gcf(), update, interval=200)
plt.show()

为了在按键事件上关闭窗口,你可以添加一个回调,像这样

#... other code
ani = FuncAnimation(plt.gcf(), update, interval=200)

def close(event):
    if event.key == 'q':
        plt.close(event.canvas.figure)

cid = plt.gcf().canvas.mpl_connect("key_press_event", close)

plt.show()

# code that should be executed after window is closed.

【讨论】:

这个真的很有帮助。是否有任何可能性允许用户在不使用 CTRL + C 键的情况下按下一个键来退出 while True:... 循环?这是为了允许执行脚本中的下一行。我已经尝试过 cv2.waitkey,但它似乎没有帮助 您到底想要发生什么?所以用户按下键'Q'然后?窗户应该关闭还是应该保持打开状态?你在哪个环境下运行这个?作为脚本? 我正在使用 Python 在 Windows 计算机上运行它。当用户按下 'q' 键时,窗口应该关闭并退出 while 循环。现在我已经将我的代码修改为 while True: frame1 = grab_frame(cap1) im1.set_data(frame1) im2.set_data(frame1) plt.pause(0.1) k = cv2.waitKey(1) & 0xFF if k==ord ('q'): break 但是在运行代码时,当我在键盘上输入 q 时没有任何反应。 cv2.waitKey(1) 是一个 opencv 命令,在使用 matplotlib 时不起作用。你有什么理由想按一个键而不是点击窗口的 X 来关闭它? 我不知道 cv2.waitKey 不适用于 matplotlib。按下 X 并关闭窗口很好,但我想退出 while 循环并继续我的 python 脚本。现在,当点击 X 时,还会阻止脚本在 while 循环之外运行后续行。无论如何要继续在while循环之外运行后续行?

以上是关于使用实时相机预览更新 matplotlib 中的帧的主要内容,如果未能解决你的问题,请参考以下文章

从实时相机预览中获取特定像素的颜色 - Ionic

如何设置Android Camera2预览画面的帧率(FPS)?

Android:实时图像处理

倒置相机预览字节数组[重复]

检测实时android相机预览的颜色代码

如何使用 Android 在相机预览中添加卡通脸