mirror of
https://github.com/storytold/storyteller-ml.git
synced 2026-10-16 00:13:07 +00:00
105 lines
3.8 KiB
Python
105 lines
3.8 KiB
Python
#
|
|
# based on: https://colab.research.google.com/notebooks/snippets/advanced_outputs.ipynb#scrollTo=2viqYx97hPMi
|
|
#
|
|
|
|
from IPython.display import display, Javascript
|
|
from google.colab.output import eval_js
|
|
from base64 import b64decode, b64encode
|
|
import numpy as np
|
|
import cv2
|
|
|
|
def init_camera():
|
|
"""Create objects and functions in HTML/JavaScript to access local web camera"""
|
|
|
|
js = Javascript('''
|
|
|
|
// global variables to use in both functions
|
|
var div = null;
|
|
var video = null; // <video> to display stream from local webcam
|
|
var stream = null; // stream from local webcam
|
|
var canvas = null; // <canvas> for single frame from <video> and convert frame to JPG
|
|
var img = null; // <img> to display JPG after processing with cv2
|
|
|
|
async function initCamera() {
|
|
// place for video (and eventually buttons)
|
|
div = document.createElement('div');
|
|
document.body.appendChild(div);
|
|
|
|
// <video> to display video
|
|
video = document.createElement('video');
|
|
video.style.display = 'block';
|
|
div.appendChild(video);
|
|
|
|
// get webcam stream and assing to <video>
|
|
stream = await navigator.mediaDevices.getUserMedia({video: true});
|
|
video.srcObject = stream;
|
|
|
|
// start playing stream from webcam in <video>
|
|
await video.play();
|
|
|
|
// Resize the output to fit the video element.
|
|
google.colab.output.setIframeHeight(document.documentElement.scrollHeight, true);
|
|
|
|
// <canvas> for frame from <video>
|
|
canvas = document.createElement('canvas');
|
|
canvas.width = video.videoWidth;
|
|
canvas.height = video.videoHeight;
|
|
//div.appendChild(input_canvas); // there is no need to display to get image (but you can display it for test)
|
|
|
|
// <img> for image after processing with cv2
|
|
img = document.createElement('img');
|
|
img.width = video.videoWidth;
|
|
img.height = video.videoHeight;
|
|
div.appendChild(img);
|
|
}
|
|
|
|
async function takeImage(quality) {
|
|
// draw frame from <video> on <canvas>
|
|
canvas.getContext('2d').drawImage(video, 0, 0);
|
|
|
|
// stop webcam stream
|
|
//stream.getVideoTracks()[0].stop();
|
|
|
|
// get data from <canvas> as JPG image decoded base64 and with header "data:image/jpg;base64,"
|
|
return canvas.toDataURL('image/jpeg', quality);
|
|
//return canvas.toDataURL('image/png', quality);
|
|
}
|
|
|
|
async function showImage(image) {
|
|
// it needs string "data:image/jpg;base64,JPG-DATA-ENCODED-BASE64"
|
|
// it will replace previous image in <img src="">
|
|
img.src = image;
|
|
// TODO: create <img> if doesn't exists,
|
|
// TODO: use id to use different <img> for different image - like name in cv2.imshow(name, image)
|
|
}
|
|
|
|
''')
|
|
|
|
display(js)
|
|
eval_js('initCamera()')
|
|
|
|
def take_frame(quality=0.8):
|
|
"""Get frame from web camera"""
|
|
|
|
data = eval_js('takeImage({})'.format(quality)) # run JavaScript code to get image (JPG as string base64) from <canvas>
|
|
|
|
header, data = data.split(',') # split header ("data:image/jpg;base64,") and base64 data (JPG)
|
|
data = b64decode(data) # decode base64
|
|
data = np.frombuffer(data, dtype=np.uint8) # create numpy array with JPG data
|
|
|
|
img = cv2.imdecode(data, cv2.IMREAD_UNCHANGED) # uncompress JPG data to array of pixels
|
|
|
|
return img
|
|
|
|
def show_frame(img, quality=0.8):
|
|
"""Put frame as <img src="data:image/jpg;base64,...."> """
|
|
|
|
ret, data = cv2.imencode('.jpg', img) # compress array of pixels to JPG data
|
|
|
|
data = b64encode(data) # encode base64
|
|
data = data.decode() # convert bytes to string
|
|
data = 'data:image/jpg;base64,' + data # join header ("data:image/jpg;base64,") and base64 data (JPG)
|
|
|
|
eval_js('showImage("{}")'.format(data)) # run JavaScript code to put image (JPG as string base64) in <img>
|
|
# argument in showImage needs " "
|