У меня есть 2-й график рассеяния точек, соответствующих изображениям. Мне было интересно, есть ли простой способ отображения соответствующего изображения (как всплывающего окна или всплывающей подсказки), когда вы наводите указатель мыши на каждую точку? Я пробовал замысловато, но выяснил, что вам нужно вручную отредактировать javascript, чтобы заставить событие зависания работать. Есть ли простое решение только с matplotlib или другим распространенным пакетом?
Изображение Python отображается при наведении курсора на точку
Ответ 1
Найдите здесь полное решение о том, как отображать изображение при наведении курсора. Он использует 'motion_notify_event'
для обнаружения, когда мышь находится над точкой разброса (зависание). Если это так, он отображает аннотация изображения с соответствующим изображением рядом с нависшей точкой рассеяния.
import matplotlib.pyplot as plt
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
import numpy as np; np.random.seed(42)
# Generate data x, y for scatter and an array of images.
x = np.arange(20)
y = np.random.rand(len(x))
arr = np.empty((len(x),10,10))
for i in range(len(x)):
f = np.random.rand(5,5)
arr[i, 0:5,0:5] = f
arr[i, 5:,0:5] =np.flipud(f)
arr[i, 5:,5:] =np.fliplr(np.flipud(f))
arr[i, 0:5:,5:] = np.fliplr(f)
# create figure and plot scatter
fig = plt.figure()
ax = fig.add_subplot(111)
line, = ax.plot(x,y, ls="", marker="o")
# create the annotations box
im = OffsetImage(arr[0,:,:], zoom=5)
xybox=(50., 50.)
ab = AnnotationBbox(im, (0,0), xybox=xybox, xycoords='data',
boxcoords="offset points", pad=0.3, arrowprops=dict(arrowstyle="->"))
# add it to the axes and make it invisible
ax.add_artist(ab)
ab.set_visible(False)
def hover(event):
# if the mouse is over the scatter points
if line.contains(event)[0]:
# find out the index within the array from the event
ind, = line.contains(event)[1]["ind"]
# get the figure size
w,h = fig.get_size_inches()*fig.dpi
ws = (event.x > w/2.)*-1 + (event.x <= w/2.)
hs = (event.y > h/2.)*-1 + (event.y <= h/2.)
# if event occurs in the top or right quadrant of the figure,
# change the annotation box position relative to mouse.
ab.xybox = (xybox[0]*ws, xybox[1]*hs)
# make annotation box visible
ab.set_visible(True)
# place it at the position of the hovered scatter point
ab.xy =(x[ind], y[ind])
# set the image corresponding to that point
im.set_data(arr[ind,:,:])
else:
#if the mouse is not over a scatter point
ab.set_visible(False)
fig.canvas.draw_idle()
# add callback for mouse moves
fig.canvas.mpl_connect('motion_notify_event', hover)
plt.show()
Ответ 2
Если вы хотите, чтобы ваши изображения отображались в RGB, вам нужно немного изменить код. Для этого примера изображения должны быть на вашем диске. Вместо использования 3darray для изображений, где первое измерение представляет только индекс, вам нужно прочитать изображение с помощью plt.imread и затем установить_данные в соответствующую позицию в вашем массиве, содержащем имена изображений.
import matplotlib.pyplot as plt
from matplotlib.offsetbox import OffsetImage, AnnotationBbox
import numpy as np; np.random.seed(42)
import os
os.chdir('Path/to/your/images')
# Generate data x, y for scatter and an array of images.
x = np.arange(3)
y = np.random.rand(len(x))
jpg_name_np = np.array(['904646.jpg', '903825.jpg', '905722.jpg']).astype('<U12') # names of your images files
cmap = plt.cm.RdYlGn
# create figure and plot scatter
fig = plt.figure()
ax = fig.add_subplot(111)
#line, = ax.plot(x,y, ls="", marker="o")
line = plt.scatter(x,y,c=heat, s=10, cmap=cmap)
image_path = np.asarray(jpg_name_np)
# create the annotations box
image = plt.imread(image_path[0])
im = OffsetImage(image, zoom=0.1)
xybox=(50., 50.)
ab = AnnotationBbox(im, (0,0), xybox=xybox, xycoords='data',
boxcoords="offset points", pad=0.3, arrowprops=dict(arrowstyle="->"))
# add it to the axes and make it invisible
ax.add_artist(ab)
ab.set_visible(False)
def hover(event):
# if the mouse is over the scatter points
if line.contains(event)[0]:
# find out the index within the array from the event
ind, = line.contains(event)[1]["ind"]
# get the figure size
w,h = fig.get_size_inches()*fig.dpi
ws = (event.x > w/2.)*-1 + (event.x <= w/2.)
hs = (event.y > h/2.)*-1 + (event.y <= h/2.)
# if event occurs in the top or right quadrant of the figure,
# change the annotation box position relative to mouse.
ab.xybox = (xybox[0]*ws, xybox[1]*hs)
# make annotation box visible
ab.set_visible(True)
# place it at the position of the hovered scatter point
ab.xy =(x[ind], y[ind])
# set the image corresponding to that point
im.set_data(plt.imread(image_path[ind]))
else:
#if the mouse is not over a scatter point
ab.set_visible(False)
fig.canvas.draw_idle()
# add callback for mouse moves
fig.canvas.mpl_connect('motion_notify_event', hover)
fig = plt.gcf()
fig.set_size_inches(10.5, 9.5)
plt.show()