dash-canvas — это модуль для аннотации и обработки изображений с помощью Dash.

Приведенный ниже учебник предоставляет способ динамической загрузки (через пользовательскую систему во время выполнения) изображения внутри dash-canvas, на котором пользователь может выполнять различные функции, предоставляемые холстом.

Во-первых, мы создадим функцию загрузки, используя dcc.upload, как показано ниже:

import datetime
from dash import Dash, dcc, html
from dash.dependencies import Input, Output, State
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = Dash(__name__, external_stylesheets=external_stylesheets)
app.layout = html.Div([
    dcc.Upload(
        id='upload-image',
        children=html.Div([
            'Drag and Drop or ',
            html.A('Select Files')
        ]),
        style={
            'width': '100%',
            'height': '60px',
            'lineHeight': '60px',
            'borderWidth': '1px',
            'borderStyle': 'dashed',
            'borderRadius': '5px',
            'textAlign': 'center',
            'margin': '10px'
        },
        # Allow multiple files to be uploaded
        multiple=True
    ),
    html.Div(id='output-image-upload'),
])
def parse_contents(contents, filename, date):
    return html.Div([
        html.H5(filename),
        html.H6(datetime.datetime.fromtimestamp(date)),
# HTML images accept base64 encoded strings in the same format
        # that is supplied by the upload
        html.Img(src=contents),
        html.Hr(),
        html.Div('Raw Content'),
        html.Pre(contents[0:200] + '...', style={
            'whiteSpace': 'pre-wrap',
            'wordBreak': 'break-all'
        })
    ])
@app.callback(Output('output-image-upload', 'children'),
              Input('upload-image', 'contents'),
              State('upload-image', 'filename'),
              State('upload-image', 'last_modified'))
def update_output(list_of_contents, list_of_names, list_of_dates):
    if list_of_contents is not None:
        children = [
            parse_contents(c, n, d) for c, n, d in
            zip(list_of_contents, list_of_names, list_of_dates)]
        return children
if __name__ == '__main__':
    app.run_server(debug=True)

Опция загрузки позволит нам загрузить изображение на нашу веб-страницу. Функция обратного вызова update_output определяет, где будут отображаться выходные данные загрузки. Итак, мы добавим наш холст здесь.

Функция update_output, в свою очередь, вызывает parse_contents, который возвращает элемент HTML, вызываемый функцией загрузки, внутри которого мы определяем наш HTML для холста тире. Теперь вопрос в том, как обеспечить входное изображение внутри холста?

Как указано в официальной документации,

Фоновое изображение может быть обновлено благодаря свойству image_content (a str), например, с помощью свойства contents dcc.Upload (диалоговое окно «Открыть файл»). Обновление image_content запускает обновление свойства json_data, содержащего аннотации.

Мы можем использовать свойство изображения-контента холста, как показано ниже:

from dash_canvas import DashCanvas
from dash_canvas.utils import array_to_data_url, image_string_to_PILImage
import numpy as np
def parse_contents(contents, filename, date):
    img = image_string_to_PILImage(contents)
    pix = np.array(img)
    img_content = array_to_data_url(pix)
    return html.Div([DashCanvas(id='canvaas_image',
                                image_content=img_content,
                                tool='line',
                                lineWidth=5,
                                lineColor='red',
                                width=canvas_width)])

Мы используем функцию dash.utils image_string_toPILImage, чтобы получить строку загружаемого содержимого в изображении, а затем преобразовать ее в массив NumPy. Этот массив можно преобразовать в URL-адрес данных, приемлемый для свойства image_content в Dash Canvas.

Чтобы узнать больше об этих функциях, посетите репозиторий GitHub ниже:



Найдите окончательный код ниже:

import dash
import numpy as np
import dash_html_components as html
from dash_canvas import DashCanvas
from dash import dcc
from dash.dependencies import Input, Output, State
from dash_canvas.utils import array_to_data_url, image_string_to_PILImage

app = dash.Dash(__name__)

canvas_width = 500

app.layout = html.Div([
    dcc.Upload(
        id='upload-image',
        children=html.Div([
            'Drag and Drop or ',
            html.A('Select Files')
        ]),
        style={
            'width': '100%',
            'height': '60px',
            'lineHeight': '60px',
            'borderWidth': '1px',
            'borderStyle': 'dashed',
            'borderRadius': '5px',
            'textAlign': 'center',
            'margin': '10px'
        },
        # Allow multiple files to be uploaded
        multiple=True
    ),
    html.Div(id='output-image-upload')
])


def parse_contents(contents, filename, date):
    img = image_string_to_PILImage(contents)
    pix = np.array(img)
    img_content = array_to_data_url(pix)
    return html.Div([DashCanvas(id='canvaas_image',
                                image_content=img_content,
                                tool='line',
                                lineWidth=5,
                                lineColor='red',
                                width=canvas_width)])


@app.callback(Output('output-image-upload', 'children'),
              Input('upload-image', 'contents'),
              State('upload-image', 'filename'),
              State('upload-image', 'last_modified'))
def update_output(list_of_contents, list_of_names, list_of_dates):
    if list_of_contents is not None:
        children = [
            parse_contents(c, n, d) for c, n, d in
            zip(list_of_contents, list_of_names, list_of_dates)]
        return children


if __name__ == '__main__':
    app.run_server(debug=True)

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