我需要绘制图像的轮廓,即绘制矩阵列的值。
并将其实现为拖动工具,它将根据光标在上方图形上方的位置自动更新下方图形:
基于文档中的“新的自定义工具” example,我编写了一个可以正常工作但有几个问题的代码:
import numpy as np
import bokeh.plotting as bp
from bokeh.models import CustomJS
from bokeh.layouts import layout, column, row
from bokeh.io import reset_output
from PIL import Image
im = Image.open(r'C:\Documents\image1.jpg')
z = np.array(im)[:,:,0]
from bokeh.core.properties import Instance, Float
from bokeh.io import output_file, show, output_notebook
from bokeh.models import ColumnDataSource, Tool
from bokeh.plotting import figure
from bokeh.util.compiler import TypeScript
from bokeh.layouts import layout, column, row
#output_file("a.html")
#reset_output()
# image vertical profile tool
TS_CODE = """
import {GestureTool, GestureToolView} from "models/tools/gestures/gesture_tool"
import {ColumnDataSource} from "models/sources/column_data_source"
import {GestureEvent} from "core/ui_events"
import * as p from "core/properties"
export class DrawToolView extends GestureToolView {
model: DrawTool
//this is executed when the pan/drag event starts
_pan_start(_ev: GestureEvent): void {
this.model.source.data = {x: [], y: []}
}
//this is executed on subsequent mouse/touch moves
_pan(ev: GestureEvent): void {
const {frame} = this.plot_view
const {sx, sy} = ev
if (!frame.bbox.contains(sx, sy))
return
const x = frame.xscales.default.invert(sx)
const y = frame.yscales.default.invert(sy)
var res = Array(128);
var rx = Math.round(x);
for(var i=0; i<128; i++) res[i] = this.model.zz.data["z"][i*225+rx];
this.model.source.data = {
x: Array(128).fill(0).map(Number.call, Number),
y: res
};
this.model.source.change.emit()
}
// this is executed then the pan/drag ends
_pan_end(_ev: GestureEvent): void {}
}
export namespace DrawTool {
export type Attrs = p.AttrsOf<Props>
export type Props = GestureTool.Props & {
source: p.Property<ColumnDataSource>,
zz: p.Property<ColumnDataSource>,
width: p.Float
}
}
export interface DrawTool extends DrawTool.Attrs {}
export class DrawTool extends GestureTool {
properties: DrawTool.Props
constructor(attrs?: Partial<DrawTool.Attrs>) {
super(attrs)
}
tool_name = "Drag Span"
icon = "bk-tool-icon-lasso-select"
event_type = "pan" as "pan"
default_order = 12
static initClass(): void {
this.prototype.type = "DrawTool"
this.prototype.default_view = DrawToolView
this.define<DrawTool.Props>({
source: [ p.Instance ],
zz: [ p.Instance ],
width: [ p.Float ]
})
}
}
DrawTool.initClass()
"""
class DrawTool(Tool):
__implementation__ = TypeScript(TS_CODE)
source = Instance(ColumnDataSource)
zz = Instance(ColumnDataSource)
width = Float()
output_notebook()
source = ColumnDataSource(data=dict(x=[], y=[]))
zz = ColumnDataSource(data=dict(z=z.flatten()))
p1 = figure(plot_width=600, plot_height=200, x_range=(0, 225), y_range=(0, 128),
tools=[DrawTool(source=source, zz=zz, width=225)])
im = p1.image(image=[np.flipud(z)], x=0, y=0, dw=225,
dh=128, palette='Greys256')
p2 = figure(plot_width=600, plot_height=200)
p2.line('x', 'y', source=source)
bp.show(column(p1, p2))
1)现在图像尺寸已被硬编码:如何将图像尺寸从python导入js?
2)图像两次传输到客户端:首先作为image()
的参数,然后作为按钮图的源。如何从DrawTool访问图像“源”?
3)如果(所有这些代码都在一个jupyter单元中)我第二次运行它,则它拒绝在控制台Model 'DrawTool' does not exist.
中绘制任何带有javascript错误的内容,第三次,第四次运行并继续运行精细。 bokeh试图在此错误消息中告诉我什么?
答案 0 :(得分:1)
1)现在图像尺寸已被硬编码:如何输入图像尺寸 从python到js?
2)图像两次传输到客户端:首先作为参数 到image(),然后作为按钮图的源。如何进入 来自DrawTool的图像“源”?
答案是相同的,为要存储在DrawTool
上的数据添加更多属性(在Python和JS上)。例如。另一个Instance
用于保存图像数据的另一个ColumnDataSource
,以及宽度和高度的整数属性。
3)如果(所有这些代码都在一个jupyter单元中)我第二次运行它,则它拒绝在控制台模型'DrawTool'中不存在带有JavaScript错误的任何内容。第三次,第四次以及以后继续运行都可以。 bokeh试图在此错误消息中告诉我什么?
此消息表明BokehJS对DrawTool
一无所知,其原因是,由于笔记本中的工作方式,自定义扩展仅在您调用{{1 }}。因此,您必须在定义自定义扩展名后再次调用output_notebook
。。我不喜欢这种状况,但是我们对此无能为力。