Skip to content

Commit 0752df7

Browse files
committed
modified tutorial
1 parent 78d2454 commit 0752df7

File tree

1 file changed

+68
-28
lines changed

1 file changed

+68
-28
lines changed

doc/python/imshow.md

Lines changed: 68 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -86,29 +86,9 @@ fig = px.imshow(img)
8686
fig.show()
8787
```
8888

89-
### Passing image data as a binary string
90-
91-
... add explanations here about `use_binary_string` and `contrast_rescaling`
92-
93-
```python
94-
import plotly.express as px
95-
import numpy as np
96-
img = np.arange(15**2).reshape((15, 15))
97-
fig = px.imshow(img, use_binary_string=True)
98-
fig.show()
99-
```
100-
101-
```python
102-
import plotly.express as px
103-
import numpy as np
104-
img = np.arange(13**2, dtype=np.uint8).reshape((13, 13))
105-
fig = px.imshow(img, use_binary_string=True, contrast_rescaling='dtype')
106-
fig.show()
107-
```
108-
10989
### Choose the colorscale to display a single-channel image
11090

111-
You can customize the [continuous color scale](/python/colorscales/) just like with any other Plotly Express function:
91+
You can customize the [continuous color scale](/python/colorscales/) just like with any other Plotly Express function. However, `color_continuous_scale` is ignored when using `binary_string=True`, since the image is always represented as grayscale (and no colorbar is displayed).
11292

11393
```python
11494
import plotly.express as px
@@ -199,22 +179,41 @@ fig = go.Figure(go.Image(z=img_rgb))
199179
fig.show()
200180
```
201181

202-
### Defining the data range covered by the color range with zmin and zmax
182+
### Passing image data as a binary string to `go.Image`
203183

204-
The data range and color range are mapped together using the parameters `zmin` and `zmax`, which correspond respectively to the data values mapped to black `[0, 0, 0]` and white `[255, 255, 255]`, or to the extreme colors of the colorscale in the case on single-channel data.
184+
The `z` parameter of `go.Image` passes image data in the form of an array or a list of numerical values, but it is also possible to use the `source` parameter, which takes a b64 binary string. Thanks to png or jpg compression, using `source` is a way to reduce the quantity of data passed to the browser, and also to reduce the serialization time of the figure, resulting in increased performance.
205185

206-
For single-channel data, the defaults values of `zmin` and `zmax` used by `px.imshow` and `go.Heatmap` are the extrema of the data range. For multichannel data, `px.imshow` and `go.Image` use slightly different default values for `zmin` and `zmax`. For `go.Image`, the default value is `zmin=[0, 0, 0]` and `zmax=[255, 255, 255]`, no matter the data type. On the other hand, `px.imshow` adapts the default `zmin` and `zmax` to the data type:
207-
- for integer data types, `zmin` and `zmax` correspond to the extreme values of the data type, for example 0 and 255 for `uint8`, 0 and 65535 for `uint16`, etc.
208-
- for float numbers, the maximum value of the data is computed, and zmax is 1 if the max is smaller than 1, 255 if the max is smaller than 255, etc. (with higher thresholds 2**16 - 1 and 2**32 -1).
186+
Note than an easier way of creating binary strings with `px.imshow` is explained below.
187+
188+
```python
189+
import plotly.graph_objects as go
190+
from skimage import data
191+
from PIL import Image
192+
import base64
193+
from io import BytesIO
194+
195+
img = data.astronaut() # numpy array
196+
pil_img = Image.fromarray(img) # PIL image object
197+
prefix = "data:image/png;base64,"
198+
with BytesIO() as stream:
199+
pil_img.save(stream, format="png")
200+
base64_string = prefix + base64.b64encode(stream.getvalue()).decode("utf-8")
201+
fig = go.Figure(go.Image(source=base64_string))
202+
fig.show()
203+
```
209204

210-
These defaults can be overriden by setting the values of `zmin` and `zmax`. For `go.Image`, `zmin` and `zmax` need to be given for all channels, whereas it is also possible to pass a scalar value (used for all channels) to `px.imshow`.
205+
### Defining the data range covered by the color range with zmin and zmax
206+
207+
The data range and color range are mapped together using the parameters `zmin` and `zmax` of `px.imshow` or `go.Image`, which correspond respectively to the data values mapped to black `[0, 0, 0]` and white `[255, 255, 255]`, or to the extreme colors of the colorscale in the case on single-channel data.
208+
209+
For `go.Image`, `zmin` and `zmax` need to be given for all channels, whereas it is also possible to pass a scalar value (used for all channels) to `px.imshow`.
211210

212211
```python
213212
import plotly.express as px
214213
from skimage import data
215214
img = data.astronaut()
216215
# Increase contrast by clipping the data range between 50 and 200
217-
fig = px.imshow(img, zmin=50, zmax=200)
216+
fig = px.imshow(img, zmin=50, zmax=200, binary_string=False)
218217
# We customize the hovertemplate to show both the data and the color values
219218
# See https://plotly.com/python/hover-text-and-formatting/#customize-tooltip-text-with-a-hovertemplate
220219
fig.update_traces(hovertemplate="x: %{x} <br> y: %{y} <br> z: %{z} <br> color: %{color}")
@@ -230,6 +229,21 @@ fig = px.imshow(img, zmin=[50, 0, 0], zmax=[200, 255, 255])
230229
fig.show()
231230
```
232231

232+
### Automatic contrast rescaling in `px.imshow`
233+
234+
When `zmin` and `zmax` are not specified, the `contrast_rescaling` arguments determines how `zmin` and `zmax` are computed. For `contrast_rescaling='minmax'`, the extrema of the data range are used. For `contrast_rescaling='infer'`, a heuristic based on the data type is used:
235+
- for integer data types, `zmin` and `zmax` correspond to the extreme values of the data type, for example 0 and 255 for `uint8`, 0 and 65535 for `uint16`, etc.
236+
- for float numbers, the maximum value of the data is computed, and zmax is 1 if the max is smaller than 1, 255 if the max is smaller than 255, etc. (with higher thresholds 2**16 - 1 and 2**32 -1).
237+
238+
These two modes can be used for single- and multichannel data. The default value is to use `'minmax'` for single-channel data (as in a Heatmap trace) and `infer` for multi-channel data (which often consist of uint8 data). In the example below we override the default value by setting `contrast_rescaling='infer'` for a single-channel image.
239+
240+
```python
241+
import plotly.express as px
242+
img = np.arange(100, dtype=np.uint8).reshape((10, 10))
243+
fig = px.imshow(img, contrast_rescaling='infer')
244+
fig.show()
245+
```
246+
233247
### Ticks and margins around image data
234248

235249
```python
@@ -327,5 +341,31 @@ fig.show(config={'modeBarButtonsToAdd':['drawline',
327341
]})
328342
```
329343

344+
### Passing image data as a binary string
345+
346+
`px.imshow` can pass the data to the figure object either as a list of numerical values, or as a png binary string which is passed directly to the browser. While the former solution offers more flexibility (values can be of float or int type, while values are rescaled to the range [0-255] for an image string), using a binary string is usually faster for large arrays. The parameter `binary_string` controls whether the image is passed as a png string (when `True`) or a list of values (`False`). Its default value is `True` for multi-channel images and `False` for single-channel images. When `binary_string=True`, image data are always represented using a `go.Image` trace.
347+
348+
```python
349+
import plotly.express as px
350+
import numpy as np
351+
img = np.arange(15**2).reshape((15, 15))
352+
fig = px.imshow(img, binary_string=True)
353+
fig.show()
354+
```
355+
356+
### Changing the level of compression of the binary string in `px.imshow`
357+
358+
The `binary_compression_level` parameter controls the level of compression to be used by the backend creating the png string. Two different backends can be used, `pypng` (which is a dependency of `plotly` and is therefore always available), and `pil` for Pillow, which is often more performant. The compression level has to be between 0 (no compression) and 9 (highest compression), although increasing the compression above 4 and 5 usually only offers diminishing returns (no significant compression gain, at the cost of a longer execution time).
359+
360+
```python
361+
import plotly.express as px
362+
from skimage import data
363+
img = data.camera()
364+
for compression_level in range(0, 9):
365+
fig = px.imshow(img, binary_string=True, binary_compression_level=compression_level)
366+
print(f"compression level {compression_level}: length of {len(fig.data[0].source)}")
367+
fig.show()
368+
```
369+
330370
#### Reference
331371
See https://plotly.com/python/reference/#image for more information and chart attribute options!

0 commit comments

Comments
 (0)