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

问题描述

运行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()

解决方案

若要加快显示速度,请仅在笔记本和jpg格式内使用IPython.display.display,而不使用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].tobytes())

然后,播放视频:

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.tobytes()))
except KeyboardInterrupt:
    pass
finally:
    video.release()
    display_handle.update(None)

update每次都比clear_output+display快一点,但与渲染相比没有明显提高。

相关文章