Spaces:
Sleeping
Sleeping
"""The VideoStreamInterface provides an easy way to apply transforms to a video stream""" | |
import numpy as np | |
import panel as pn | |
import param | |
import skimage | |
from PIL import Image, ImageFilter | |
from skimage import data, filters | |
from skimage.color.adapt_rgb import adapt_rgb, each_channel | |
from skimage.draw import rectangle | |
from skimage.exposure import rescale_intensity | |
from skimage.feature import Cascade | |
from videostream_utils import PILImageTransform, NumpyImageTransform, VideoStreamInterface | |
pn.extension("terminal", sizing_mode="stretch_width") | |
ACCENT = "#fef3c7" | |
class GaussianBlur(PILImageTransform): | |
"""Gaussian Blur | |
https://pillow.readthedocs.io/en/stable/reference/ImageFilter.html#PIL.ImageFilter.GaussianBlur | |
""" | |
radius = param.Integer(default=2, bounds=(0, 10)) | |
def transform(self, image: Image): | |
return image.filter(ImageFilter.GaussianBlur(radius=self.radius)) | |
class GrayscaleTransform(NumpyImageTransform): | |
"""GrayScale transform | |
https://scikit-image.org/docs/0.15.x/auto_examples/color_exposure/plot_rgb_to_gray.html | |
""" | |
def transform(self, image: np.ndarray): | |
grayscale = skimage.color.rgb2gray(image[:, :, :3]) | |
return skimage.color.gray2rgb(grayscale) | |
class SobelTransform(NumpyImageTransform): | |
"""Sobel Transform | |
https://scikit-image.org/docs/0.15.x/auto_examples/color_exposure/plot_adapt_rgb.html | |
""" | |
def transform(self, image): | |
def sobel_each(image): | |
return filters.sobel(image) | |
return rescale_intensity(1 - sobel_each(image)) | |
def get_detector(): | |
"""Returns the Cascade detector""" | |
trained_file = data.lbp_frontal_face_cascade_filename() | |
return Cascade(trained_file) | |
class FaceDetectionTransform(NumpyImageTransform): | |
"""Face detection using a cascade classifier. | |
https://scikit-image.org/docs/0.15.x/auto_examples/applications/plot_face_detection.html | |
""" | |
scale_factor = param.Number(1.4, bounds=(1.0, 2.0), step=0.1) | |
step_ratio = param.Integer(1, bounds=(1, 10)) | |
size_x = param.Range(default=(60, 322), bounds=(10, 500)) | |
size_y = param.Range(default=(60, 322), bounds=(10, 500)) | |
def transform(self, image): | |
detector = get_detector() | |
detected = detector.detect_multi_scale( | |
img=image, | |
scale_factor=self.scale_factor, | |
step_ratio=self.step_ratio, | |
min_size=(self.size_x[0], self.size_y[0]), | |
max_size=(self.size_x[1], self.size_y[1]), | |
) | |
for patch in detected: | |
rrr, ccc = rectangle( | |
start=(patch["r"], patch["c"]), | |
extent=(patch["height"], patch["width"]), | |
shape=image.shape[:2], | |
) | |
image[rrr, ccc, 0] = 200 | |
return image | |
component = VideoStreamInterface( | |
transforms=[ | |
GaussianBlur, | |
GrayscaleTransform, | |
SobelTransform, | |
FaceDetectionTransform, | |
] | |
) | |
component.video_stream.timeout=1000 | |
component.video_stream.param.timeout.bounds=(250, 2000) | |
pn.template.FastListTemplate( | |
site="Awesome Panel 🤗", | |
title="VideoStream with transforms", | |
sidebar=[component.settings], | |
main=[ | |
"""Try a much, much faster version <a href="https://sharing.awesome-panel.org/MarcSkovMadsen/videostream-interface/app.html" target="_blank">here</a> powered by Webassembly.""", | |
component], | |
favicon="https://sharing.awesome-panel.org/favicon.ico", | |
accent=ACCENT, | |
header_color="#4b5563" | |
).servable() |