matplotlib:获取文本包围盒,独立于后端。

时间:2022-10-17 22:22:34

I would like to get the bounding box (dimensions) around some text in a matplotlib figure. The post here, helped me realize that I can use the method text.get_window_extent(renderer) to get the bounding box, but I have to supply the correct renderer. Some backends do not have the method figure.canvas.get_renderer(), so I tried matplotlib.backend_bases.RendererBase() to get the renderer and it did not produce satisfactory results. Here is a simple example

我想在matplotlib图中获得一些文本的包围框(维度)。这里的文章帮助我认识到,我可以使用方法text. get_window_区段(renderer)来获得边框框,但是我必须提供正确的渲染器。有些后端没有方法figure.canvas.get_renderer(),所以我尝试了matplotlib.backend_base . rendererbase()来获取渲染器,但没有产生满意的结果。这里有一个简单的例子

import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle

fig = plt.figure()
ax = plt.subplot()
txt = fig.text(0.15,0.5,'afdjsklhvvhwd', fontsize = 36)
renderer1 = fig.canvas.get_renderer()
renderer2 = mpl.backend_bases.RendererBase()
bbox1 = txt.get_window_extent(renderer1)
bbox2 = txt.get_window_extent(renderer2)
rect1 = Rectangle([bbox1.x0, bbox1.y0], bbox1.width, bbox1.height, \
    color = [0,0,0], fill = False)
rect2 = Rectangle([bbox2.x0, bbox2.y0], bbox2.width, bbox2.height, \
    color = [1,0,0], fill = False)
fig.patches.append(rect1)
fig.patches.append(rect2)
plt.draw()

This produces the following plot:

这就产生了以下情节:

matplotlib:获取文本包围盒,独立于后端。

Clearly the red box is too small. I think a Paul's answer here found the same issue. The black box looks great, but I cannot use the MacOSX backend, or any others that do not have the method figure.canvas.get_renderer().

显然红色的盒子太小了。我认为保罗的回答也有同样的问题。黑框看起来很不错,但是我不能使用MacOSX后端,也不能使用其他没有method figure.canvas.get_renderer()的。

In case it matters, I am on Mac OS X 10.8.5, Matplotlib 1.3.0, and Python 2.7.5

如果重要的话,我使用的是Mac OS X 10.8.5、Matplotlib 1.3.0和Python 2.7.5

1 个解决方案

#1


7  

Here is my solution/hack. @tcaswell suggested I look at how matplotlib handles saving figures with tight bounding boxes. I found the code for backend_bases.py on Github, where it saves the figure to a temporary file object simply in order to get the renderer from the cache. I turned this trick into a little function that uses the built-in method get_renderer() if it exists in the backend, but uses the save method otherwise.

这是我的解决方案/黑客。@tcaswell建议我看看matplotlib是如何使用紧密的边框来处理保存数据的。我找到了backend_bases的代码。在Github上,它将图形保存到一个临时文件对象中,只是为了从缓存中获取渲染器。我将这个技巧转换为一个小函数,如果在后端中存在,它将使用内置方法get_renderer(),但不使用save方法。

def find_renderer(fig):

    if hasattr(fig.canvas, "get_renderer"):
        #Some backends, such as TkAgg, have the get_renderer method, which 
        #makes this easy.
        renderer = fig.canvas.get_renderer()
    else:
        #Other backends do not have the get_renderer method, so we have a work 
        #around to find the renderer.  Print the figure to a temporary file 
        #object, and then grab the renderer that was used.
        #(I stole this trick from the matplotlib backend_bases.py 
        #print_figure() method.)
        import io
        fig.canvas.print_pdf(io.BytesIO())
        renderer = fig._cachedRenderer
    return(renderer)

Here are the results using find_renderer() with a slightly modified version of the code in my original example. With the TkAgg backend, which has the get_renderer() method, I get:

下面是使用find_renderer()的结果,并在我最初的示例中对代码进行了稍微修改。TkAgg后端有get_renderer()方法,我得到:

matplotlib:获取文本包围盒,独立于后端。

With the MacOSX backend, which does not have the get_renderer() method, I get:

MacOSX后端没有get_renderer()方法,我得到:

matplotlib:获取文本包围盒,独立于后端。

Obviously, the bounding box using MacOSX backend is not perfect, but it is much better than the red box in my original question.

显然,使用MacOSX后端进行的边界框并不完美,但它比我最初的问题中的红色框要好得多。

#1


7  

Here is my solution/hack. @tcaswell suggested I look at how matplotlib handles saving figures with tight bounding boxes. I found the code for backend_bases.py on Github, where it saves the figure to a temporary file object simply in order to get the renderer from the cache. I turned this trick into a little function that uses the built-in method get_renderer() if it exists in the backend, but uses the save method otherwise.

这是我的解决方案/黑客。@tcaswell建议我看看matplotlib是如何使用紧密的边框来处理保存数据的。我找到了backend_bases的代码。在Github上,它将图形保存到一个临时文件对象中,只是为了从缓存中获取渲染器。我将这个技巧转换为一个小函数,如果在后端中存在,它将使用内置方法get_renderer(),但不使用save方法。

def find_renderer(fig):

    if hasattr(fig.canvas, "get_renderer"):
        #Some backends, such as TkAgg, have the get_renderer method, which 
        #makes this easy.
        renderer = fig.canvas.get_renderer()
    else:
        #Other backends do not have the get_renderer method, so we have a work 
        #around to find the renderer.  Print the figure to a temporary file 
        #object, and then grab the renderer that was used.
        #(I stole this trick from the matplotlib backend_bases.py 
        #print_figure() method.)
        import io
        fig.canvas.print_pdf(io.BytesIO())
        renderer = fig._cachedRenderer
    return(renderer)

Here are the results using find_renderer() with a slightly modified version of the code in my original example. With the TkAgg backend, which has the get_renderer() method, I get:

下面是使用find_renderer()的结果,并在我最初的示例中对代码进行了稍微修改。TkAgg后端有get_renderer()方法,我得到:

matplotlib:获取文本包围盒,独立于后端。

With the MacOSX backend, which does not have the get_renderer() method, I get:

MacOSX后端没有get_renderer()方法,我得到:

matplotlib:获取文本包围盒,独立于后端。

Obviously, the bounding box using MacOSX backend is not perfect, but it is much better than the red box in my original question.

显然,使用MacOSX后端进行的边界框并不完美,但它比我最初的问题中的红色框要好得多。