Thank you Bryan for pointing out. The square is generated from figure.square()
and I also put it in the renderer of BoxEditTool
for drag and drop (and of course I would also love to resize it in the future).
Here is code example:
import numpy as np
import skimage
import skimage.io
# Import Bokeh modules for interactive plotting
import bokeh.io
from bokeh.models import (BoxEditTool,
PointDrawTool,
PolyDrawTool,
PolyEditTool,
LineEditTool,
ColumnDataSource)
import bokeh.palettes
import bokeh.plotting
from bokeh.layouts import column
from bokeh.plotting import (
figure,
curdoc,
output_file,
show
)
def bokeh_imshow(im, color_mapper=None, plot_height=400, length_units='pixels',
interpixel_distance=1.0):
# Get shape, dimensions
n, m, _ = im.shape
dw = m * interpixel_distance
dh = n * interpixel_distance
# Set up figure with appropriate dimensions
s = ColumnDataSource(data = dict(x=[0,1],y=[0,1])) #points of the line
callback = bokeh.models.CustomJS(args=dict(s=s), code="""
var geometry = cb_data['geometry'];
console.log(geometry);
var x_data = geometry.x; // current mouse x position in plot coordinates
var y_data = geometry.y; // current mouse y position in plot coordinates
console.log("(x,y)=" + x_data+","+y_data); //monitors values in Javascript console
""")
hover_tool = bokeh.models.HoverTool(callback=callback)
plot_width = int(m/n * plot_height)
p = bokeh.plotting.figure(plot_height=n,
plot_width=m,
x_range=[0, m],
y_range=[0, n],
x_axis_label=length_units,
y_axis_label=length_units,
tools= [hover_tool,
"crosshair,box_zoom,wheel_zoom,pan,reset"])
p.line(x='x', y='y', source=s)
# Set color mapper; we'll do Viridis with 256 levels by default
if color_mapper is None:
color_mapper = bokeh.models.LinearColorMapper(bokeh.palettes.viridis(256))
# Display the image
# https://stackoverflow.com/questions/52433129/python-bokeh-get-image-from-webcam-and-show-it-in-dashboard
img = np.empty((n, m), dtype=np.uint32)
view = img.view(dtype=np.uint8).reshape((n, m, 4))
view[:,:,0] = im[:,:,0] # copy red channel
view[:,:,1] = im[:,:,1] # copy blue channel
view[:,:,2] = im[:,:,2] # copy green channel
view[:,:,3] = 255
img = img[::-1] # flip for Bokeh
im_bokeh = p.image_rgba(image=[img], x=0, y=0, dw=m, dh=n)
# add a square renderer with a size, color, and alpha
sqr_source = ColumnDataSource(data=dict(x=[50], y=[50]))
sqs = p.square(x='x', y='y', source=sqr_source, size=80, color="olive", alpha=0.5)
# create ColumnDataSource from a dict
source = ColumnDataSource(data=dict(x=[1, 2, 3, 4, 5], y=[1, 2, 3, 4, 5]))
c1 = p.circle(x="x", y="y", size=10, hover_color="red", source=source)
tool1 = PointDrawTool(renderers=[c1])
# add box editable tool
source1 = ColumnDataSource(data=dict(x=[5], y=[5]))
source2 = ColumnDataSource(data=dict(x=[2], y=[3]))
r1 = p.rect(x='x', y='y', width=10, height=5, source=source1)
r2 = p.rect(x='x', y='y', width=5, height=5, source=source2)
tool2 = BoxEditTool(renderers=[r1, r2, sqs], empty_value=1)
p1 = p.patches([], [], fill_alpha=0.4)
ps = ColumnDataSource(data=dict(xs=[[10, 20, 30, 100]], ys=[[30, 50, 20, 250]]))
def show_updated_source(attr, old, new):
print(attr)
print(old)
print(new)
ps.on_change('data', show_updated_source)
p2 = p.patches(xs='xs', ys='ys', fill_color='green', fill_alpha=0.4, source=ps)
c1 = p.circle([], [], size=10, color='red')
draw_tool = PolyDrawTool(renderers=[p1, p2])
edit_tool = PolyEditTool(renderers=[p1, p2], vertex_renderer=c1)
line_source = ColumnDataSource(data = dict(x=[10, 100], y=[20, 100]))
edit_line = p.line(x='x', y='y', source=line_source)
c2 = p.circle([], [], fill_color="white", size=8)
edit_line_tool = LineEditTool(renderers=[edit_line], intersection_renderer=c2)
p.add_tools(tool1, tool2, draw_tool, edit_tool, edit_line_tool)
return p
im = skimage.io.imread('wand.jpg') # Returned image: RGB-image MxNx3 or RGBA-image MxNx4
p = bokeh_imshow(im, plot_height=680, interpixel_distance=0.0636)
# put the plot in a layout and add to the document
curdoc().add_root(column(p))
My goal is to access vertices of Polygon(xy of all connected points eg. in matplotlib
it’s easy to access via polygon.xy
), Line(xy of the connected points), and Square (corners’ points).