Customize hovertemplate in a px.Imshow Image

Hello everyone, I’m having trouble displaying an Image on my dashboard and then getting custom information on mouseover (or on the hovertemplate).

Right now, I’m using px.Imshow(img) to display an image, and, on hover I can get the RGBA values of the image… and that’s great! Like this:

But I want to do something else aside from that. I want to map that RGBA color to a, let’s say, a name. Like a Dictionary.

rgba_dict = {
    '[255,255,255,255]': 'empty',
    '[0,0,0,255]': 'all black',
    ...
}

And I want that custom information to be present on the hovertemplate. Something like this (This image presents a value according to the color of the pixel):

hover_example

I want to display custom information on an Image like in this example. It doesn’t matter if I need to use anything different from px.Imshow.

This sample code is what I was testing on, it works as an MVP, so you guys can run it with just copy-paste.

from dash import Dash, html, dcc
from dash_bootstrap_components.themes import BOOTSTRAP
import plotly.express as px
import plotly.graph_objs as go
import requests
from io import BytesIO
from PIL import Image


def blank_fig():
    figura = go.Figure({
            'style': {'background': 'white', 'background-color': 'white'},
            'data': [],
            'layout': go.Layout(
                xaxis={
                    'showticklabels': False,
                    'ticks': '',
                    'showgrid': False,
                    'zeroline': False
                },
                yaxis={
                    'showticklabels': False,
                    'ticks': '',
                    'showgrid': False,
                    'zeroline': False
                }
            )
        }
    )
    return figura


def main_test():
    app = Dash(external_stylesheets=[BOOTSTRAP])
    app.title = "Dashboard test"
    app.layout = html.Div(
        layout_test(app),
        style={
            "background-color": "#6e8190",
            "padding": "20px",
        }
    )
    app.run(debug=True)


def layout_test(app):
    return html.Div(
        children=[
            dcc.Graph(
                figure=render_img(app),
            )
        ]
    )


def render_img(app):
    link_img = 'https://fastly.picsum.photos/id/63/200/300.jpg?hmac' \
               '=Zhw62KKdLbsw5yRcx9gVDEQq4kzPwjZUrJAJUIryu6k'
    try:
        response = requests.get(link_img, timeout=5)
        img = Image.open(BytesIO(response.content))

        fig = px.imshow(img)
        fig.update_traces(hovertemplate='Color: %{z}<extra></extra>')

    except (requests.exceptions.RequestException, IOError) as e:
        print(f"Failed to load image: {e}")
        fig = blank_fig()

    fig.update_layout(
        title=f'Test',
        title_font_color='white',
        xaxis=dict(gridcolor='#181f26', showticklabels=False, showline=False,
                   zeroline=False),
        yaxis=dict(gridcolor='#181f26', showticklabels=False, showline=False,
                   zeroline=False),
        plot_bgcolor='#181f26',
        paper_bgcolor='#181f26',
        coloraxis_showscale=False,
        autosize=False,
    )
    return fig


if __name__ == "__main__":
    main_test()

Any help would be much appreciated.

Right now I’m getting the RGBA values from the “z” value of the image/graph.

fig.update_traces(hovertemplate='Color: %{z}<extra></extra>')

I would like to do something like this:

rgba_dict[%{z}]

Or anything similar.

Any idea, anyone?

Or is this currently impossible?

Maybe with JS?

Hi @FMonzon I don’t know how to do this on the fly (in the browser using JS) but you could add customdata to your image and use this information in the hovertemplate:

import numpy as np
import plotly.express as px
import string
import plotly.graph_objects as go

categories = 10

# create dictionary for mapping of values --> labels
convert = {value: label for value, label in zip(range(categories), string.ascii_lowercase[:categories] )}

# create an image
arr = np.random.randint(0, categories, size=(30, 30))

# mapping
customdata = np.array([convert[val] for val in arr.flatten()]).reshape((30, 30))

#create figure
fig = go.Figure(go.Heatmap(z=arr, customdata=customdata, hovertemplate='<b>Your value</b>: %{customdata}<extra></extra>'))
fig.show()

The drawback is that the figure size (ammount of data) increases.