浏览图像序列与散景中的滑块

时间:2017-03-12 04:57:34

标签: python bokeh

我正在尝试使用Bokeh显示一系列图像,并希望以交互方式滑动或播放序列。当我运行我的脚本时,它会显示第一个图像,但是当我拖动滑块或单击播放按钮时图像不会更新。我的代码如下:

import numpy as np
import bokeh.io
from bokeh.plotting import figure
from bokeh.io import curdoc
from bokeh.layouts import layout
from bokeh.models import  ColumnDataSource, HoverTool, SingleIntervalTicker, Slider, Button, Label
from bokeh.palettes import Spectral1
from skimage.external import tifffile as T


img=T.imread('C:/Users/UserXX/Desktop/Image_Sequence.tif')
sources={}
frames=list(range(0,img.shape[0]))

for frame in frames:
    sources[frame]=ColumnDataSource(data=dict(image=[img[frame,:,:]]))

source1 = sources[0]


p_img = figure(plot_width=694, plot_height=520, x_range=[0,1388], y_range=[0, 1040])
label = Label(x=1.1, y=18, text=str(frames[0]), text_font_size='70pt', text_color='#eeeeee')
p_img.add_layout(label)
p_img.image(image='image', x=[0], y=[0], dw=[1388], dh=[1040],source=source1, palette="Spectral11")

slider = Slider(start=frames[0], end=frames[-1], value=frames[0],step=1, title="Frame")

def animate_update():
    frame = slider.value + 1
    if frame > frames[-1]:
        frame = frames[0]
    slider.value = frame



def slider_update(attr, old, new):
    global source
    global sources
    frame = slider.value
    label.text = str(frame)
    source= sources[frame]



slider.on_change('value', slider_update)


def animate():
    if button.label == '► Play':
        button.label = '❚❚ Pause'
        curdoc().add_periodic_callback(animate_update, 200)
    else:
        button.label = '► Play'
        curdoc().remove_periodic_callback(animate_update)

button = Button(label='► Play', width=60)
button.on_click(animate)

l = layout([[p_img],[slider, button],], sizing_mode='scale_width')
curdoc().add_root(l)
curdoc().title = "Image_Sequence"

我以此为例: https://github.com/bokeh/bokeh/blob/master/examples/app/gapminder/main.py 我不确定我将新图像数据传递给源的方式是否正确。 有什么建议吗?

2 个答案:

答案 0 :(得分:3)

在您的代码中需要修复或改进一些不同的东西,因此可能更容易学习和模拟这个简化的完整工作示例:

import numpy as np

from bokeh.io import curdoc
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, Slider
from bokeh.plotting import figure

N = 100

x_ = np.linspace(0, 10, 200)
y_ = np.linspace(0, 10, 200)
z_ = np.linspace(0, 10, N)

x, y, z = np.meshgrid(x_, y_, z_, indexing='xy')

data = np.sin(x+z)*np.cos(y)

source = ColumnDataSource(data=dict(image=[data[:, :, 0]]))

p = figure(x_range=(0, 10), y_range=(0, 10))
p.image(image='image', x=0, y=0, dw=10, dh=10, source=source, palette="Spectral11")

slider = Slider(start=0, end=(N-1), value=0, step=1, title="Frame")

def update(attr, old, new):
    source.data = dict(image=[data[:, :, slider.value]])

slider.on_change('value', update)

curdoc().add_root(column(p, slider))

请注意,每次滑块更改都会发生更新,即使是200x200,也会开始略微滞后(至少在我的系统上)。因此,您可能还需要考虑Throttling in Bokeh application

中描述的技术

enter image description here

答案 1 :(得分:2)

基于@ bigreddot的例子。拖动滑块或单击按钮时,我的代码可以更新图像。虽然对于尺寸较大的图像,它们的更新速度非常慢。

import numpy as np
from bokeh.plotting import figure,ColumnDataSource
from bokeh.io import curdoc
from bokeh.layouts import layout
from bokeh.models import  Slider, Button, Label
from bokeh.palettes import Spectral11
from skimage.external import tifffile as T


img_o=T.imread('C:/Users/UserXX/Desktop/Image_Sequence.tif')

frames=list(range(0,img_o.shape[0]))
img=np.flip(img_o,1)



source = ColumnDataSource(data=dict(image=[img[0,:,:]]))


p_img = figure(x_range=(0,1388), y_range=(0, 1040))
label = Label(x=1.1, y=18, text=str(frames[0]), text_font_size='70pt', text_color='#eeeeee')
p_img.add_layout(label)
im=p_img.image(image='image', x=0, y=0, dw=1388, dh=1040, source=source, palette="Spectral11")

slider = Slider(start=frames[0], end=frames[-1], value=frames[0],step=1, title="Frame")

def animate_update():
    frame = slider.value + 1
    if frame > frames[-1]:
        frame = frames[0]
    slider.value = frame

ds=im.data_source    

def slider_update(attr, old, new):

    new_data=dict()
    frame = slider.value
    label.text = str(frame)
    new_data['image']=[img[frame,:,:]]
    ds.data= new_data



slider.on_change('value', slider_update)


def animate():
    if button.label == '► Play':
        button.label = '❚❚ Pause'
        curdoc().add_periodic_callback(animate_update, 200)
    else:
        button.label = '► Play'
        curdoc().remove_periodic_callback(animate_update)

button = Button(label='► Play', width=60)
button.on_click(animate)

l = layout([[p_img],[slider,button],], sizing_mode='scale_width')
curdoc().add_root(l)
curdoc().title = "Image_sequence"

我主要改变数据传递到源的方式。 另一件事是这条线不起作用(第一帧被绘制但没有更新)

im=p_img.image(image='image', x=[0], y=[0], dw=[1388], dh=[1040], source=source, palette="Spectral11")

我改为:

im=p_img.image(image='image', x=0, y=0, dw=1388, dh=1040, source=source, palette="Spectral11")

可以更新图像。 唯一的区别是[]摆脱了参数x,y,dw,dh。但我不知道为什么它会引起问题。