python - 在散景中使用滑块过滤图像
问题描述
我正在尝试根据其 alpha 值过滤 RGBA 图像,例如,使用 Bokeh 回调。我研究这个图书馆不到一周,所以我对它的了解真的很原始。从 API示例中,我不太了解如何使用这些回调。我实现我想要的方法如下:
### RGBA Image
N = 20
img = np.empty((N,N, 4), dtype=np.uint8)
for i in range(N):
for j in range(N):
img[i, j, 0] = int(i/N*255)
img[i, j, 1] = 158
img[i, j, 2] = int(j/N*255)
img[i, j, 3] = np.random.randint(1, 255)
mask = img[:, :, 3]
img = np.squeeze(img.view(np.uint32))
source = ColumnDataSource(data=(dict(image=[img],
x=[0],
y=[0],
dw=[10],
dh=[10])))
p = figure(x_range=(0,10), y_range=(0,10))
p.image_rgba(source=source, image='image', x='x', y='y', dw='dw', dh='dh')
### Threshold Slider
def slider_callback(source=source):
data = source.data
img = data['image']
img = img * (mask > cb_obj.value).astype(int)
source.change.emit();
t_slider = Slider(start=0, end=255, value=255, step=1,
title="Threshold", width=140,
callback=CustomJS.from_py_func(slider_callback))
l = layout([t_slider, p])
curdoc().add_root(l)
show(l)
由于在更改滑块值时我没有看到绘图有任何变化,我想我不知道如何使用这个回调。
解决方案
首先,作为一个温和的建议:请不要在示例代码中省略导入。其他人提供帮助的最快方法是能够立即、直接、按原样运行示例代码,这对于不完整的代码是不可能的
这段代码有几个不同的问题,我将尝试解决它们:
CustomJS.from_py_func
已弃用并将在将来删除,不应使用即使不是这种情况,
from_py_func
最终也会生成在您的浏览器中运行的JavaScript代码。它只能转换简单的纯 Python dode,不能转换任何依赖于 Numpy 或 Pandas 等真正 Python 库的 Python 代码。您的调用和所有花哨的切片都是浏览器一无所知的Numpy函数,因此这种方法不可能奏效。astype
因此,为了能够在回调中运行真正的 Python 代码,您必须制作一个Bokeh Server 应用程序需要明确的是,Bokeh 服务器应用程序必须与bokeh 服务器一起运行,即类似于
bokeh serve --show myapp.py
回调的逻辑也不对。它为局部变量分配一个新值
img
,然后将其丢弃。它不会更新source.data
触发 Bokeh 根据新数据更新绘图的值。你需要一个回调和连接,更像:t_slider = Slider(start=0, end=255, value=255, step=1, title="Threshold", width=140) def slider_callback(attr, old, new): source.data['image'] = [(mask > t_slider.value).astype(int)] t_slider.on_change('value', slider_callback)
另请注意,
source.data['image']
该值的列表值需要是图像列表/数组(因为image
可以一次显示多个图像),因此列表是相关的。
如果进行上述更改并使用 运行您的代码bokeh serve
,那么在滑动滑块时绘图会更新的意义上,事情会“起作用”。但是回调逻辑将大部分图像数组设置为零,从而导致空白图。如果不了解您要实际完成的工作,就无法在回调逻辑方面提供更多帮助。
编辑:如果您的意图是使用掩码更新显示的图像,您还应该知道,您必须在每次回调中复制原始图像。否则,您将在回调第一次运行时根据原始版本进行更新,但随后的回调将永远修改已修改的版本。即你需要这样的东西:
def slider_callback(attr, old, new):
newimg = img.copy()
newimg[(mask > t_slider.value).astype(int)] = 0
source.data['image'] = [newimg]
推荐阅读
- r - 计算 R 中两个掷骰子总和的概率
- sql - 根据评估几列中的某些列是否为真来创建计算列?
- python - 在 Python 中查找井字游戏的结果
- sql - sql join 给出累积结果
- python - 如何将变量分配给要排序的数字
- javascript - 从父组件动态传递 v-date-picker 的默认日期并从子组件返回更改的日期
- batch-file - 批处理“找不到文件”
- c - 如何像访问数组一样通过指针访问结构的成员?
- python - 如何确定图片上看不到的轮廓在哪里并绘制出来?
- apache-camel - 如何在路线到达终点之前在 Camel 中确认 Google Pubsub 消息?