Matplotlib如何实现不同缩放比例坐标轴的共享联动缩放
实现不同尺度的Matplotlib坐标轴同步缩放
不需要修改底层transform,靠坐标轴的事件回调就能实现,逻辑很简单。
核心原理
你的场景里高低分辨率图像尺寸比固定为4:1,轴坐标映射是固定线性关系:高分辨率轴坐标乘0.25就是低分辨率轴的对应坐标。
Matplotlib自带的sharex/sharey只支持1:1坐标映射,所以只要监听高分辨率轴的视图范围变化(缩放、平移都会触发这个事件),按比例算出低分辨率轴的对应范围更新上去就行。
注意事项
- 两个同分辨率的高分辨率轴保持原生共享即可,不用改逻辑
- 回调里要加个简单的锁,防止更新低分辨率轴的时候反向触发事件,造成循环调用死锁
完整可运行代码
from PIL import Image import numpy as np import matplotlib.pyplot as plt Hh, Wh = 128, 128 Hl, Wl = 32, 32 # 高低分辨率轴的坐标缩放比例 scale_x = Wl / Wh scale_y = Hl / Hh gridh, gridw = np.mgrid[:Hh, :Wh] xh = np.sin(gridh) + np.cos(gridw) xl = np.array(Image.fromarray(xh).resize(size=(Hl, Wl))) fig, (axh1, axl, axh2) = plt.subplots(ncols=3) # 同尺度高分辨率轴使用原生共享 axh1.sharex(axh2) axh1.sharey(axh2) # 绘图时指定extent让像素坐标完全对齐整数边界,匹配你要的映射规则 axh1.imshow(xh, extent=(0, Wh, Hh, 0)) axh2.imshow(xh, extent=(0, Wh, Hh, 0)) axl.imshow(xl, extent=(0, Wl, Hl, 0)) sync_lock = False def sync_low_res(ax): global sync_lock if sync_lock: return sync_lock = True # 读取高分辨率轴当前视图范围 x0, x1 = ax.get_xlim() y0, y1 = ax.get_ylim() # 按比例更新低分辨率轴 axl.set_xlim(x0 * scale_x, x1 * scale_x) axl.set_ylim(y0 * scale_y, y1 * scale_y) fig.canvas.draw_idle() sync_lock = False # 给两个高分辨率轴绑定视图变更事件 for ax in [axh1, axh2]: ax.callbacks.connect('xlim_changed', sync_low_res) ax.callbacks.connect('ylim_changed', sync_low_res) plt.show()
效果
运行后缩放、平移任意一个高分辨率子图,低分辨率子图都会自动按比例同步到对应区域:比如你在高分辨率图框选(0,0,16,16)的区域,低分辨率图会自动跳转到(0,0,4,4)的对应位置,交互手感和原生共享坐标轴没有区别。后续如果要改尺度比例,只需要调整scale_x、scale_y的计算值即可。
内容的提问来源于stack exchange,提问作者paime
相关产品推荐
相关产品推荐

