I want to read a list of images into Python/Matplotlib and then plot this images instead of other markers (like points) in a graph. I have tried with imshow but I didn't succeed, because I cannot shift the image to another position and scale it appropriately. Maybe somebody has a good idea : )

47
votes
There are some other questions about this here and here, although whether those solutions will work for you depends on exactly what you need.
- BrenBarn
Try this: matplotlib.org/examples/pylab_examples/demo_annotation_box.html
- Nitish
2 Answers
51
votes
There are two ways to do this.
- Plot the image using
imshowwith theextentkwarg set based on the location you want the image at. - Use an
OffsetImageinside anAnnotationBbox.
The first way is the easiest to understand, but the second has a large advantage. kThe annotation box approach will allow the image to stay at a constant size as you zoom in. Using imshow will tie the size of the image to the data coordinates of the plot.
Here's an example of the second option:
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
from matplotlib.cbook import get_sample_data
def main():
x = np.linspace(0, 10, 20)
y = np.cos(x)
image_path = get_sample_data('ada.png')
fig, ax = plt.subplots()
imscatter(x, y, image_path, zoom=0.1, ax=ax)
ax.plot(x, y)
plt.show()
def imscatter(x, y, image, ax=None, zoom=1):
if ax is None:
ax = plt.gca()
try:
image = plt.imread(image)
except TypeError:
# Likely already an array...
pass
im = OffsetImage(image, zoom=zoom)
x, y = np.atleast_1d(x, y)
artists = []
for x0, y0 in zip(x, y):
ab = AnnotationBbox(im, (x0, y0), xycoords='data', frameon=False)
artists.append(ax.add_artist(ab))
ax.update_datalim(np.column_stack([x, y]))
ax.autoscale()
return artists
main()

34
votes
If you want different images:
This is now the first reply when googling "matplotlib scatter with images". If you're like me and actually need to plot different images on each image, try this minimalied example instead. Just be sure to input your own images.
import matplotlib.pyplot as plt
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
def getImage(path):
return OffsetImage(plt.imread(path))
paths = [
'a.jpg',
'b.jpg',
'c.jpg',
'd.jpg',
'e.jpg']
x = [0,1,2,3,4]
y = [0,1,2,3,4]
fig, ax = plt.subplots()
ax.scatter(x, y)
for x0, y0, path in zip(x, y,paths):
ab = AnnotationBbox(getImage(path), (x0, y0), frameon=False)
ax.add_artist(ab)
