I have a single-channel image where each integer pixel value maps to a string. For example 5 -> ‘person’. I’m trying to create an interactive image where hovering over a pixel will display it’s corresponding string.
I figured using plotly heatmaps might be the way to do this. The issues I’m having are:
- It’s really slow. If I make my numpy array even (100,100) size it takes minutes to load. I’m thinking it might be because my code is not efficient?
- I can’t figure out how to maintain aspect ratio. So if my image is a size (100,100) numpy array, I’d like the plot to also be (100,100) pixels.
- using blank values for
z_text
seems like a bad workaround, but settingannotation_text=None
doesn’t seem to work.
Can anyone help me out here? Here’s what I’ve got:
import numpy as np import plotly.graph_objs as go from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot init_notebook_mode(connected=True) import plotly.figure_factory as ff z = np.random.randint(0,6, size=(10, 10)) z_text = np.full(z.shape, '', dtype=str) d = {0:'a', 1:'b', 2:'c', 3:'d', 4:'e', 5:'f'} class_mat = np.vectorize(d.get)(z) fig = ff.create_annotated_heatmap(z, annotation_text=z_text, text=class_mat, hoverinfo='text', colorscale='Viridis', ) fig.layout.title = 'Semantic Segmentation' iplot(fig, filename='annotated_heatmap_text')
And here’s what it currently looks like:
Also if a plotly heatmap is not the best way to go about this I’d love to hear any alternatives!
Note: I’m currently displaying inside jupyterlab.
Advertisement
Answer
I’m not sure if I’ve gotten every detail correct here, but the code in the snippet below will produce the following plot in a Jupyter Notebook. The line that handles the aspect ratio is:
fig['layout']['yaxis']['scaleanchor']='x'
You can also use:
fig.update_layout(yaxis = dict(scaleanchor = 'x'))
Plot 1:
Plot 2:
Just make sure to include:
fig.update_layout(plot_bgcolor='rgba(0,0,0,0)')
Or else you’ll end up with this:
Code 1 – My edits to your sample:
fig.data[0]['hoverinfo'] = 'all' fig['layout']['yaxis']['scaleanchor']='x' fig['layout']['xaxis']['gridcolor'] = 'rgba(0, 0, 0, 0)' fig['layout']['yaxis']['gridcolor'] = 'rgba(0, 0, 0, 0)' fig['layout']['yaxis']['color'] = 'rgba(0, 0, 0, 0)'
Code 2 – The whole thing for an easy copy&paste:
import numpy as np import plotly.graph_objs as go from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot init_notebook_mode(connected=True) import plotly.figure_factory as ff #%qtconsole z = np.random.randint(0,6, size=(10, 10)) z_text = np.full(z.shape, '', dtype=str) d = {0:'a', 1:'b', 2:'c', 3:'d', 4:'e', 5:'f'} class_mat = np.vectorize(d.get)(z) fig = ff.create_annotated_heatmap(z, annotation_text=z_text, text=class_mat, hoverinfo='text', colorscale='Viridis', # x = list('ABCDEFGHIJ'), # y = list('ABCDEFGHIJ') ) fig.layout.title = 'Semantic Segmentation' # My suggestions: fig.data[0]['hoverinfo'] = 'all' fig['layout']['yaxis']['scaleanchor']='x' fig['layout']['xaxis']['gridcolor'] = 'rgba(0, 0, 0, 0)' fig['layout']['yaxis']['gridcolor'] = 'rgba(0, 0, 0, 0)' fig['layout']['yaxis']['color'] = 'rgba(0, 0, 0, 0)' fig.update_layout(plot_bgcolor='rgba(0,0,0,0)') fig.show()
Speed:
Even this small figure takes some time to plot, but so far I do not have any suggestions on how to speed things up.