是否可以在IPython/JuPyter笔记本中显示OpenCV视频?

是否可以在IPython/JuPyter笔记本中显示OpenCV视频?,python,opencv,jupyter-notebook,ipython,jupyter,Python,Opencv,Jupyter Notebook,Ipython,Jupyter,当运行OpenCV视频处理python教程中的示例时,它们都会在专用窗口中弹出。我知道IPython笔记本可以显示来自磁盘和YouTube的视频,因此我想知道是否有办法将OpenCV视频播放引导到笔记本浏览器,并让它在输出单元而不是单独的窗口中播放(最好不将其保存到磁盘,然后从那里播放) 下面是OpenCV教程中的代码 import cv2 cap = cv2.VideoCapture('/path/to/video') while(True): # Capture frame-b

当运行OpenCV视频处理python教程中的示例时,它们都会在专用窗口中弹出。我知道IPython笔记本可以显示来自磁盘和YouTube的视频,因此我想知道是否有办法将OpenCV视频播放引导到笔记本浏览器,并让它在输出单元而不是单独的窗口中播放(最好不将其保存到磁盘,然后从那里播放)

下面是OpenCV教程中的代码

import cv2

cap = cv2.VideoCapture('/path/to/video') 

while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()

    # Our operations on the frame come here
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # Display the resulting frame
    cv2.imshow('frame',gray)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
视频编码数据(如果采用浏览器可以解码的格式,例如ISO mp4容器中编码的h264)可以使用HTML
标记和
IPython.core.display.HTML()
显示,这将提供标准的播放性能


可以是链接,也可以嵌入base64'ed数据(例如,后者就是
matplotlib.animation
所做的),其数据当然可以使用OpenCV(例如
VideoWriter
)在笔记本中生成。

是。但这将是缓慢的

使用Python 3和OpenCV 3.3从网络摄像头读取的代码(从文件中,只需更改cv2.VideoCapture(“filename.mp4”):

您可能需要更改IOPub数据速率限制。 您可以在.jupyter配置中更改此设置,也可以直接运行 jupyter笔记本--NotebookApp.iopub\u数据\u速率\u限制=100000000


不过,键盘中断无法正常工作。

您可以使用Bokeh来完成,而且速度可能会快一点

from bokeh.plotting import figure
from bokeh.io import output_notebook, show, push_notebook
import cv2
import time
output_notebook()

cap = cv2.VideoCapture(0)
ret, frame = cap.read()
frame=cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA) # because Bokeh expects a RGBA image
frame=cv2.flip(frame, -1) # because Bokeh flips vertically
width=frame.shape[1]
height=frame.shape[0]
p = figure(x_range=(0,width), y_range=(0,height), output_backend="webgl", width=width, height=height)
myImage = p.image_rgba(image=[frame], x=0, y=0, dw=width, dh=height)
show(p, notebook_handle=True)
while True:
    ret, frame = cap.read()
    frame=cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
    frame=cv2.flip(frame, -1)
    myImage.data_source.data['image']=[frame]
    push_notebook()
    time.sleep(0.3)

要加快显示速度,请仅在笔记本内使用
IPython.display.display
,并使用JPG格式而不是PNG格式。(注意:在笔记本电脑外部使用
cv2.imshow
本机显示要快得多,但这不是问题要求的):

下面的代码将测试所有受支持的文件格式,以找到最快的文件格式(使用正则表达式从
\uuuuuu doc\uuuuuu
中提取,不可靠)

在我的例子中,
.jpeg
是最快的。确保浏览器显示也支持该扩展:

Image(data=cv2.imencode(".jpeg", frame)[1].tostring())
然后,播放视频:

import cv2
from IPython.display import display, Image

video = cv2.VideoCapture(0)
display_handle=display(None, display_id=True)
try:
    while True:
        _, frame = video.read()
        frame = cv2.flip(frame, 1) # if your camera reverses your image
        _, frame = cv2.imencode('.jpeg', frame)
        display_handle.update(Image(data=frame.tostring()))
except KeyboardInterrupt:
    pass
finally:
    video.release()
    display_handle.update(None)

更新
每次都比
清除输出
+
显示
快一点;然而,与渲染相比,这并不是一个显著的改进。

我也在寻找这个,但还没有找到任何解决方案。。。我想这是不可能的,因为只要窗口存在,内核就会保持活动状态。因此,如果窗口在工作簿中,那么我们无法关闭它,这意味着当前单元格将运行其代码,等等。请检查此项:@EzerK提供的链接可以被视为解决方案。我尝试了@EzerK提供的解决方案。它确实会在笔记本电脑中显示视频,但帧速率非常低,因此视频看起来不稳定。我试着用python3.5和opencv3 v3.1.0从我的网络摄像头中进行流媒体传输。我的磁盘上的视频根本无法播放。@moondra没有,但自从我上次发表评论以来,我一直没有积极地关注这一点,所以如果你四处看看,你可能会发现一些东西。谢谢你的建议。不幸的是,这对我不起作用。我尝试使用磁盘上的一个文件,但视频明显滞后,每几秒钟只前进1帧(我尝试了JupyterNotebook和JupyterLab)。播放是否像在专用播放器(如VLC)中播放视频一样流畅?效果很好!您可以很容易地从菜单中断。请注意,最新版本的bokeh需要uint32的(w,h)数组,而opencv输出uint8的(w,h,4)数组。所以有必要在它们之间进行转换。(使用frame=frame.view(dtype=numpy.uint8)。重塑(例如frame.shape[:2]),尽管我仍然发现这种方法比使用带有jpeg格式的IPython.display慢一点(请参阅),并且比单独窗口中的cv2.imshow慢得多。在python3中,您应该将
图像(data=encoded.decode('ascii')
更改为
图像(data=png)
您需要在
块中添加
中断
,但
块除外。
Image(data=cv2.imencode(".jpeg", frame)[1].tostring())
import cv2
from IPython.display import display, Image

video = cv2.VideoCapture(0)
display_handle=display(None, display_id=True)
try:
    while True:
        _, frame = video.read()
        frame = cv2.flip(frame, 1) # if your camera reverses your image
        _, frame = cv2.imencode('.jpeg', frame)
        display_handle.update(Image(data=frame.tostring()))
except KeyboardInterrupt:
    pass
finally:
    video.release()
    display_handle.update(None)