How do I work with images in Bokeh (Python)

Posted on

Question :

How do I work with images in Bokeh (Python)

For example you can plot an image in matplotlib using this code:

%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
img=mpimg.imread('image.png')
plt.imshow(img)

Is something like this possible with Bokeh(0.10)?

Answer #1:

You can use the ImageURL glyph (image_url plot method)to load images locally or from the web.

from bokeh.plotting import figure, show, output_file

output_file('image.html')

p = figure(x_range=(0,1), y_range=(0,1))
p.image_url(url=['tree.png'], x=0, y=1, w=0.8, h=0.6)
## could also leave out keywords
# p.image_url(['tree.png'], 0, 1, 0.8, h=0.6)  
show(p)

Image Example

One gotcha – if you graph only an image (and no other data), you’ll have to explicitly set the plot ranges.

Here’s the docs:

http://docs.bokeh.org/en/latest/docs/reference/models/glyphs.html#bokeh.models.glyphs.ImageURL

Answered By: Luke Canavan

Answer #2:

The earlier answer was helpful. However, I wanted an image only option without any additional object. So, adding the answer for Bokeh version 0.12.0 and removed all the grids, axes and toolbar.

from bokeh.plotting import figure, curdoc
from bokeh.models import ColumnDataSource, Range1d

bosch_logo = "static/tree.jpg"
logo_src = ColumnDataSource(dict(url = [bosch_logo]))

page_logo = figure(plot_width = 500, plot_height = 500, title="")
page_logo.toolbar.logo = None
page_logo.toolbar_location = None
page_logo.x_range=Range1d(start=0, end=1)
page_logo.y_range=Range1d(start=0, end=1)
page_logo.xaxis.visible = None
page_logo.yaxis.visible = None
page_logo.xgrid.grid_line_color = None
page_logo.ygrid.grid_line_color = None
page_logo.image_url(url='url', x=0.05, y = 0.85, h=0.7, w=0.9, source=logo_src)
page_logo.outline_line_alpha = 0 
curdoc().add_root(page_logo)
Answered By: Jayant

Answer #3:

Running this example using bokeh serve is a bit more tricky. I suggest to setup working directory properly:

server_folder/
     +main.py
     +static/
         +logo.png

.. and run bokeh serve command from directory ABOVE server_folder

bokeh serve server_folder --show

Then this code works for me

#main.py file
from bokeh.plotting import figure, curdoc
x_range = (-20,-10) # could be anything - e.g.(0,1)
y_range = (20,30)
p = figure(x_range=x_range, y_range=y_range)
#img_path = 'https://docs.bokeh.org/en/latest/_static/images/logo.png'
img_path = 'server_folder/static/logo.png'
p.image_url(url=[img_path],x=x_range[0],y=y_range[1],w=x_range[1]-x_range[0],h=y_range[1]-y_range[0])
doc = curdoc()
doc.add_root(p)

enter image description here

Answered By: Karel Marik

Answer #4:

Another option is to display the image in a div.:

from bokeh.io import output_notebook, show
from bokeh.models.widgets import Div

output_notebook()
div_image = Div(text="""<img src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/7.png" alt="div_image">""", width=150, height=150)
show(div_image)

Squirtle sprite

ImageURL can’t get updated dynamically with a callback. However, using a div, you can do so by treating the div_image.text as a regular Python string, for example:

from ipywidgets import interact

from bokeh.io import output_notebook, show, push_notebook
from bokeh.models.widgets import Div

output_notebook()
div_image = Div(text="""<img src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/1.png" alt="div_image">""", width=100, height=100)

def update(pokemon_number=1):
    div_image.text = """<img src="https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/{}.png" alt="div_image">""".format(pokemon_number)
    push_notebook()

show(div_image, notebook_handle=True)

interact(update, pokemon_number=[1, 4, 7])

Pokemon selector

Of course, the image source can also point to a local file.

(Tested in Python 3.7.3 and bokeh 1.2.0)

Leave a Reply

Your email address will not be published.