将图像的Y轴反转而不翻转图像

11

我正在尝试使用 matplotlib 进行图像处理。然而,y轴从下往上递减。我希望它从下往上递增,而不翻转图像

我有以下代码

import matplotlib.pyplot as plt
import numpy as np
img_path = '/path/to/image.tif'
img = plt.imread(img_path)
plt.imshow(img, cmap = 'gray')

它生成了以下的图像:enter image description here

这些图片可以在这里获取

我尝试了plt.gca().invert_yaxis()但没有成功

我该怎么办?


可能没有比matplotlib关于原点和范围的教程更好的解释了。 - ImportanceOfBeingErnest
感谢@ImportanceOfBeingErnest的评论。那确实是一个很好的参考。虽然我还没有找到直接回答这个问题的答案,但我正在努力寻找我的答案。 - ecjb
1个回答

15
imshow 的默认行为是将坐标系的原点放置在左上角。这与绘制科学数据(如两个实体xy相对)的方式不同,其中原点即对应于坐标(0,0)的点位于左下角,正 x 轴向右延伸,正 y 轴向上延伸。
后者只是科学惯例,虽然已有数百年历史。可以说(尽管几乎不可能有历史证据支持),x轴传统上被左对齐,因为许多语言的书写方式都是这样,而y轴朝向顶部是因为人们直觉地认为这是一个“增加” —— 就像地形的高度一样。
另一方面,对于图像,现有的惯例源于像素数据的存储方式以及在画布上排列连续像素的方法:在第一行从左到右(按照上述逻辑),然后再次从左边开始排列下一行,以此类推,对所有其他行进行排列,从上到下进行。就像排列在页面上的文字——使用从左到右且更普遍的是从上到下编写的语言一样。
正是出于这个原因,图像中的y轴采用了它现在的方向。要使y值从下往上增加,可以调用选项origin='lower',以便将输入数据解释为科学惯例。但是,你也需要将图像的行翻转倒过来,以便在屏幕上显示时图像呈现其预期的方向。这是因为当图像加载到内存中时曾经是第一行的东西现在对应于最后一个y坐标,即顶部的那个坐标。
总之,只需按以下代码中的方式调用imshow
plt.imshow(np.flipud(img), cmap='gray', origin='lower')
为了进一步说明,这里提供一个自包含的示例来展示这种行为:
from imageio import imread
image = imread('https://upload.wikimedia.org/wikipedia/commons'
               '/thumb/6/6a/Mona_Lisa.jpg/158px-Mona_Lisa.jpg')

from matplotlib import pyplot
figure = pyplot.figure(tight_layout=True)
(axes1, axes2, axes3) = figure.subplots(nrows=1, ncols=3)

axes1.set_title("origin='upper'")
axes1.imshow(image)

axes2.set_title("origin='lower'")
axes2.imshow(image, origin='lower')

axes3.set_title("'lower' + flipped")
axes3.imshow(image[::-1], origin='lower')

pyplot.show()

示例需要安装ImageIO才能获取示例图像。 它的输出是:

demo script的输出

(在示例代码中,我使用了image[::-1]来翻转图像,而不是前面提到的等效语法np.flipud(image)。所有这样做的是避免显式地导入NumPy(作为np),即额外的一行代码。 隐式地,NumPy仍然在工作。)

类似问题:


1
因为默认情况下原点已经是“上方”,所以我们可以保持不变。需要更改的是范围; 在这种情况下,plt.imshow(img, extent=[-.5, img.shape[1]-0.5, -0.5, img.shape[0]-0.5])。这是显式范围部分的第一行。 - ImportanceOfBeingErnest

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接