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

时间:2015-01-10 23:23:54

标签: opencv video ipython ipython-notebook jupyter

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

以下是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()

4 个答案:

答案 0 :(得分:3)

为了使显示更快,在笔记本中仅使用 IPython.display.display 和 JPG 格式而不是 PNG。 (注意在笔记本外部使用 cv2.imshow 本地显示要快得多,但这不是问题所要求的):

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

from IPython.display import clear_output, Image, display, HTML
import cv2

# Read one frame from the camera for testing
video = cv2.VideoCapture(0)
_, frame = video.read()
video.release()

import re
from timeit import timeit
import math

extensions=re.findall(r"\\\*(\.\w*)", cv2.imread.__doc__)

def test(extension):
    try:
        totalTime=0
        numTry=3
        for _ in range(numTry):
            totalTime+=timeit(lambda: display(Image(data=cv2.imencode(extension, frame)[1])), number=1)
            clear_output(wait=True)
        return totalTime/numTry, extension

    except cv2.error as e: #usually "unsupported file type"
        return (math.inf, extension, e)
for x in sorted(
    [test(extension) for extension in extensions], key=lambda x: x[0]
): print(x)

就我而言,.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)

update 每次都比 clear_output + display 快一点;但是与渲染相比,它并不是一个显着的改进。

答案 1 :(得分:2)

视频编码数据(如果采用浏览器可以解码的格式,例如ISO mp4容器中的h264编码)可以使用HTML <video>标记和IPython.core.display.HTML()显示,这将提供标准播放性能。

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

答案 2 :(得分:1)

您可以使用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)

答案 3 :(得分:0)

是。但它会是斯洛伐克......

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

from IPython.display import clear_output, Image, display, HTML
import numpy as np
import cv2
import base64

def arrayShow (imageArray):
    ret, png = cv2.imencode('.png', imageArray)
    encoded = base64.b64encode(png)
    return Image(data=encoded.decode('ascii'))
video = cv2.VideoCapture(0)
while(True):
    try:
        clear_output(wait=True)
        _, frame = video.read()
        lines, columns, _ =  frame.shape
        frame = cv2.resize(frame, (int(columns/4), int(lines/4))) 
        img = arrayShow(frame)
        display(img)
    except KeyboardInterrupt:
        video.release()

您可能需要更改IOPub数据速率限制。 您可以在.jupyter配置中更改此设置或只运行 jupyter notebook --NotebookApp.iopub_data_rate_limit = 1000000000

但键盘中断无法正常工作。