Display the live webcam feed in a Jupyter notebook using OpenCV
getting started with OpenCV and Jupyter notebook
OpenCV is a popular and powerful computer vision library for Python. It allows the user to efficiently computation intensive task on images and videos, including live webcam feed. By default, OpenCV displays images in its own independent window. However, it is often more practical to visualize results directly in the notebook. Here, I'll demonstrate how to display the webcam feed in the notebook and how to setup Ipywidgets to interact with the feed.
import matplotlib.pyplot as plt
import cv2
import numpy as np
from IPython.display import display, Image
import ipywidgets as widgets
import threading
cap = cv2.VideoCapture(0)
cap.set(3,640) # adjust width
cap.set(4,480) # adjust height
while True:
success, img = cap.read()
cv2.imshow("Webcam", img) # This will open an independent window
if cv2.waitKey(1) & 0xFF==ord('q'): # quit when 'q' is pressed
cap.release()
break
cv2.destroyAllWindows()
cv2.waitKey(1) # normally unnecessary, but it fixes a bug on MacOS where the window doesn't close
Display the webcam inside the notebook
Here I combine the display code proposed here with an Ipywidget button. Since the feed is updated inside a loop, the button is not updated by default, which renders it inactive. To fix that I use the asynchronous widget update described here. Now, when clicked the button will stop the feed and remove the output. Note that the code reference your own webcam so it won't work on Google Colab.
# ================
stopButton = widgets.ToggleButton(
value=False,
description='Stop',
disabled=False,
button_style='danger', # 'success', 'info', 'warning', 'danger' or ''
tooltip='Description',
icon='square' # (FontAwesome names without the `fa-` prefix)
)
# Display function
# ================
def view(button):
cap = cv2.VideoCapture(0)
display_handle=display(None, display_id=True)
i = 0
while True:
_, frame = cap.read()
frame = cv2.flip(frame, 1) # if your camera reverses your image
_, frame = cv2.imencode('.jpeg', frame)
display_handle.update(Image(data=frame.tobytes()))
if stopButton.value==True:
cap.release()
display_handle.update(None)
# Run
# ================
display(stopButton)
thread = threading.Thread(target=view, args=(stopButton,))
thread.start()
Et voilà! The output looks like this