交互式滑块用于改变Bokeh图像绘制中使用的切片。

5
我想使用Bokeh将图片放在IPython笔记本中。特别是,我经常与具有3个或更多维度的多维NumPy数组交互。以3维数组为例。一个常见的例子是RGB图像。三个维度是x、y和颜色。
我希望使用Bokeh在IPython笔记本中绘制单个图像通道。我想提供一个交互式滑块,允许IPython笔记本的用户单击第三个维度的每个索引,例如颜色。
我的以下代码(在IPython笔记本中运行时)成功显示第一个颜色通道的绘图。但我无法弄清楚是什么导致了我调用interact时的错误。我是否正确定义了我的ColumnDataSource,并且在Bokeh绘图构建中正确引用了它?
# imports
import numpy as np
from scipy.misc import imread

from bokeh.plotting import figure, show
from bokeh.io import output_notebook
from bokeh.models import ColumnDataSource
from bokeh.palettes import Greys9

from IPython.html.widgets import interact

# enable Bokeh to plot to the notebook 
output_notebook()

# Make the Bokeh plot of the "first" layer of the 3D data
## This part works
TOOLS="pan, box_zoom, reset, save"

  # The image from https://windycitizensports.files.wordpress.com/2011/10/baboon.jpg?w=595
RGB_image = imread('/Users/curt/Downloads/BaboonRGB.jpg')

nx, ny, n_colors = RGB_image.shape

source = ColumnDataSource(data={'image': RGB_image[:, :, 0]})

p = figure(title="ColorChannel", 
           tools=TOOLS, 
           x_range=[0, nx], 
           y_range=[0, ny],
          )

p.image([source.data['image'][::-1, :]-1],
        x=0, 
        y=0, 
        dh=[ny], 
        dw=[nx], 
        palette=Greys9,
        source=source,
        )

show(p)

# try to add interactive slider
## This part does not work & gives a JavaScript error

def update(idx=0):
    global RGB_image
    source.data['image'] = RGB_image[:, :, idx]
    source.push_notebook()

interact(update, idx=(0, 2))

这个 Javascript 错误是:

Javascript error adding output!
TypeError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The provided float value is non-finite.
See your browser Javascript console for more details.

我不确定这是怎么回事。我尝试通过在定义后立即执行RGB_Image = RGB_Image.astype(float)RGB_Image强制转换为浮点数,但是我仍然得到了相同的错误。


1
虽然我无法完全复制您的问题,因为我无法让IPython控制台像您的IPython笔记本那样工作,但是我确实发现了您代码中的一个潜在问题。您是否检查过更新函数是否将idx用作单个数字?RGB_image[:, :, idx]数组列表可以完美地接受idx作为元组,这会导致源数据['image']与源数据的其余部分之间存在数据格式不匹配。 - Uvar
1个回答

5

实质上,预定义的图像格式与您尝试更新的格式不一致。

以下是有效的解决方案:

def update(idx=0):
    global RGB_image
    source.data['image'] = RGB_image[:, :, idx]
    p.image([source.data['image'][::-1, :]-1],
        x=0, 
        y=0, 
        dh=[ny], 
        dw=[nx], 
        palette=Greys9,
        source=source,
        )
    show(p)

interact(update, idx=(0, 2))

我承认不停地定义图像并不是做这件事的首选方式,但至少它应该让你知道在哪里寻找。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接