【问题标题】:How to show a local image in an interactive dash with python如何使用 python 在交互式破折号中显示本地图像
【发布时间】:2021-08-11 18:58:29
【问题描述】:

所以我正在开发 Dash Plotly。网页应该有一个文本框和一个按钮。这个想法是当我写一个图像名称然后选择按钮时,它将显示本地目录中的图像。

我试着把整个作品分成两部分。

首先,我有这段代码,它会显示你在文本框中输入的任何内容,然后单击按钮。代码:

# -*- coding: utf-8 -*-
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import os 
from PIL import Image
import numpy as np
import plotly.express as px

os.chdir(os.path.dirname(os.path.abspath(__file__)))

external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"]

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div(
    [
        html.I("Try typing the image name in input and observe it"),
        html.Br(),
        dcc.Input(id="input", type="text", placeholder=""),
        html.Div(id="output"),
    ]
)


@app.callback(
    Output("output", "children"),
    Input("input", "value")
)
def update_output(input):
    return u'Input {}'.format(input)


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

接下来,我有这段代码,当在本地运行时,它只会显示网页中的图像。要点:python文件和图像在同一个本地目录中。代码:

import os 

from PIL import Image
import numpy as np
import plotly.express as px

# Change working dir to current running script dir:
print('[change directory]')
os.chdir(os.path.dirname(os.path.abspath(__file__)))

def test():
    # load the image
    img = np.array(Image.open('img name.tiff'))

    fig = px.imshow(img, color_continuous_scale='gray')
    fig.update_layout(coloraxis_showscale=False)
    fig.update_xaxes(showticklabels=False)
    fig.update_yaxes(showticklabels=False)
    fig.show()

test()

现在,我需要一种方法来添加这两个代码,以便当我在文本框中输入“img name.tiff”并选择按钮时,它会显示网页中的图片。

我是 Dash 和 Plotly 的新手。我不知道该怎么做。我试图研究它,但找不到任何有用的东西。有人可以帮忙吗?

【问题讨论】:

    标签: python html plotly-dash


    【解决方案1】:

    你可以把你的回调改成这样:

    @app.callback(Output("output", "children"), Input("input", "value"))
    def update_output(input):
        if not input:
            raise PreventUpdate
    
        try:
            img = np.array(Image.open(f"assets/{input}"))
        except OSError:
            raise PreventUpdate
    
        fig = px.imshow(img, color_continuous_scale="gray")
        fig.update_layout(coloraxis_showscale=False)
        fig.update_xaxes(showticklabels=False)
        fig.update_yaxes(showticklabels=False)
    
        return dcc.Graph(figure=fig)
    

    如果没有输入值或者用户指定路径的图片无法打开,我们使用PreventUpdate

    在某些情况下,您不想更新回调输出。您可以通过在回调函数中引发 PreventUpdate 异常来实现此目的。

    注意:此示例假定图像存储在assets 文件夹中。

    更新:使用按钮实现

    @app.callback(
        Output("output", "children"),
        Input("input", "value"),
        Input("show-image", "n_clicks"),
        prevent_initial_call=True,
    )
    def update_output(input, n_clicks):
        if not input:
            raise PreventUpdate
    
        ctx = dash.callback_context
        if ctx.triggered[0]["prop_id"].split(".")[0] != "show-image":
            raise PreventUpdate
    
        try:
            img = np.array(Image.open(f"assets/{input}"))
        except OSError:
            raise PreventUpdate
    
        fig = px.imshow(img, color_continuous_scale="gray")
        fig.update_layout(coloraxis_showscale=False)
        fig.update_xaxes(showticklabels=False)
        fig.update_yaxes(showticklabels=False)
    
        return dcc.Graph(figure=fig)
    

    在前面关于查找可以打开的图像的示例中,回调返回带有图像的图形。如果您想推迟显示图像,直到单击按钮,您可以在布局中添加一个按钮

    html.Button("Show Image", id="show-image", n_clicks=0)
    

    并使用callback_context 来确定是哪个Input 触发了该按钮。如果此输入的id 等于"show-input"(我们按钮的id),我们将显示图形和图像。

    【讨论】:

    • 嘿,解决方案几乎完美,只是一个小问题。当我运行它时,会有这个文本框,我可以在其中写下图像的名称。然后,当我选择鼠标左键(不是 Enter)时,它会显示图像。但是没有可以单击以显示图像的按钮。可以查一下吗?
    • @KhabbabZakaria 第一个回调实际上显示了您输入图像名称的那一刻,该图像存在并且可以打开,而不管鼠标左键或输入单击。请参阅我更新的答案中的第二个示例,以了解延迟加载图像直到单击按钮后的回调。
    猜你喜欢
    • 1970-01-01
    • 2019-02-02
    • 1970-01-01
    • 1970-01-01
    • 2017-05-26
    • 1970-01-01
    • 1970-01-01
    • 2011-05-30
    • 2021-05-08
    相关资源
    最近更新 更多