首页 > 其他分享 >前端开发笔记[4]-Gradio搭建演示页面

前端开发笔记[4]-Gradio搭建演示页面

时间:2023-11-04 16:46:52浏览次数:40  
标签:Gradio gradio 前端开发 video np btn image fn 页面

摘要

使用Gradio在Python环境搭建图像处理和视频处理的演示网页.

Gradio简介

[https://www.gradio.app]
Gradio是一个开源的Python库,用于构建机器学习和数据科学演示应用。它可以帮助AI算法工程师将训练的模型分享给大众,并赋予模型与用户交互的能力。使用Gradio,你可以通过几行代码快速创建一个简单漂亮的用户界面,围绕你的机器学习模型或数据科学工作流程。Gradio支持多种输入输出格式,如图像分类中的图像到标签、超分辨率中的图像到图像等。它还可以生成可外部访问的链接,方便你与朋友、同事分享你的算法。

Gradio的优势包括自动生成页面且可交互、改动几行代码就能完成、支持自定义多种输入输出、支持生成可外部访问的链接进行分享。它已经被许多优秀的开源项目使用来构建演示页面。使用Gradio的步骤包括安装Gradio库和编写相应的代码。

总之,Gradio是一个方便快捷的工具,可以帮助你将机器学习模型转化为交互式的Web应用,使其更易于分享和使用。

GradioLite简介

[https://www.gradio.app/playground]

  • 可以无需网页服务器,直接运行在浏览器
    All the demos on this page are interactive - meaning you can change the code and the embedded demo will update automatically. Use this as a space to explore and play around with Gradio. This is made possible thanks to the Gradio Lite package.
    GradioLite是一个在浏览器中完全运行的无服务器Gradio。它是Gradio的轻量级版本,旨在提供简单易用的界面来展示和测试机器学习模型,而无需搭建服务器。GradioLite允许用户在本地环境中加载和运行模型,以进行实时的交互式预测。

使用GradioLite,您可以通过简单的代码将模型与用户界面进行绑定,从而创建一个交互式的应用程序。您可以定义输入和输出的类型,并为它们提供适当的界面元素,如文本框、滑块、下拉菜单等。然后,您可以使用GradioLite的预测函数将输入传递给模型,并将输出显示给用户。

GradioLite的主要优点是它的易用性和轻量级性质。它不需要复杂的服务器设置,可以在本地环境中快速部署和运行。此外,GradioLite支持多种输入和输出类型,包括文本、图像、音频和视频,使其适用于各种机器学习任务。

Gradio的两种布局方式:Interface和Block

Gradio提供了两种布局方式:Interface(界面)和Block(块)。

Interface是Gradio的高级抽象API,它提供了一种简单的方式来创建交互式的Web应用和演示。使用Interface,您可以通过定义输入和输出的类型来快速构建一个应用程序,并将其展示给用户。Interface的布局是自动排列的,它会根据输入和输出的类型自动创建适当的界面元素,如文本框、滑块等。这种布局方式适用于简单的场景,可以快速搭建一个交互页面。

Block是Gradio的低级API,它提供了更灵活和可定制的布局选项,使用户能够创建更复杂的Web应用和演示。使用Block,您可以自由地设计和排列组件,创建自定义的布局。Block提供了多种布局元素,如Row(行布局)、Column(列布局)、Tab(标签页布局)等,您可以根据需要选择合适的布局方式。这种布局方式适用于需要更多灵活性和控制的场景。

总结起来,Interface适用于简单的场景,提供了自动排列的布局方式;而Block适用于更复杂的场景,提供了更灵活和可定制的布局选项。

Gradio内嵌CSS和JS

[https://www.gradio.app/guides/custom-CSS-and-JS]
You can elem_id to add an HTML element id to any component, and elem_classes to add a class or list of classes. This will allow you to select elements more easily with CSS. This approach is also more likely to be stable across Gradio versions as built-in class names or ids may change (however, as mentioned in the warning above, we cannot guarantee complete compatibility between Gradio versions if you use custom CSS as the DOM elements may themselves change).
Event listeners have a _js argument that can take a Javascript function as a string and treat it just like a Python event listener function. You can pass both a Javascript function and a Python function (in which case the Javascript function is run first) or only Javascript (and set the Python fn to None).

实现

Gradio网页服务器

import cv2
import gradio
import random
import numpy as np
import os
import subprocess
import time
import shutil
from PIL import Image

##################start 功能函数##################
def fn_gray(image):
    '''
    图片转灰度函数
    '''
    output = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    return output

def fn_binary(image):
    '''
    将图像转换为二值图函数
    '''
    gray_image = fn_gray(image)
    _, binary_image = cv2.threshold(gray_image, 128, 255, cv2.THRESH_BINARY)
    return binary_image

def fn_salt_and_pepper_noise(image, prob=random.randint(1,100)):
    '''
    添加椒盐噪声函数
    参数:
    - image: 输入的图像
    - prob: 噪声概率,即每个像素被噪声影响的概率
    返回:
    - noisy_image: 添加了椒盐噪声的图像
    '''
    noisy_image = np.copy(image)
    h, w = noisy_image.shape[:2]
    num_noise_pixels = int(prob * h * w)
    
    # 随机选择像素位置并添加噪声
    for _ in range(num_noise_pixels):
        x = np.random.randint(0, w)
        y = np.random.randint(0, h)
        noisy_image[y, x] = 0 if np.random.rand() < 0.5 else 255
    
    return noisy_image

def fn_remove_noise(image, kernel_size=random.randint(1,100)):
    '''
    去除噪声函数
    参数:
    - image: 输入的图像
    - kernel_size: 平滑滤波器的大小
    返回:
    - denoised_image: 去除噪声后的图像
    '''
    denoised_image = cv2.medianBlur(image, kernel_size)
    return denoised_image

def fn_open_operation(image, kernel_size=random.randint(1,100)):
    '''
    开运算函数
    参数:
    - image: 输入的图像
    - kernel_size: 开运算的核大小
    返回:
    - opened_image: 开运算后的图像
    '''
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, kernel_size)
    opened_image = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel)
    return opened_image

def fn_close_operation(image: np.ndarray, kernel_size: int = 3) -> np.ndarray:
    '''
    闭运算函数
    参数:
    - image: 输入的图像
    - kernel_size: 卷积核大小,默认为3
    返回:
    - closed_image: 闭运算后的图像
    '''
    kernel = np.ones((kernel_size, kernel_size), np.uint8)
    closed_image = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernel)
    return closed_image

