【问题标题】:Displaying an image with dcc.Graph in Plotly-Dash在 Plotly-Dash 中使用 dcc.Graph 显示图像
【发布时间】:2022-01-06 21:53:20
【问题描述】:

我试图在 Plotly-Dash 中显示带有 dcc.Graph 组件的图像,因此我得到了它漂亮的工具栏和内置 UI。但是我收到了一堆错误。这是我的程序:

  1. 上传 JPG 图片。
  2. 使用np.array(Image.open(..))加载图片。
  3. 用px.imshow()转换成图形。
  4. 通过dcc.Graph 组件传递这个并尝试在页面上显示它。

下面是我的代码:

import datetime
import dash
from dash.dependencies import Input, Output, State
from dash import dcc
from dash import html
import numpy as np
from PIL import Image
import plotly.express as px

app = dash.Dash(__name__)

app.layout = html.Div([

    html.Div(
        children=[
            dcc.Upload(
                id='upload-image',
                children=html.Div([
                    'Drag and Drop or ',
                    html.A('Select Files')
                ]),
                # Allow multiple files to be uploaded
                multiple=True)]),
    html.Div(
        children=[
            html.Div(id='output-image-upload'),
        ])
])

def parse_contents(contents, filename, date):
    img = np.array(Image.open(contents))
    fig = px.imshow(img)
    return html.Div([
        html.H5(filename),
        html.H6(datetime.datetime.fromtimestamp(date)),
        dcc.Graph(figure=fig)
    ])
        
@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)

我在下面收到这些错误:

Callback error updating output-image-upload.children

Traceback (most recent call last):
  File "C:\Users\...\test.py", line 48, in update_output
    children = [
  File "C:\Users\...\test.py", line 49, in <listcomp>
    parse_contents(c, n, d) for c, n, d in
  File "C:\Users\...\test.py", line 34, in parse_contents
    img = np.array(Image.open(contents))
  File "C:\Users\...\AppData\Local\Programs\Python\Python38\Lib\site-packages\PIL\Image.py", line 2904, in open
    fp = builtins.open(filename, "rb")
FileNotFoundError: [Errno 2] No such file or directory: 'data:image/jpeg;base64,/9j/2wBDAAYEBQY...

【问题讨论】:

    标签: python numpy plotly plotly-dash


    【解决方案1】:

    如this answer 中所述,您需要从图像字符串中删除data:image/png;base64,。如果您按如下方式更新您的 parse_contents 函数,您的应用应该可以工作:

    def parse_contents(contents, filename, date):
    
        # Remove 'data:image/png;base64' from the image string,
        # see https://stackoverflow.com/a/26079673/11989081
        data = contents.replace('data:image/png;base64,', '')
        img = Image.open(io.BytesIO(base64.b64decode(data)))
    
        # Convert the image string to numpy array and create a
        # Plotly figure, see https://plotly.com/python/imshow/
        fig = px.imshow(np.array(img))
    
        # Hide the axes and the tooltips
        fig.update_layout(
            plot_bgcolor='white',
            paper_bgcolor='white',
            margin=dict(t=20, b=0, l=0, r=0),
            xaxis=dict(
                showgrid=False,
                showticklabels=False,
                linewidth=0
            ),
            yaxis=dict(
                showgrid=False,
                showticklabels=False,
                linewidth=0
            ),
            hovermode=False
        )
    
        return html.Div([
            html.H5(filename),
            html.H6(datetime.datetime.fromtimestamp(date)),
            dcc.Graph(
                figure=fig,
                config={'displayModeBar': True} # Always display the modebar
            )
        ])
    

    完整代码:

    import io
    import base64
    import datetime
    import dash
    import dash_core_components as dcc
    import dash_html_components as html
    from dash.dependencies import Input, Output, State
    import numpy as np
    import plotly.express as px
    from PIL import Image
    
    app = dash.Dash(__name__)
    
    app.layout = html.Div([
        html.Div(
            children=[
                dcc.Upload(
                    id='upload-image',
                    children=html.Div(['Drag and Drop or ', html.A('Select Files')]),
                    multiple=True
                )
            ]
        ),
        html.Div(
            children=[
                html.Div(id='output-image-upload'),
            ]
        )
    ])
    
    def parse_contents(contents, filename, date):
    
        # Remove 'data:image/png;base64' from the image string,
        # see https://stackoverflow.com/a/26079673/11989081
        data = contents.replace('data:image/png;base64,', '')
        img = Image.open(io.BytesIO(base64.b64decode(data)))
    
        # Convert the image string to numpy array and create a
        # Plotly figure, see https://plotly.com/python/imshow/
        fig = px.imshow(np.array(img))
    
        # Hide the axes and the tooltips
        fig.update_layout(
            plot_bgcolor='white',
            paper_bgcolor='white',
            margin=dict(t=20, b=0, l=0, r=0),
            xaxis=dict(
                showgrid=False,
                showticklabels=False,
                linewidth=0
            ),
            yaxis=dict(
                showgrid=False,
                showticklabels=False,
                linewidth=0
            ),
            hovermode=False
        )
    
        return html.Div([
            html.H5(filename),
            html.H6(datetime.datetime.fromtimestamp(date)),
            dcc.Graph(
                figure=fig,
                config={'displayModeBar': True} # Always display the modebar
            )
        ])
    
    @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, host='127.0.0.1')
    

    【讨论】:

    • 我收到错误PIL.UnidentifiedImageError: cannot identify image file &lt;_io.BytesIO object at 0x000001F6FD158360&gt;
    • 我无法复制,它对我来说很好用。尝试查看this question 的答案。如果它们没有帮助,最好在 Plotly-Dash 之外创建一个最小的可重现问题示例并提出新问题(我认为,如果你没有将它具体描述为一个 Plotly-Dash 问题)。
    • 发现需要为我更改为 /jpeg。谢谢。
    • 你知道为什么图片现在显示得这么小吗?
    • 比实际图片尺寸小吗?
    猜你喜欢
    • 1970-01-01
    • 2022-07-30
    • 2021-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-25
    • 2021-11-04
    相关资源
    最近更新 更多