Как загрузить изображение на холст в Gradio с помощью специального HTML и JavaScript?

Я готов реализовать редактор ограничивающих рамок в градиенте, самостоятельно создав html и js (где пользователь может перемещать bbox, масштабировать и рисовать новые). Но я не могу найти способ загрузить изображение на холст. Я был бы признателен за любую помощь

Лучшее, чего я достиг на данный момент, — это загрузка изображения в html-элемент изображения:

import gradio as gr
import numpy as np
import base64
from PIL import Image
from io import BytesIO

def image_to_base64(img):
    buffered = BytesIO()
    img.save(buffered, format = "PNG")
    img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
    return img_str

def image_uploaded(img):
    img_pil = Image.fromarray(img)
    img_str = image_to_base64(img_pil)

    # HTML content with a canvas element
    html_content = f"""
    <html lang = "en">
    <body>
        <img src = "data:image/png;base64,{img_str}" alt = "">
        <canvas id = "canvas"></canvas>
    </body>
    </html>
    """
    
    return img, gr.HTML(html_content)

with gr.Blocks(js=None) as demo:
    uploaded_image = gr.Image(type = "numpy", show_label=False, interactive=True, show_download_button=False)
    original_image = gr.Image(type = "numpy", interactive=False, show_label=False, show_download_button=False)

    bounding_box_editor = gr.HTML()
    
    uploaded_image.upload(image_uploaded, inputs=uploaded_image, outputs=[original_image, bounding_box_editor])

demo.launch(share=False)

P.S. Если есть другие реализации - я был бы рад их увидеть (где пользователь может перемещать bbox, масштабировать и рисовать новые)

Мне нужна помощь с частью JavaScript, чтобы нарисовать загруженное изображение на холсте. Любые рекомендации или примеры будут с благодарностью приняты.

Я думаю, вы найдете идеи во многих вопросах по JavaScript и Canvas. Возможно, потребуется получить 2D-контент content = canvas.getContext('2d'), получить изображение в формате base64 (и, возможно, преобразовать в BLOB) и нарисовать его на холсте context.drawImage(image, x, y, width, height)

furas 28.06.2024 17:23

используйте кнопку try it yourself, чтобы увидеть исходный код в методе HTML Canvas drawImage()

furas 28.06.2024 17:26

Я тестирую код, но проблема в том, что gr.HTML не запускается <script>. Возможно, потребуется добавить функцию script в gr.Blocks(js=scirpt), но позже понадобится какой-то метод для выполнения этой функции, когда изображение и холст уже созданы. В данный момент у меня работает, если в html_content я добавляю кнопку с onclick= для выполнения этой функции.

furas 28.06.2024 23:20
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
3
116
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете увидеть это во многих вопросах или руководствах.

Вам нужно получить холст, затем получить контекст .getContext('2d') и затем поместить изображение с помощью .drawImage(img, x, y, width, height).

Что-то вроде этого

var image  = document.getElementById("image");
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0);

Но я обнаружил, что gr.HTML() не может запустить <script>, и это создает проблемы с запуском приведенного выше кода.

Но вы можете добавить скрипт в gr.Block(js=script) с функцией, которую позже можно будет использовать в onclick = "..", назначенном кнопке, или в onload = "...", назначенном изображению.


Полный код:

import gradio as gr
import numpy as np
import base64
from PIL import Image
from io import BytesIO

def image_to_base64(img):
    buffered = BytesIO()
    img.save(buffered, format = "PNG")
    img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
    return img_str

def image_uploaded(img):
    img_pil = Image.fromarray(img)
    img_str = image_to_base64(img_pil)

    img_str = f'data:image/png;base64,{img_str}'
    #img_str = f'https://upload.wikimedia.org/wikipedia/en/7/7d/Lenna_%28test_image%29.png'
    
    # HTML content with a canvas element
    html_content = f"""
<h1>Uploaded: img</h1>

<img id = "image" src = "{img_str}" alt = "" onload = "draw_image();">

<h1>Uploaded: canvas</h1>

<canvas id = "canvas" width = "600"></canvas>

<!-- <button onclick = "draw_image();" style = "background-color:#eee;padding:25px">Draw Image</button>  -->
"""

    return img, html_content

script = """
/* this function is executed automatically at start (not when you load canvas) */
/* so draw_image() has to be inside (not in place of `async ()`) */
async () => {
    globalThis.draw_image = () => {
        var image  = document.getElementById("image");
        var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext('2d');
        ctx.drawImage(image, 0, 0);
    }
}
"""

with gr.Blocks(js=script) as demo:
    uploaded_image = gr.Image(type = "numpy", show_label=False, interactive=True, show_download_button=False)
    original_image = gr.Image(type = "numpy", interactive=False, show_label=False, show_download_button=False)

    bounding_box_editor = gr.HTML()
    
    uploaded_image.upload(image_uploaded, inputs=uploaded_image, outputs=[original_image, bounding_box_editor])
    
demo.launch(share=False)

Источник информации:


Код, который добавляет второе изображение (изображение Ленна из Википедии), и вы можете использовать кнопки, чтобы выбрать, какое изображение разместить на холсте.

import gradio as gr
import numpy as np
import base64
from PIL import Image
from io import BytesIO

def image_to_base64(img):
    buffered = BytesIO()
    img.save(buffered, format = "PNG")
    img_str = base64.b64encode(buffered.getvalue()).decode("utf-8")
    return img_str

def image_uploaded(img):
    img_pil = Image.fromarray(img)
    img_str = image_to_base64(img_pil)

    img_str_1 = f'data:image/png;base64,{img_str}'
    img_str_2 = f'https://upload.wikimedia.org/wikipedia/en/7/7d/Lenna_%28test_image%29.png'
    
    # HTML content with a canvas element
    html_content = f"""
<h1>Uploaded: img</h1>

<img id = "image1" src = "{img_str_1}" alt = "" width = "200" height = "200"> <img id = "image2" src = "{img_str_2}" alt = "" width = "200" height = "200">

<h1>Uploaded: canvas</h1>

<canvas id = "canvas" width = "200" height = "200"></canvas>

<button onclick = "draw_image('image1');" style = "background-color:#eee;padding:25px">Draw Image 1</button>
<button onclick = "draw_image('image2');" style = "background-color:#eee;padding:25px">Draw Image 2</button>
"""

    return img, html_content

script = """
/* this function is executed automatically at start (not when you load canvas) */
/* so draw_image() has to be inside (not in place of `async ()`) */
async () => {
    globalThis.draw_image = (image_id) => {
        var image  = document.getElementById(image_id);
        var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext('2d');
        ctx.drawImage(image, 0, 0, 200, 200);
    }
}
"""

with gr.Blocks(js=script) as demo:
    uploaded_image = gr.Image(type = "numpy", show_label=False, interactive=True, show_download_button=False)
    original_image = gr.Image(type = "numpy", interactive=False, show_label=False, show_download_button=False)

    bounding_box_editor = gr.HTML()
    
    uploaded_image.upload(image_uploaded, inputs=uploaded_image, outputs=[original_image, bounding_box_editor])
    
demo.launch(share=False)

Другие вопросы по теме