You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Matplotlib调用get_window_extent配transform参数获取Bbox坐标错误问题

问题成因
  • 坐标转换时机错误:plt.show()执行前调用fig.canvas.get_renderer()获取的是未完成全局布局的渲染结果,此时文本、坐标轴的位置还没有完成最终适配,拿到的extent坐标是临时值,窗口缩放后布局重绘,之前计算的坐标就会失效
  • 坐标系匹配错误:你计算得到的坐标是相对于ax_img的归一化坐标轴坐标,但如果将矩形添加到主坐标轴ax,又使用ax_img.transAxes作为变换,两个坐标轴的位置、尺寸参数不匹配,会导致坐标进一步偏移
  • 自适应布局干扰:matplotlib默认的紧凑布局、坐标轴自适应调整会在渲染过程中修改axes的实际位置,和你初始化add_axes时指定的参数产生偏差
修复方案

两种可选方案,可根据使用场景选择:

方案1:固定窗口尺寸+强制预渲染

适合不需要缩放窗口、直接导出图片的场景,提前固定画布DPI和尺寸,强制完成全量渲染后再计算坐标:

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

# 提前固定画布尺寸和DPI,避免后续布局偏移
fig, ax = plt.subplots(figsize=(8,6), dpi=100)
# 禁用紧凑布局,避免axes位置被自动调整
fig.set_layout_engine(None)

# 替换为你的本地图片路径
flash_pic = plt.imread("./statics/images/flash_decrease.png")

ax_img = fig.add_axes([0.3,0.3,0.1,0.1], aspect='equal')
ax_img.imshow(flash_pic)
# 隐藏ax_img的坐标轴边框、刻度,避免干扰显示
ax_img.axis('off')

str_up = "This is"
str_right = "a random string"

text_up = ax_img.text(0, 1.1, str_up, fontsize=14, transform=ax_img.transAxes)
text_right = ax_img.text(1.1, 0, str_right, fontsize=14, transform=ax_img.transAxes)

# 强制canvas完成全量渲染,拿到最终布局参数
fig.canvas.draw()
r = fig.canvas.get_renderer()

# 坐标转换时直接转为figure的归一化坐标,矩形直接添加到fig上避免坐标轴变换干扰
x0 = text_up.get_window_extent(renderer=r).transformed(fig.transFigure.inverted()).x0
x1 = text_right.get_window_extent(renderer=r).transformed(fig.transFigure.inverted()).x1
y0 = text_right.get_window_extent(renderer=r).transformed(fig.transFigure.inverted()).y0
y1 = text_up.get_window_extent(renderer=r).transformed(fig.transFigure.inverted()).y1

width = x1 - x0
height = y1 - y0
# 矩形添加到fig的patch层,使用fig的坐标变换,完全不受坐标轴影响
rect = Rectangle((x0, y0), width, height, transform=fig.transFigure, color='red', alpha=0.3, zorder=0)
fig.patches.append(rect)

plt.show()

方案2:添加重绘回调,支持窗口自适应缩放

适合需要交互式操作、窗口可能缩放的场景,把矩形坐标计算逻辑放到重绘回调中,每次窗口调整时自动重新计算坐标:

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

fig, ax = plt.subplots()
flash_pic = plt.imread("./statics/images/flash_decrease.png")

ax_img = fig.add_axes([0.3,0.3,0.1,0.1], aspect='equal')
ax_img.imshow(flash_pic)
ax_img.axis('off')

str_up = "This is"
str_right = "a random string"

text_up = ax_img.text(0, 1.1, str_up, fontsize=14, transform=ax_img.transAxes)
text_right = ax_img.text(1.1, 0, str_right, fontsize=14, transform=ax_img.transAxes)

# 初始化矩形,后续回调里更新坐标
rect = Rectangle((0,0), 0, 0, color='red', alpha=0.3, zorder=0)
fig.patches.append(rect)

def update_rect(event):
    r = fig.canvas.get_renderer()
    x0 = text_up.get_window_extent(renderer=r).transformed(fig.transFigure.inverted()).x0
    x1 = text_right.get_window_extent(renderer=r).transformed(fig.transFigure.inverted()).x1
    y0 = text_right.get_window_extent(renderer=r).transformed(fig.transFigure.inverted()).y0
    y1 = text_up.get_window_extent(renderer=r).transformed(fig.transFigure.inverted()).y1
    rect.set_bounds(x0, y0, x1-x0, y1-y0)

# 绑定draw事件,每次重绘自动更新矩形坐标
fig.canvas.mpl_connect('draw_event', update_rect)
# 首次触发更新
fig.canvas.draw()

plt.show()

内容的提问来源于stack exchange,提问作者calvin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 06:36:03