Home > Software engineering >  matplotlib plot numpy array of images as markers
matplotlib plot numpy array of images as markers

Time:08-30

There are a lot of posts on plotting pre-saved png images as scatter plot markers but I'm wondering if there's a way to take an array of 2D arrays (lets naively call them images) and, given x and y coordinates, use them as scatter markers without having to save out as pngs and then read in.

For example, say you have these rather dull 'images':

import numpy as np
images = np.random.uniform(0,1,(5,10,10))

... that is, we have 5 lots of 10 by 10, 2D images.

If we want to plot these 'images' as markers at the following 5 locations specified by x and y coordinates:

x, y, = np.array([0, 2, -3, 6, 6.5]), np.array([10, 3, -2, -1, 0.2])

... what is the best way to go about doing this?


Closest example I have tried but failed to make work:

import matplotlib.pyplot as plt
import numpy as np
from PIL import Image
from matplotlib.offsetbox import AnnotationBbox, OffsetImage

# Convert the images into PIL images
# How? Using: https://stackoverflow.com/a/62144323/8188120
# Why? Maybe PIL images are nice and easy for plotting as markers.. I'm grasping at straws really

pil_images = []
for i in range(images.shape[0]):
    pil_images.append(Image.fromarray(np.uint8(images[i])).convert('RGB'))

# Try plotting the images as markers
# Why this method? Saw it in this thread and continued grasping for more straws: https://stackoverflow.com/a/53851017/8188120

fig, ax = plt.subplots()
for i in range(len(pil_images)):
    ab = AnnotationBbox(OffsetImage(pil_images[i]), x[i], y[i], frameon=False)
    ax.add_artist(ab)
fig.savefig(image_path   'funny_markers.png')
plt.close('all')

CodePudding user response:

You need to set the limits of the axis accordingly, or they would default to just (0,1):

from matplotlib.offsetbox import OffsetImage, AnnotationBbox
fig, ax = plt.subplots()
for x0, y0, img in zip(x, y, images):
    ab = AnnotationBbox(OffsetImage(img, zoom=5, cmap='gray'), (x0, y0), frameon=False)
    ax.add_artist(ab)
plt.xlim(x.min(), x.max() 1)
plt.ylim(y.min(), y.max() 1)
plt.show()

Output:

enter image description here

  • Related