def fn_connected_domains(image: np.ndarray) -> np.ndarray:
    '''
    连通域函数
    参数:
    - image: 输入的二值图像
    返回:
    - labeled_image: 标记了连通域的图像
    - num_labels: 连通域的数量
    '''
    _, labeled_image = cv2.connectedComponents(image)
    num_labels = np.max(labeled_image)
    return labeled_image

def fn_erosion(image: np.ndarray, kernel_size: int = 3) -> np.ndarray:
    '''
    腐蚀函数
    参数:
    - image: 输入的图像
    - kernel_size: 卷积核大小,默认为3
    返回:
    - eroded_image: 腐蚀后的图像
    '''
    kernel = np.ones((kernel_size, kernel_size), np.uint8)
    eroded_image = cv2.erode(image, kernel, iterations=1)
    return eroded_image

def fn_dilation(image: np.ndarray, kernel_size: int = 3) -> np.ndarray:
    '''
    膨胀函数
    参数:
    - image: 输入的图像
    - kernel_size: 卷积核大小,默认为3
    返回:
    - dilated_image: 膨胀后的图像
    '''
    kernel = np.ones((kernel_size, kernel_size), np.uint8)
    dilated_image = cv2.dilate(image, kernel, iterations=1)
    return dilated_image

def fn_watermark(image: np.ndarray, watermark: np.ndarray = [[1,0],[0,1]]) -> np.ndarray:
    '''
    添加水印函数
    参数:
    - image: 输入的图像
    - watermark: 水印图像
    返回:
    - watermarked_image: 添加水印后的图像
    '''
    watermarked_image = cv2.addWeighted(image, 1, watermark, 0.5, 0)
    return watermarked_image

def fn_gaussian_filter(image: np.ndarray, kernel_size: int = 3, sigma: float = 0) -> np.ndarray:
    '''
    高斯滤波函数
    参数:
    - image: 输入的图像
    - kernel_size: 卷积核大小,默认为3
    - sigma: 高斯核标准差,默认为0
    返回:
    - filtered_image: 滤波后的图像
    '''
    filtered_image = cv2.GaussianBlur(image, (kernel_size, kernel_size), sigma)
    return filtered_image

