Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to display an OpenCV video inside the IPython /JuPyter Notebook?

When running the examples from the OpenCV video processing python tutorials, they all pop up in a dedicated window. I know that the IPython notebook can display videos from disk and YouTube, so I wonder if there is a way to direct the OpenCV video playback to the Notebook browser and have it play in the output cell instead of a separate window (preferably without saving it to disk and then playing it from there).

Below is the code from the OpenCV tutorial.

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() 
like image 334
joelostblom Avatar asked Jan 10 '15 23:01

joelostblom


People also ask

How do you display a video in a Jupyter notebook?

How do you view videos on a Jupyter Notebook? To display local video files in the Jupyter notebook, we should use an Html video tag ( <video ), and set the base64 encoded video file content to the src attribute of the Html video tag ( <video .. src='data:video/x-m4v;base64, ' ).

Can we use OpenCV in Jupyter notebook?

Type the command “pip install opencv-python” to install python lib You should see 'Successfully installed' to finish installing opencv-python. 7. Use Jupyter notebook to run python code Open the Windows Start menu in your Desktop, click “Anaconda3 (64-bit)”, and then click “Jupyter Notebook(anaconda3)”.

Can Jupyter notebook support videos?

It uses the power of the WebRTC browser API to allow video streaming inside of the Jupyter Notebook. The API of ipywebrtc is very simple: first, the user would create what we call a MediaStream widget.


2 Answers

You can do it with Bokeh and probably it is a bit faster.

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) 
like image 74
Enrico Pallazzo Avatar answered Sep 21 '22 20:09

Enrico Pallazzo


To make the display faster use only IPython.display.display inside the notebook and JPG format instead of PNG. (Note displaying with cv2.imshow natively outside the notebook is much faster, but this is not what the question asks for):

The code below will test all the supported file formats to find the fastest one (extracted from __doc__ with a regex, not reliable)

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) 

In my case, .jpeg is the fastest. Make sure that the browser display also support that extension:

Image(data=cv2.imencode(".jpeg", frame)[1].tobytes()) 

Then, to play the video:

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 is a little faster than clear_output + display every time; however compare to the rendering it isn't a significant improvement.

like image 28
user202729 Avatar answered Sep 23 '22 20:09

user202729