matplotlib:获取文本边界框,独立于后端 [英] matplotlib: get text bounding box, independent of backend
问题描述
我想获得matplotlib图形中某些文本的边界框(尺寸).帖子此处使我意识到,我可以使用方法text.get_window_extent(renderer)
来获取边界框,但我必须提供正确的渲染器.某些后端没有方法figure.canvas.get_renderer()
,因此我尝试了matplotlib.backend_bases.RendererBase()
来获取渲染器,但未产生令人满意的结果.这是一个简单的例子
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
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()
这将产生以下情节:
显然,红色方框太小了.我认为Paul的答案在此处发现了相同的问题.黑匣子看起来不错,但我不能使用MacOSX后端,也不能使用任何没有方法figure.canvas.get_renderer()
的其他软件.
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()
.
如果有问题,我使用的是Mac OS X 10.8.5,Matplotlib 1.3.0和Python 2.7.5
In case it matters, I am on Mac OS X 10.8.5, Matplotlib 1.3.0, and Python 2.7.5
推荐答案
这是我的解决方案/黑客. @tcaswell建议我看一下matplotlib如何处理带有紧密边界框的保存图形.我在Gith上找到代码. ,它将图形保存到临时文件对象中只是为了从缓存中获取渲染器.我将这个技巧变成了一个小函数,如果后端中存在内置函数get_renderer()
,则使用内置方法get_renderer()
,否则使用save方法.
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.
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)
以下是在我的原始示例中使用find_renderer()
并对代码进行了稍微修改的版本的结果.使用具有get_renderer()
方法的TkAgg后端,我得到:
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:
使用没有get_renderer()
方法的MacOSX后端,我得到:
With the MacOSX backend, which does not have the get_renderer()
method, I get:
显然,使用MacOSX后端的边界框并不完美,但比我最初提出的问题中的红色框要好得多.
Obviously, the bounding box using MacOSX backend is not perfect, but it is much better than the red box in my original question.
这篇关于matplotlib:获取文本边界框,独立于后端的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!