def fn_median_filter(image: np.ndarray, kernel_size: int = 3) -> np.ndarray:
    '''
    中值滤波函数
    参数:
    - image: 输入的图像
    - kernel_size: 卷积核大小,默认为3
    返回:
    - filtered_image: 滤波后的图像
    '''
    filtered_image = cv2.medianBlur(image, kernel_size)
    return filtered_image

def fn_mean_filter(image: np.ndarray, kernel_size: int = 3) -> np.ndarray:
    '''
    均值滤波函数
    参数:
    - image: 输入的图像
    - kernel_size: 卷积核大小,默认为3
    返回:
    - filtered_image: 滤波后的图像
    '''
    kernel = np.ones((kernel_size, kernel_size), np.float32) / (kernel_size * kernel_size)
    filtered_image = cv2.filter2D(image, -1, kernel)
    return filtered_image

def fn_gray_mapping(image: np.ndarray) -> np.ndarray:
    '''
    灰度映射函数
    参数:
    - image: 输入的图像
    - mapping_func: 灰度映射函数
    返回:
    - mapped_image: 映射后的图像
    '''
    mapped_image = fn_binary(image)
    return mapped_image

def fn_image_enhancement(image: np.ndarray) -> np.ndarray:
    '''
    图像增强函数
    参数:
    - image: 输入的图像
    - enhancement_func: 图像增强函数
    返回:
    - enhanced_image: 增强后的图像
    '''
    #enhanced_image = enhancement_func(image)
    return image

def fn_walsh_transform(signal: np.ndarray) -> np.ndarray:
    '''
    Walsh变换函数
    参数:
    - signal: 输入的信号
    返回:
    - transformed_signal: 变换后的信号
    '''
    transformed_signal = np.fft.ifftshift(np.fft.fft(signal))
    return transformed_signal

def fn_hadamard_transform(signal: np.ndarray) -> np.ndarray:
    '''
    Hadamard变换函数
    参数:
    - signal: 输入的信号
    返回:
    - transformed_signal: 变换后的信号
    '''
    transformed_signal = np.fft.ifftshift(np.fft.fft(signal))
    return transformed_signal

def fn_1d_dct(signal: np.ndarray) -> np.ndarray:
    '''
    一维离散余弦变换函数
    参数:
    - signal: 输入的信号
    返回:
    - transformed_signal: 变换后的信号
    '''
    transformed_signal = np.fft.ifftshift(np.fft.fft(signal))
    return transformed_signal

def fn_2d_dct(image: np.ndarray) -> np.ndarray:
    '''
    二维离散余弦变换函数
    参数:
    - image: 输入的图像
    返回:
    - transformed_image: 变换后的图像
    '''
    transformed_image = cv2.dct(image)
    return transformed_image

def fn_2d_continuous_fourier_transform(image: np.ndarray) -> np.ndarray:
    '''
    二维连续傅里叶变换函数
    参数:
    - image: 输入的图像
    返回:
    - transformed_image: 变换后的图像
    '''
    transformed_image = np.fft.fft2(image)
    return transformed_image

def fn_2d_discrete_fourier_transform(image: np.ndarray) -> np.ndarray:
    '''
    二维离散傅里叶变换函数
    参数:
    - image: 输入的图像
    返回:
    - transformed_image: 变换后的图像
    '''
    transformed_image = np.fft.fftshift(np.fft.fft2(image))
    return transformed_image

def fn_continuous_wavelet_transform(signal: np.ndarray) -> np.ndarray:
    '''
    连续小波变换函数
    参数:
    - signal: 输入的信号
    - wavelet: 小波函数
    返回:
    - transformed_signal: 变换后的信号
    '''
    #transformed_signal = pywt.cwt(signal, wavelet)
    return signal

def fn_1d_discrete_wavelet_transform(signal: np.ndarray) -> np.ndarray:
    '''
    一维离散小波变换函数
    参数:
    - signal: 输入的信号
    - wavelet: 小波函数
    返回:
    - transformed_signal: 变换后的信号
    '''
    #transformed_signal = pywt.wavedec(signal, wavelet)
    return signal

