I use plotly to visualize images with additional data in python jupyter notebooks (jupyter-lab).
I have currently three implementations, two show the desired result but are slow, the third one is fast but shows blurry images.
Especially when it comes to investigating behavior of image-processing networks, I need to see each pixel of the image. CSS already supports that simply by setting this style parameter
style="image-rendering: pixelated;"
I would like to include this as part of my plotly visualizations.
These are the options I know of. (One and two seem to do something similar under the hood)
plotly.express.imshow
HeatMap
to plot imagesf"data:image/png;base64,{base64.b64encode(res)}"
Again: The option 1 and 2 work, but are very slow compared to option 3. (Edit: >30x slower for 1024x1024 image, see below) This impacts the development when doing this on a regular basis. The option 3 is nice, but has the problem that png images are blurred.
Here an example run in jupyter lab
import cv2
import base64
import numpy as np
from plotly import graph_objects as go
import plotly.express as px
from IPython.display import display, HTML
image = np.random.uniform(0, 1, size=(50, 50))
display(px.imshow(image))
_, res = cv2.imencode(".png", image * 255)
data = b"data:image/png;base64," + base64.b64encode(res)
fig = go.FigureWidget()
n_y_pixel, n_x_pixel = image.shape[:2]
layout = go.Layout(
xaxis=dict(range=(0, n_x_pixel)),
yaxis=dict(range=(n_y_pixel, 0), scaleanchor="x", scaleratio=1.0),
images=[
dict(
source=data.decode(),
xref="x",
yref="y",
x=-0.5,
y=-0.5,
sizex=n_x_pixel,
sizey=n_y_pixel,
)
],
)
fig.update_layout(layout)
display(fig)
The manual hack is basically executing this in a separate cell afterwards. (It is not reliable, so you may want to reload the window and only plot option two)
display(HTML("<script>var imgElement = document.querySelector('image'); imgElement.style.imageRendering = 'pixelated'; </script>"))
My goal is to have option 3 with pixelated accuracy, without the need to hack it every time I plot something in every notebook. I don't see how this is possible, or even if this is simply a feature request to plotly.
Things I tried
Layout
where I could override the styledisplay(HTML(
hack in my plot function before the figure has no impact. This would be necessary if want to integrate it into my plotting functionThanks for any help!
I am using
Time measurements with an image of size (1024, 1024) in my browser
(simply using the code above, but using image = np.random.uniform(0, 1, size=(1024, 1024))
. plotly v5.15.0; chrome 114.0.5735.198, jupyter lab 3.3.2
px.imshow
As @EricLavault pointed out, binary_string=True
does the job.
import plotly.express as px
px.imshow(image, binary_string=True)
This shows a 2D image
(no-color) as a grayscale image including the pixelated effect, including a massive speedup