gpt4 book ai didi

python - Matplotlib:以图像作为注释的 3D 散点图

转载 作者:行者123 更新时间:2023-11-28 19:02:31 26 4
gpt4 key购买 nike

我正在尝试为包含 0 到 9 数字的数据集中的图像的 tSNE 嵌入生成 3D 散点图。我还想用数据集中的图像注释这些点。

在浏览了与该问题相关的现有资源后,我发现使用 matplotlib.offsetbox 可以很容易地绘制二维散点图,如前所述 here .

还有一个question关于与 3D 注释相关但仅包含文本的 SO。有谁知道如何用图像而不是文本进行注释?

谢谢!

最佳答案

matplotlib.offsetbox 在 3D 中不起作用。作为一种解决方法,可以使用覆盖 3D 图的 2D 轴,并将图像注释放置在与 3D 轴位置相对应的 2D 轴位置。

要计算这些位置的坐标,可以引用How to transform 3d data units to display units with matplotlib? .然后可以使用这些显示坐标的逆变换来获得叠加轴中的新坐标。

from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d import proj3d
import matplotlib.pyplot as plt
from matplotlib import offsetbox
import numpy as np

xs = [1,1.5,2,2]
ys = [1,2,3,1]
zs = [0,1,2,0]

c = ["b","r","g","gold"]

fig = plt.figure()
ax = fig.add_subplot(111, projection=Axes3D.name)

ax.scatter(xs, ys, zs, c=c, marker="o")

# Create a dummy axes to place annotations to
ax2 = fig.add_subplot(111,frame_on=False)
ax2.axis("off")
ax2.axis([0,1,0,1])


def proj(X, ax1, ax2):
""" From a 3D point in axes ax1,
calculate position in 2D in ax2 """
x,y,z = X
x2, y2, _ = proj3d.proj_transform(x,y,z, ax1.get_proj())
return ax2.transData.inverted().transform(ax1.transData.transform((x2, y2)))

def image(ax,arr,xy):
""" Place an image (arr) as annotation at position xy """
im = offsetbox.OffsetImage(arr, zoom=2)
im.image.axes = ax
ab = offsetbox.AnnotationBbox(im, xy, xybox=(-30., 30.),
xycoords='data', boxcoords="offset points",
pad=0.3, arrowprops=dict(arrowstyle="->"))
ax.add_artist(ab)


for s in zip(xs,ys,zs):
x,y = proj(s, ax, ax2)
image(ax2,np.random.rand(10,10),[x,y])

ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.show()

enter image description here

上面的解决方案是静态的。这意味着如果绘图被旋转或缩放,注释将不再指向正确的位置。为了同步注释,可以连接到绘图事件并检查限制或视角是否已更改并相应地更新注释坐标。 (2019 年编辑:较新版本还需要将事件从顶部 2D 轴传递到底部 3D 轴;代码已更新)

from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d import proj3d
import matplotlib.pyplot as plt
from matplotlib import offsetbox
import numpy as np

xs = [1,1.5,2,2]
ys = [1,2,3,1]
zs = [0,1,2,0]
c = ["b","r","g","gold"]


fig = plt.figure()
ax = fig.add_subplot(111, projection=Axes3D.name)

ax.scatter(xs, ys, zs, c=c, marker="o")

# Create a dummy axes to place annotations to
ax2 = fig.add_subplot(111,frame_on=False)
ax2.axis("off")
ax2.axis([0,1,0,1])

class ImageAnnotations3D():
def __init__(self, xyz, imgs, ax3d,ax2d):
self.xyz = xyz
self.imgs = imgs
self.ax3d = ax3d
self.ax2d = ax2d
self.annot = []
for s,im in zip(self.xyz, self.imgs):
x,y = self.proj(s)
self.annot.append(self.image(im,[x,y]))
self.lim = self.ax3d.get_w_lims()
self.rot = self.ax3d.get_proj()
self.cid = self.ax3d.figure.canvas.mpl_connect("draw_event",self.update)

self.funcmap = {"button_press_event" : self.ax3d._button_press,
"motion_notify_event" : self.ax3d._on_move,
"button_release_event" : self.ax3d._button_release}

self.cfs = [self.ax3d.figure.canvas.mpl_connect(kind, self.cb) \
for kind in self.funcmap.keys()]

def cb(self, event):
event.inaxes = self.ax3d
self.funcmap[event.name](event)

def proj(self, X):
""" From a 3D point in axes ax1,
calculate position in 2D in ax2 """
x,y,z = X
x2, y2, _ = proj3d.proj_transform(x,y,z, self.ax3d.get_proj())
tr = self.ax3d.transData.transform((x2, y2))
return self.ax2d.transData.inverted().transform(tr)

def image(self,arr,xy):
""" Place an image (arr) as annotation at position xy """
im = offsetbox.OffsetImage(arr, zoom=2)
im.image.axes = ax
ab = offsetbox.AnnotationBbox(im, xy, xybox=(-30., 30.),
xycoords='data', boxcoords="offset points",
pad=0.3, arrowprops=dict(arrowstyle="->"))
self.ax2d.add_artist(ab)
return ab

def update(self,event):
if np.any(self.ax3d.get_w_lims() != self.lim) or \
np.any(self.ax3d.get_proj() != self.rot):
self.lim = self.ax3d.get_w_lims()
self.rot = self.ax3d.get_proj()
for s,ab in zip(self.xyz, self.annot):
ab.xy = self.proj(s)


imgs = [np.random.rand(10,10) for i in range(len(xs))]
ia = ImageAnnotations3D(np.c_[xs,ys,zs],imgs,ax, ax2 )

ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.show()

enter image description here

关于python - Matplotlib:以图像作为注释的 3D 散点图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50981514/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com