def fn_2d_discrete_wavelet_transform(image: np.ndarray) -> np.ndarray:
    '''
    二维离散小波变换函数
    参数:
    - image: 输入的图像
    - wavelet: 小波函数
    返回:
    - transformed_image: 变换后的图像
    '''
    #transformed_image = pywt.wavedec2(image, wavelet)
    return image

def fn_image_skeletonization(image: np.ndarray) -> np.ndarray:
    '''
    图像骨架化函数
    参数:
    - image: 输入的二值图像
    返回:
    - skeletonized_image: 骨架化后的图像
    '''
    skeletonized_image = cv2.ximgproc.thinning(image)
    return skeletonized_image

# 打开摄像头并显示视频
def fn_open_webcam(is_open:bool=True):
    '''
    打开摄像头画面
    '''
    global before_video_webcam
    global before_video
    before_video_webcam.visible = True
    before_video.source="webcam"

# 关闭摄像头画面
def fn_close_webcam(is_open:bool=False):
    '''
    关闭摄像头画面
    '''
    global before_video_webcam
    global before_video
    before_video_webcam.visible=False

# 获取摄像头当前帧并显示
def fn_screenshot_webcam(image):
    '''
    截图摄像头
    '''
    output = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    file_name = "screenshot_{}.jpg".format(random.randint(100,200))
    cv2.imwrite(file_name, output)
    return image,image

# 获取视频第五帧并显示
def fn_screenshot_frame_5(video):
    '''
    截图视频
    '''
    _video = cv2.VideoCapture(video)
    print("video类型:{}".format(type(video)))
    print(video)
    # 读取并丢弃前四帧
    for _ in range(4):
        _video.read()
    # 读取第五帧
    ret, image = _video.read()

    output = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    file_name = "screenshot_{}.jpg".format(random.randint(100,200))
    cv2.imwrite(file_name, image)
    return output,output

# 获取视频当前帧并显示
def fn_screenshot(video):
    '''
    截图视频
    '''
    _video = cv2.VideoCapture(video)
    print("video类型:{}".format(type(video)))
    print(video)
    # 读取并丢弃前n帧
    for _ in range(random.randint(1,200)):
        _video.read()
    # 读取第n+1帧
    ret, image = _video.read()

    output = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    file_name = "screenshot_{}.jpg".format(random.randint(100,200))
    cv2.imwrite(file_name, image)
    return output,output

# 随机剪辑视频
def fn_save_video_random(video_path):
    '''
    随机剪辑视频
    '''
    output_path = f'video_shotcut_{random.randint(100,200)}.mp4'
    shell_command = f'ffmpeg -i "{video_path}" -filter_complex "[0:v]split=2[top][bottom];[bottom]crop=iw:ih/2:0:0[bottom1];[top]crop=iw:ih/2:0:ih/2[top1];[top1][bottom1]vstack" -c:a copy "{output_path}"'
    subprocess.call(shell_command,shell=True)

    return output_path

# 视频添加水印
def fn_add_watermark_video(video_path):
    '''
    给视频添加水印
    '''
    output_path = f'video_watermark_{random.randint(100,200)}.mp4'
    watermark_text = f'qsbye_{random.randint(100,200)}'
    shell_command = f'ffmpeg -i "{video_path}" -vf "drawtext=text=\'{watermark_text}\':x=w-tw-10:y=10:fontsize=24:fontcolor=white:shadowcolor=black:shadowx=2:shadowy=2" -c:a copy "{output_path}"'
    subprocess.call(shell_command, shell=True)
    return output_path

# 视频倒放
def fn_video_upend(video_path):
    '''
    视频倒放
    '''
    output_path = f'video_upend_{random.randint(100,200)}.mp4'
    shell_command = f'ffmpeg -i "{video_path}" -vf "reverse" -af "areverse" "{output_path}"'
    subprocess.call(shell_command, shell=True)
    return output_path

