从 bokeh==2.1.1 升级到 bokeh==2.2.0 会破坏figure.image_rgba()

Nic*_*gan 3 python python-3.x bokeh

使用以下代码时,此代码片段会呈现图像(尽管是颠倒的)bokeh==2.1.1

from PIL import Image
import numpy as np
import requests

from bokeh.plotting import figure
from bokeh.io import output_notebook
from bokeh.plotting import show
output_notebook()

response = requests.get('https://upload.wikimedia.org/wikipedia/en/a/a9/Example.jpg', stream=True)
rgba_img = Image.open(response.raw).convert("RGBA")
numpy_img = np.array(rgba_img)

fig = figure()
plotted_image = fig.image_rgba(image=[np_img], x=50, y=50, dw=50, dh=50)
show(fig)
Run Code Online (Sandbox Code Playgroud)

bokeh==2.2.0在(以及更高版本)中运行完全相同的代码不会输出任何内容,并且不会引发任何错误。

bokeh 的发行说明没有提及任何更改image_rgba()

big*_*dot 6

错误出现在浏览器中的 JS 控制台中(因为错误实际上发生在浏览器中,而不是“python 端”):

未处理的承诺拒绝:错误:需要 2D 数组

如果你看一下np_img,你会发现它不是一个二维数组:

In [3]: np_img.shape
Out[3]: (297, 275, 4)

In [4]: np_img.dtype
Out[4]: dtype('uint8')
Run Code Online (Sandbox Code Playgroud)

Bokeh 需要 uint32 的 2D 数组,而不是 uint8 的 3D 数组,而且情况一直如此,并且文档中已经演示了这一点。过去可能意外或无意地接受了 3D 数组(这就是发行说明中不会注明任何更改的原因),或者可能在 NumPy 或 PIL 方面发生了某些更改并转换为 NumPy 数组。无论如何,您需要创建一个 2D 视图:

np_img = np.array(rgba_img)

np_img2d = np_img.view("uint32").reshape(np_img.shape[:2])

fig = figure()
plotted_image = fig.image_rgba(image=[np_img2d], x=50, y=50, dw=50, dh=50)
Run Code Online (Sandbox Code Playgroud)