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
(astr
), например, с помощью свойства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.