# 保存3s摄像头视频
def fn_save_video_webcam(input_image):
    '''
    保存3s摄像头视频到文件
    输出:视频路径
    '''
    cap = cv2.VideoCapture(0)
    temp_folder = "temp"
    if not os.path.exists(temp_folder):
        os.makedirs(temp_folder)
    
    i = 0
    start_time = time.time()
    while time.time() - start_time < 3:
        image_path = os.path.join(temp_folder, f'image_{i}.jpg')
        #pil_image = Image.fromarray(np.uint8(input_image))
        #pil_image.save(image_path)
        ret, frame = cap.read()
        if ret:
            cv2.imwrite(image_path, frame)
        i += 1
        time.sleep(0.1)  # 暂停0.1秒钟

    cap.release()

    output_path = f'video_{random.randint(100,200)}.mp4'
    shell_command = f'ffmpeg -f image2 -r 1/3 -i {temp_folder}/image_%d.jpg -vf "fps=10" -y {output_path}'
    subprocess.call(shell_command, shell=True)
    
    shutil.rmtree(temp_folder)
    
    return output_path


##################end 功能函数##################

##################start 界面构建##################

# 示例图片
examples_imgs = [
    ["/Users/workspace/Desktop/2023课程归档/大三-上学期-第二周/数字图像处理实验/exp9/exp9-6/imgs/pikachu.jpeg"],
    ["/Users/workspace/Desktop/2023课程归档/大三-上学期-第二周/数字图像处理实验/exp9/exp9-6/imgs/leaf3.jpg"],
    ["/Users/workspace/Desktop/2023课程归档/大三-上学期-第二周/数字图像处理实验/exp9/exp9-6/imgs/qrcode2.png"],
    ["/Users/workspace/Desktop/2023课程归档/大三-上学期-第二周/数字图像处理实验/exp9/exp9-6/imgs/qrcode3.png"],
    ["/Users/workspace/Desktop/2023课程归档/大三-上学期-第二周/数字图像处理实验/exp9/exp9-6/imgs/shape4.bmp"],
    ["/Users/workspace/Desktop/2023课程归档/大三-上学期-第二周/数字图像处理实验/exp9/exp9-6/imgs/shapes.bmp"]
]

# 示例视频
examples_videos = [
    ["/Users/workspace/Desktop/2023课程归档/大三-上学期-第二周/数字图像处理实验/exp9/city_car_stream.mp4"],
]

