Я готов реализовать редактор ограничивающих рамок в градиенте, самостоятельно создав 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, чтобы нарисовать загруженное изображение на холсте. Любые рекомендации или примеры будут с благодарностью приняты.
используйте кнопку try it yourself
, чтобы увидеть исходный код в методе HTML Canvas drawImage()
Я тестирую код, но проблема в том, что gr.HTML
не запускается <script>
. Возможно, потребуется добавить функцию script
в gr.Blocks(js=scirpt)
, но позже понадобится какой-то метод для выполнения этой функции, когда изображение и холст уже созданы. В данный момент у меня работает, если в html_content
я добавляю кнопку с onclick=
для выполнения этой функции.
Вы можете увидеть это во многих вопросах или руководствах.
Вам нужно получить холст, затем получить контекст .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)
Источник информации:
HTML-компонент Gradio с кодом JavaScript не работает - 🔒 Gradio - Форумы Hugging Face Forums
gradio.HTML НЕ МОЖЕТ загрузить мой JavaScript · Проблема № 3446 · gradio-app/gradio
Код, который добавляет второе изображение (изображение Ленна из Википедии), и вы можете использовать кнопки, чтобы выбрать, какое изображение разместить на холсте.
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)
Я думаю, вы найдете идеи во многих вопросах по JavaScript и Canvas. Возможно, потребуется получить 2D-контент
content = canvas.getContext('2d')
, получить изображение в формате base64 (и, возможно, преобразовать в BLOB) и нарисовать его на холстеcontext.drawImage(image, x, y, width, height)