【问题标题】:Python show image upon hovering over a pointPython在悬停在一个点上时显示图像
【发布时间】:2017-08-09 14:15:48
【问题描述】:

我有一个二维散点图,对应于图像。我想知道当您将鼠标悬停在每个点上时是否有一种简单的方法来显示相应的图像(作为弹出窗口或工具提示)?我尝试了很多,但发现您需要手动编辑 javascript 才能使悬停事件起作用。仅使用 matplotlib 或其他一些常见包是否有简单的解决方案?

【问题讨论】:

标签: python matplotlib


【解决方案1】:

在此处查找有关如何在悬停事件上显示图像的完整解决方案。它使用'motion_notify_event' 来检测鼠标何时位于散点上方(悬停)。如果是这种情况,它会在悬停的散点旁边显示一个带有相应图像的image annotation

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()

【讨论】:

  • 在 jupyter notebook 中,当然最好启用 %matplotlib notebook 后端。否则无法进行交互。
  • 是否可以用不同的数据组做同样的事情。例如,假设有 3 个类别,您需要执行一个 for 循环,即这里 matplotlib.org/3.1.0/gallery/lines_bars_and_markers/…。每个 x,y 数据点是否仍能显示有代表性的图像?谢谢
  • 好吧,抱歉,我通过使用 alpha 0 使这些数据点透明并覆盖彩色图来解决这个问题。如果有更正确的方法请告诉我
  • 这可以作为独立脚本正常工作,但不适用于 Colab(%matplotlib inline%matplotlib notebook):没有图像出现
【解决方案2】:

如果您希望图像以 RGB 显示,则必须稍微调整代码。对于此示例,图像需要在您的磁盘中。而不是对第一个维度仅表示索引的图像使用 3darray,您需要使用 plt.imread 读取图像,然后将 set_data 设置到包含图像名称的数组中的相应位置。

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()

Plot when hovering over scatterpoint

【讨论】:

  • 这对我来说不适用于 Colab。 (即使在更改路径并将其指向图像之后)
猜你喜欢
  • 2015-06-08
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 2020-07-22
  • 2015-08-07
  • 2017-02-09
  • 1970-01-01
相关资源
最近更新 更多