# 构建界面Blocks上下文
with gradio.Blocks() as demo:
    gradio.Markdown("# 图像视频/处理")
    gradio.Markdown("## 图像处理")
    
    # 原图预览和处理后图像预览
    # 纵向排列
    with gradio.Column():
        # 横向排列
        with gradio.Row():  
            before_img = gradio.inputs.Image(label="原图",shape=(200, 200))
            after_img = gradio.Image(label="处理后图片",shape=(200,200))
            #interface_img = gradio.Interface(fn=fun_gray_img, inputs="image", outputs="image")
        # 横向排列
        with gradio.Row():
            gradio.Examples(examples=examples_imgs, inputs=[before_img],label="示例图片")
        # 横向排列
        with gradio.Row(label="图片处理函数"):   
            # 按钮:转为灰度图
            fn_gray_btn = gradio.Button("灰度图")
            # 按钮:转为二值图
            fn_binary_btn = gradio.Button("二值图")
            # 按钮:加入椒盐噪声
            fn_salt_and_pepper_noise_btn = gradio.Button("添加椒盐噪声")
            # 按钮:去除噪声
            fn_remove_noise_btn = gradio.Button("去除常规噪声")
            # 按钮:开运算
            fn_open_operation_btn = gradio.Button("开运算")
            # 按钮:闭运算
            fn_close_operation_btn = gradio.Button("闭运算")
            # 按钮:求连通域运算
            fn_connected_domains_btn = gradio.Button("求连通域")
            # 按钮:腐蚀
            fn_erosion_btn = gradio.Button("腐蚀")
            # 按钮:膨胀
            fn_dilation_btn = gradio.Button("膨胀")
            # 按钮:添加频域水印
            fn_watermark_btn = gradio.Button("添加频域水印")
            # 按钮:高斯滤波
            fn_gaussian_filter_btn = gradio.Button("高斯滤波")
            # 按钮:中值滤波
            fn_median_filter_btn = gradio.Button("中值滤波")
            # 按钮:平均值滤波
            fn_mean_filter_btn = gradio.Button("平均值滤波")
            # 按钮:灰度映射
            fn_gray_mapping_btn = gradio.Button("灰度映射")
            # 按钮:图像增亮
            fn_image_enhancement_btn = gradio.Button("图像增亮")
            # 按钮:沃尔什变换
            fn_walsh_transform_btn = gradio.Button("沃尔什变换")
            # 按钮:哈达玛变换
            fn_hadamard_transform_btn = gradio.Button("哈达玛变换")
            # 按钮:一维DCT变换
            fn_1d_dct_btn = gradio.Button("一维离散余弦变换")
            # 按钮:二维DCT变换
            fn_2d_dct_btn = gradio.Button("二维离散余弦变换")
            # 按钮:二维连续傅立叶变换
            fn_2d_continuous_fourier_transform_btn = gradio.Button("二维连续傅立叶变换")
            # 按钮:二维离散傅立叶变换
            fn_2d_discrete_fourier_transform_btn = gradio.Button("二维离散傅立叶变换")
            # 按钮:连续小波变换
            fn_continuous_wavelet_transform_btn = gradio.Button("连续小波变换")
            # 按钮:一维离散小波变换
            fn_1d_discrete_wavelet_transform_btn = gradio.Button("一维离散小波变换")
            # 按钮:二维离散小波变换
            fn_2d_discrete_wavelet_transform_btn = gradio.Button("二维离散小波变换")
            # 按钮:图像骨骼化
            fn_image_skeletonization_btn = gradio.Button("图像骨骼化")
            
        #绑定fn_gray_btn点击函数
        fn_gray_btn.click(fn=fn_gray, inputs=[before_img], outputs=after_img)
        # 绑定fn_binary_btn点击函数
        fn_binary_btn.click(fn=fn_binary, inputs=[before_img], outputs=after_img)
        # 绑定fn_salt_and_pepper_noise_btn点击函数
        fn_salt_and_pepper_noise_btn.click(fn=fn_salt_and_pepper_noise, inputs=[before_img], outputs=after_img)
        # 绑定fn_remove_noise_btn点击函数
        fn_remove_noise_btn.click(fn=fn_remove_noise,inputs=[before_img],outputs=after_img)
        # 绑定fn_open_operation_btn点击函数
        fn_open_operation_btn.click(fn=fn_open_operation,inputs=[before_img],outputs=after_img)
        # 绑定
        fn_close_operation_btn.click(fn=fn_close_operation, inputs=[before_img], outputs=after_img)
        # 绑定
        fn_connected_domains_btn.click(fn=fn_connected_domains, inputs=[before_img], outputs=after_img)
        # 绑定
        fn_erosion_btn.click(fn=fn_erosion, inputs=[before_img], outputs=after_img)
        # 绑定
        fn_dilation_btn.click(fn=fn_dilation, inputs=[before_img], outputs=after_img)
        # 绑定
        fn_watermark_btn.click(fn=fn_watermark, inputs=[before_img], outputs=after_img)
        # 绑定
        fn_gaussian_filter_btn.click(fn=fn_gaussian_filter, inputs=[before_img], outputs=after_img)
        # 绑定
        fn_median_filter_btn.click(fn=fn_median_filter, inputs=[before_img], outputs=after_img)
        # 绑定
        fn_mean_filter_btn.click(fn=fn_mean_filter, inputs=[before_img], outputs=after_img)
        # 绑定
        fn_gray_mapping_btn.click(fn=fn_gray_mapping, inputs=[before_img], outputs=after_img)
        # 绑定
        fn_image_enhancement_btn.click(fn=fn_image_enhancement, inputs=[before_img], outputs=after_img)
        # 绑定
        fn_walsh_transform_btn.click(fn=fn_walsh_transform, inputs=[before_img], outputs=after_img)
        # 绑定
        fn_hadamard_transform_btn.click(fn=fn_hadamard_transform, inputs=[before_img], outputs=after_img)
        # 绑定
        fn_1d_dct_btn.click(fn=fn_1d_dct, inputs=[before_img], outputs=after_img)
        # 绑定
        fn_2d_dct_btn.click(fn=fn_2d_dct, inputs=[before_img], outputs=after_img)
        # 绑定
        fn_2d_continuous_fourier_transform_btn.click(fn=fn_2d_continuous_fourier_transform, inputs=[before_img], outputs=after_img)
        # 绑定
        fn_2d_discrete_fourier_transform_btn.click(fn=fn_2d_discrete_fourier_transform, inputs=[before_img], outputs=after_img)
        # 绑定
        fn_continuous_wavelet_transform_btn.click(fn=fn_continuous_wavelet_transform, inputs=[before_img], outputs=after_img)
        # 绑定
        fn_1d_discrete_wavelet_transform_btn.click(fn=fn_1d_discrete_wavelet_transform, inputs=[before_img], outputs=after_img)
        # 绑定
        fn_2d_discrete_wavelet_transform_btn.click(fn=fn_2d_discrete_wavelet_transform, inputs=[before_img], outputs=after_img)
        # 绑定
        fn_image_skeletonization_btn.click(fn=fn_image_skeletonization, inputs=[before_img], outputs=after_img)

    gradio.Markdown("## 视频处理")
    # 纵向排列
    with gradio.Column():
        # 横向排列
        with gradio.Row():
            before_video = gradio.inputs.Video(label="原视频")
            before_video_webcam = gradio.Image(source="webcam", streaming=True,label="摄像头预览",visible=True)
            after_video = gradio.Video(label="处理后视频")
            shotcut_video = gradio.Image(label="视频截图",shape=(200,200))
            #interface_img = gradio.Interface(fn=fun_gray_img, inputs="image", outputs="image")

        # 横向排列
        gradio.Markdown("视频操作区")
        with gradio.Row():
            # 按钮:视频截屏按钮
            fn_screenshot_btn = gradio.Button("视频截图")
            # 按钮:摄像头截图
            fn_screenshot_webcam_btn = gradio.Button("摄像头截图")
            # 按钮:摄像头视频保存3s
            fn_save_video_webcam_btn = gradio.Button("摄像头视频保存")
            # 按钮:添加水印功能
            fn_add_watermark_video_btn = gradio.Button("添加水印")
            # 按钮:截取第五帧
            fn_screenshot_frame_5_btn = gradio.Button("截图第五帧")
            # 按钮:随机保存视频
            fn_save_video_random_btn = gradio.Button("随机保存视频")
            # 按钮:视频倒放
            fn_video_upend_btn = gradio.Button("倒放")

        # 横向排列
        with gradio.Row():
            gradio.Examples(examples=examples_videos, inputs=[before_video], label="示例视频")
            # 按钮:打开浏览器摄像头按钮
            fn_open_webcam_btn = gradio.Button("开启摄像头画面")
            # 按钮:关闭浏览器摄像头按钮
            fn_close_webcam_btn = gradio.Button("关闭摄像头画面")
        
        # 绑定按钮功能
        fn_open_webcam_btn.click(fn=fn_open_webcam,outputs=[before_video])
        fn_close_webcam_btn.click(fn=fn_close_webcam,outputs=[before_video])
        fn_screenshot_btn.click(fn=fn_screenshot,inputs=[before_video],outputs=[shotcut_video,before_img])
        fn_screenshot_webcam_btn.click(fn=fn_screenshot_webcam,inputs=[before_video_webcam],outputs=[shotcut_video,before_img])
        fn_screenshot_frame_5_btn.click(fn=fn_screenshot_frame_5,inputs=[before_video],outputs=[shotcut_video,before_img])
        fn_save_video_random_btn.click(fn=fn_save_video_random,inputs=[before_video],outputs=[after_video])
        fn_add_watermark_video_btn.click(fn=fn_add_watermark_video,inputs=[before_video],outputs=[after_video])
        fn_video_upend_btn.click(fn=fn_video_upend,inputs=[before_video],outputs=[after_video])
        fn_save_video_webcam_btn.click(fn=fn_save_video_webcam,inputs=[before_video_webcam],outputs=[after_video])

