Matplotlib文本边界框尺寸

16 投票
2 回答
16341 浏览
提问于 2025-04-18 12:09

我想做的事情:

我想获取在matplotlib中,文本实例的位置和尺寸,单位是世界坐标(不是屏幕像素),目的是为了计算和防止文本重叠。

我在Mac OSX 10.9.3上开发,使用的是Python 2.7.5和matplotlib 1.3.1。

我尝试过的:

假设 t 是一个文本实例。

  1. t.get_window_extent(renderer):

    这个方法获取的是像素为单位的边界框尺寸,而我需要的是世界坐标(在我的情况下是标准化到-1.0到1.0之间)。

  2. t._get_bbox_patch():

    t = ax.text(x, y, text_string, prop_dict, bbox=dict(facecolor='red', alpha=0.5, boxstyle='square'))
    print t._get_bbox_patch()
    

    当我执行上面的代码时,输出是 FancyBboxPatchFancyBboxPatch(0,0;1x1)。在我生成的图像中,文本实例正确显示,并且有一个红色的边界框,所以这个输出让我觉得FancyBbox已经被实例化,但在渲染时才会填充真实的尺寸。

那么,我该如何在我传给 ax.text(...)xy 参数所用的相同坐标系单位中,获取文本实例的边界框的位置和尺寸呢?

2 个回答

5

虽然有点晚了,但这里有另一个例子,展示了如何在数据坐标或单位中获取文本对象的边界框。这个例子还会在文本周围绘制出获取的边界框,以便更直观地展示。

import matplotlib.pyplot as plt

# some example plot
plt.plot([1,2,3], [2,3,4])

t = plt.text(1.1, 3.1, "my text", fontsize=18)

# to get the text bounding box 
# we need to draw the plot
plt.gcf().canvas.draw()


# get bounding box of the text 
# in the units of the data
bbox = t.get_window_extent()\
    .inverse_transformed(plt.gca().transData)


print(bbox)
# prints: Bbox(x0=1.1, y0=3.0702380952380954, x1=1.5296875, y1=3.2130952380952382)


# plot the bounding box around the text
plt.plot([bbox.x0, bbox.x0, bbox.x1, bbox.x1, bbox.x0],
         [bbox.y0, bbox.y1, bbox.y1, bbox.y0, bbox.y0])

plt.show()

在这里输入图片描述

19

这可能会对你有点帮助。

import matplotlib.pyplot as plt

f = plt.figure()
ax = f.add_subplot(111)
ax.plot([0,10], [4,0])
t = ax.text(3.2, 2.1, "testing...")

# get the inverse of the transformation from data coordinates to pixels
transf = ax.transData.inverted()
bb = t.get_window_extent(renderer = f.canvas.renderer)
bb_datacoords = bb.transformed(transf)

# Bbox('array([[ 3.2       ,  2.1       ],\n       [ 4.21607125,  2.23034396]])')

这样做应该能满足你的需求。如果你想要的坐标是图形坐标(0到1之间),那么可以使用ax.transAxes的反转。

不过,这个解决方案有一个小问题。以下是matplotlib文档中的一段摘录:

任何文本实例都可以报告它在窗口坐标中的范围(负的x坐标表示在窗口外),但这里有个问题。

用于计算文本大小的RendererBase实例,直到图形被绘制出来(draw())之前是无法知道的。等窗口绘制完成后,文本实例才知道它的渲染器,这时你可以调用get_window_extent()。

所以,在图形真正绘制之前,似乎没有办法知道文本的大小。

顺便提一下,你可能注意到Bbox实例有一个overlaps方法,可以用来判断一个Bbox是否与另一个重叠(bb1.overlaps(bb2))。这在某些情况下可能有用,但它并不能回答“重叠多少”的问题。

如果你有旋转的文本,你会很难判断它们是否重叠,不过你可能已经知道这一点。

撰写回答