Matplotlib pyplot imshow切换图像时绘制到按钮而非主区域问题求助
问题根因
该问题由Matplotlib的「当前活跃坐标轴」机制触发:
- 首次调用
plt.imshow时,程序自动生成的主绘图区是默认的活跃坐标轴,因此第一张图片可以正常显示 - 后续你创建了两个按钮专属的坐标轴,最后创建的按钮坐标轴
axweird成为了新的默认活跃坐标轴 - 点击Next按钮调用
plt.imshow时,程序会自动在当前最新的活跃坐标轴(也就是按钮的坐标轴)上绘制图片,因此出现图片画到按钮内的异常。
修复方案
需要提前显式声明存储图片的主坐标轴,所有绘图操作都指定在该坐标轴上执行,避免和按钮坐标轴混淆,同时可以顺带修复OpenCV读取图片的颜色通道不匹配问题。
修复后完整代码
import matplotlib.pyplot as plt from matplotlib.widgets import Button import cv2 path_to_first_image = "training_data/2f8ebb07-8a83-4373-973a-439217bc7f0a/0.jpg" path_to_second_image = "training_data/2f8ebb07-8a83-4373-973a-439217bc7f0a/1.jpg" class Gui(object): def __init__(self): # 显式创建主绘图坐标轴,预留底部按钮空间,位置参数为[左, 下, 宽, 高],取值范围0-1 self.img_ax = plt.axes([0.1, 0.15, 0.8, 0.75]) self.im = None self.show_image(path_to_first_image) def next(self, event): self.show_image(path_to_second_image) def show_image(self, path): self.img_ax.axis('off') img = cv2.imread(path) # 修复OpenCV BGR通道和Matplotlib RGB通道不匹配的问题 img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) if self.im is None: # 首次绘图创建im对象 self.im = self.img_ax.imshow(img_rgb) else: # 后续仅更新图片数据,性能更高 self.im.set_data(img_rgb) plt.draw() def other(self, event): pass gui = Gui() # 按钮坐标轴创建放在主坐标轴之后,不影响图片绘图 axnext = plt.axes([0.15, 0.05, 0.1, 0.075]) axweird = plt.axes([0.7, 0.05, 0.15, 0.075]) bnext = Button(axnext, 'Next') bnext.on_clicked(gui.next) bother = Button(axweird, 'other') bother.on_clicked(gui.other) plt.show()
核心修改点
- 提前显式声明主绘图坐标轴作为类属性,所有图片绘制操作都指定在该坐标轴上执行,完全规避和按钮坐标轴的冲突
- 优化图片更新逻辑:首次绘图后仅更新图片像素数据,无需重复创建绘图对象,渲染效率更高
- 修复颜色通道不匹配问题:OpenCV默认读取图片为BGR格式,转换为RGB格式后再交给Matplotlib显示,避免图片颜色失真
内容的提问来源于stack exchange,提问作者Wessel Ottevanger
相关产品推荐
相关产品推荐