# 启动demo界面
demo.launch()

##################end 界面构建##################

GradioLite内嵌到网页中

<html>
	<head>
		<script type="module" crossorigin src="https://cdn.jsdelivr.net/npm/@gradio/lite/dist/lite.js"></script>
		<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@gradio/lite/dist/lite.css" />
	</head>
	<body>
		<gradio-lite>
		import gradio as gr

		def greet(name):
			return "Hello, " + name + "!"
		
		gr.Interface(greet, "textbox", "textbox").launch()
		</gradio-lite>
	</body>
</html>

效果


标签:Gradio,gradio,前端开发,video,np,btn,image,fn,页面
From: https://www.cnblogs.com/qsbye/p/17809505.html

相关文章

  • 一级页面、二级页面和三级页面的区别
    一级页面也就是首页,二级页面是链接到首页的,三级页面链接到二级页面。就拿来说,它的首页就是一级页面,点击百度出现的页面就是二级页面,在百度页面点击任何一项出现的页面就是三级页面。这个就像分类,下面有小分类。比如一级频道叫“电脑网络”,那电脑网络下面再分“硬件、软件、互联网”......
  • 如何在Razor视图页面中导入命名空间?
    内容来自DOChttps://q.houxu6.top/?s=如何在Razor视图页面中导入命名空间?如何在Razor视图页面中导入命名空间?终于找到了答案。@usingMyNamespace对于VB.Net:@ImportsMynamespace如果您想在应用程序中包含命名空间,请查看@ravyamiry的回答。......
  • 飞码LowCode前端技术:如何便捷配置出页面
    简介飞码是京东科技平台研发部研发的低代码产品,可使营销运营域下web页面快速搭建。本文将从三个方面来讲解如何便捷配置出页面,第一部分从数据、事件、业务支持三个方面进行分析,第二部分从模板与页面收藏与升级、页面UI结构、画布功能三个方面进行分析,第三部分从监控、页面配置、......
  • Flutter Stack 做页面切换
    从名字上看,这个容器就是堆。效果是能让自己内部的子组件重叠放置,严格意义上来说,我认为他可以算是一个布局容器,就像Row,Column一样。下面是网上找的例子(主要我懒的现写了)classCustomStackextendsStatelessWidget{@overrideWidgetbuild(BuildContextcontext){va......
  • 关于在页面列表里查询数据的时间和页面实时弹窗中的时间差1秒钟的问题
    1、问题:在一次告警中心功能的演示时,告警列表页中的实时告警数据,每次都跟弹窗的告警提示信息查一秒,有时候有事正常的,就很奇怪。2、解决:经过进行代码断点,发现在插入告警时间时,使用的LocalDateTime,该时间时带有纳秒时间的,比如在程序中显示的时间值是:1990-01-01T00:01:01.111,此时存......
  • 飞码LowCode前端技术:如何便捷配置出页面 | 京东云技术团队
    简介飞码是京东科技平台研发部研发的低代码产品,可使营销运营域下web页面快速搭建。本文将从三个方面来讲解如何便捷配置出页面,第一部分从数据、事件、业务支持三个方面进行分析,第二部分从模板与页面收藏与升级、页面UI结构、画布功能三个方面进行分析,第三部分从监控、页面配置、页......
  • vue3 -点击按钮进入新的页面
    一、调用页面//路由import{useRouter}from'vue-routerlet$router=useRouter()//车组调整页面consthandleCar=(row:any)=>{ $router.push({path:"/test/edit",query:{setCode:row.setCode,lineName:row.lineName}})}二、新打开的页面importuseTagsViewSt......
  • piti:PPT页面的神奇小插件
    piti####这是一个拥有2000+PPT页面的神器小插件。划重点:免费使用。我第一次知道piti是朋友推荐的,后来才知道原来这是一周进步推出的小插件。“让PPT好看这件事情,交给我们”,这样的slogan真是非常打动人心啊~这是piti的界面,非常简洁。如果你和我一样是个偷懒星人,那piti的PPT智......
  • Springboot使用return跳转到html页面只是返回字符串,不跳转问题的解决
    问题描述我在使用SpringBoot进行页面跳转时,发现其只是返回相应的字符串,并不会出现页面跳转:问题解决不要在Controller层加@Responsebody注解,不然就只会默认是返回字符串,而不会返回页面;......
  • 发布会回放|Gradio 4.0 正式发布!
     Gradio的目标是使机器学习模型的演示更容易定制和访问,以满足不同用户的需求。在4.0正式版的发布活动上,HuggingFace的Gradio团队介绍了自己为了提高机器学习模型的可访问性所做的工作,以及如何创建自定义组件。Gradio是一个用于构建机器学习模型演示的工具,任何人都可以......