在Matplotlib中获取注释标签的坐标(以图形坐标为准)

5
我想知道Matplotlib图中文本注释的边界矩形坐标,以图形分数坐标表示。然而,当我尝试访问与注释相关联的补丁的“范围”时,无论文本标签的大小如何,我都会得到Bbox(x0 = -0.33,y0 = -0.33,x1 = 1.33,y1 = 1.33)。这些坐标似乎与IdentityTransform相关联,但不会转换为任何有意义的图形分数坐标。如何获取标签的坐标(理想情况下是左下角和右上角)以图形分数单位表示?
示例:
import numpy as np
import matplotlib.pyplot as plt

def f(x):
    return 10 * np.sin(3*x)**4

x = np.linspace(0, 2*np.pi, 100)
y = f(x)

fig, ax = plt.subplots()
ax.plot(x,y)

xpt = 1.75
ypt = f(xpt)
xy = ax.transData.transform([xpt, ypt])
xy = fig.transFigure.inverted().transform(xy)

xytext = xy + [0.1, -0.1]
rdx, rdy = 0, 1
ann = ax.annotate('A point', xy=xy, xycoords='figure fraction',
             xytext=xytext, textcoords='figure fraction',
             arrowprops=dict(arrowstyle='->', connectionstyle="arc3",
                             relpos=(rdx, rdy)),
             bbox=dict(fc='gray', edgecolor='k', alpha=0.5),
             ha='left', va='top'
            )

enter image description here

patch = ann.get_bbox_patch()
print(patch.get_extents())

给出:

[[-0.33 -0.33]
 [ 1.33  1.33]]

c = patch.get_transform().transform(patch.get_extents())
print(c)

提供:

[[-211.2 -158.4]
 [ 851.2  638.4]]

我猜这些是显示坐标,但它们与我想要属性的标签的位置和大小不对应。

1个回答

14

在绘制图形之前,text对象的边界框仅包含相对于文本内部的框的坐标。

因此有必要先绘制图形,然后再访问边界框。

fig.canvas.draw() 
patch = ann.get_bbox_patch()
box  = patch.get_extents()
print box
#prints: Bbox(x0=263.6, y0=191.612085684, x1=320.15, y1=213.412085684)

由于这些坐标是以显示单位表示的盒子坐标,因此需要将它们转换为图形单位

tcbox = fig.transFigure.inverted().transform(box)
print tcbox
#prints [[ 0.411875    0.39919185]
#        [ 0.50023438  0.44460851]]

# The format is 
#        [[ left    bottom]
#         [ right   top   ]]

此函数返回包围文本的矩形的图形单位边界框(范围从0到1)。

如果需要坐标轴坐标,则为:

ax.transAxes.inverted().transform(box)

或者如果需要数据坐标,

ax.transData.inverted().transform(box)


如果想要文本本身的边界框,则可以使用matplotlib.text.Textget_window_extent()方法,并将注释对象作为参数提供。使用此方法

box = matplotlib.text.Text.get_window_extent(ann)
print box
# prints Bbox(x0=268.0, y0=196.012085684, x1=315.75, y1=209.012085684)

您可以按照上述步骤获取图中盒子的尺寸。


谢谢 - 我有一个问题:只有在 plt.show() 之后才能重现正确的 bbox 坐标:调用 fig.canvas.draw() 是不够的... 这是后端问题吗?我使用的是 OS X。 - xnx
由于我没有任何与 Mac 相关的经验,所以我只能说这种方法在 Windows 下的 matplotlib 1.5 中使用后端 aggTkAggQt4Agg 是有效的。 - ImportanceOfBeingErnest
是的 - 这是Mac OS X后端中的一个错误。使用“agg”可以正常工作。感谢您的帮助。 - xnx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接