Matplotlib基于图像坐标绘制矩形位置异常问题咨询
你遇到的问题核心是Matplotlib的坐标系和图像像素坐标系的y轴方向差异,再加上Rectangle补丁的坐标定义容易和视觉直觉混淆,咱们一步步理清楚:
首先,当你用ax.imshow(im, cmap="gray")时,默认的origin='upper'参数会把图像的(0,0)像素(也就是图像的顶部左侧)放在Axes坐标系的(0,0)位置,而且Axes的y轴是向下递增的——从顶部的0一直到图像底部的高度值。
而Rectangle补丁文档里说的“左下角”,是基于Axes坐标系的定义:也就是Axes中x最小、y最小的点。在y轴向下递增的情况下,这个“左下角”在视觉上其实是图像的左上角,这就是为什么你用(0, 0)作为起始点时,矩形正好显示在你想要的位置,但和你理解的“视觉左下角”不符。
针对你的需求(绘制图像坐标中(顶部0, 左侧0, 宽度240, 高度210)的矩形),有两种简单的解决方案:
方案1:适配默认的图像显示方向(推荐)
既然默认的Axes y轴是向下递增的,我们直接利用这个特性:用图像的左上角(Axes坐标系的(0,0))作为Rectangle的“左下角”,宽高直接设为240和210,这样矩形会自然向下延伸,正好覆盖你需要的区域:
import matplotlib.pyplot as plt import matplotlib.patches as mpatches from random import randint # 生成随机十六进制颜色的辅助函数 def randHex(): return f'#{randint(0, 0xFFFFFF):06x}' # 假设im是你的图像数组,这里用示例读取替换 im = plt.imread('your_image.png') fig, ax = plt.subplots() ax.imshow(im, cmap="gray") # 绘制目标矩形:对应图像顶部左侧开始,宽240高210 rect = mpatches.Rectangle((0, 0), 240, 210, fill=False, linewidth=2, edgecolor=randHex()) ax.add_patch(rect) plt.show()
方案2:统一坐标系方向(修改图像显示原点)
如果你想让Axes的坐标系和常规数学坐标系一致(y轴向上递增),可以把imshow的origin参数改成'lower'——这时候图像的(0,0)像素会放在Axes的左下角,但图像会上下翻转显示。此时需要根据图像高度计算矩形的左下角坐标:
import matplotlib.pyplot as plt import matplotlib.patches as mpatches from random import randint def randHex(): return f'#{randint(0, 0xFFFFFF):06x}' im = plt.imread('your_image.png') img_height = im.shape[0] # 获取图像的像素高度 fig, ax = plt.subplots() ax.imshow(im, cmap="gray", origin='lower') # 修改原点为左下角 # 图像顶部对应Axes的y=img_height,所以矩形左下角的y坐标是 img_height - 210 rect = mpatches.Rectangle((0, img_height - 210), 240, 210, fill=False, linewidth=2, edgecolor=randHex()) ax.add_patch(rect) plt.show()
简单来说,你之前的困惑源于“坐标系定义”和“视觉位置”的错位,默认的origin='upper'让Axes的y轴方向和图像像素的y轴方向一致,但和常规坐标系相反,这才导致了文档描述和实际显示的反差。
内容的提问来源于stack exchange,提问作者Carpetfizz

