注意
前往底部下載完整範例程式碼。
imshow
中的 origin 和 extent#
imshow()
允許您將影像 (2D 陣列,將根據 norm 和 cmap 進行顏色映射;或是 3D RGB(A) 陣列,將按原樣使用) 渲染到資料空間中的矩形區域。最終渲染中影像的方向由 origin 和 extent 關鍵字引數 (以及產生的 AxesImage
執行個體的屬性) 和軸的資料限制控制。
extent 關鍵字引數控制影像將填充的資料座標中的邊界框,指定為 (左, 右, 下, 上)
,以資料座標表示。origin 關鍵字引數控制影像如何填充該邊界框,並且最終渲染影像中的方向也會受到軸限制的影響。
提示
以下大部分程式碼用於將標籤和資訊文字新增到繪圖中。 origin 和 extent 的描述效果可以在繪圖中看到,無需遵循所有程式碼細節。
為了快速理解,您可能想要略過下面的程式碼細節,直接繼續討論結果。
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.gridspec import GridSpec
def index_to_coordinate(index, extent, origin):
"""Return the pixel center of an index."""
left, right, bottom, top = extent
hshift = 0.5 * np.sign(right - left)
left, right = left + hshift, right - hshift
vshift = 0.5 * np.sign(top - bottom)
bottom, top = bottom + vshift, top - vshift
if origin == 'upper':
bottom, top = top, bottom
return {
"[0, 0]": (left, bottom),
"[M', 0]": (left, top),
"[0, N']": (right, bottom),
"[M', N']": (right, top),
}[index]
def get_index_label_pos(index, extent, origin, inverted_xindex):
"""
Return the desired position and horizontal alignment of an index label.
"""
if extent is None:
extent = lookup_extent(origin)
left, right, bottom, top = extent
x, y = index_to_coordinate(index, extent, origin)
is_x0 = index[-2:] == "0]"
halign = 'left' if is_x0 ^ inverted_xindex else 'right'
hshift = 0.5 * np.sign(left - right)
x += hshift * (1 if is_x0 else -1)
return x, y, halign
def get_color(index, data, cmap):
"""Return the data color of an index."""
val = {
"[0, 0]": data[0, 0],
"[0, N']": data[0, -1],
"[M', 0]": data[-1, 0],
"[M', N']": data[-1, -1],
}[index]
return cmap(val / data.max())
def lookup_extent(origin):
"""Return extent for label positioning when not given explicitly."""
if origin == 'lower':
return (-0.5, 6.5, -0.5, 5.5)
else:
return (-0.5, 6.5, 5.5, -0.5)
def set_extent_None_text(ax):
ax.text(3, 2.5, 'equals\nextent=None', size='large',
ha='center', va='center', color='w')
def plot_imshow_with_labels(ax, data, extent, origin, xlim, ylim):
"""Actually run ``imshow()`` and add extent and index labels."""
im = ax.imshow(data, origin=origin, extent=extent)
# extent labels (left, right, bottom, top)
left, right, bottom, top = im.get_extent()
if xlim is None or top > bottom:
upper_string, lower_string = 'top', 'bottom'
else:
upper_string, lower_string = 'bottom', 'top'
if ylim is None or left < right:
port_string, starboard_string = 'left', 'right'
inverted_xindex = False
else:
port_string, starboard_string = 'right', 'left'
inverted_xindex = True
bbox_kwargs = {'fc': 'w', 'alpha': .75, 'boxstyle': "round4"}
ann_kwargs = {'xycoords': 'axes fraction',
'textcoords': 'offset points',
'bbox': bbox_kwargs}
ax.annotate(upper_string, xy=(.5, 1), xytext=(0, -1),
ha='center', va='top', **ann_kwargs)
ax.annotate(lower_string, xy=(.5, 0), xytext=(0, 1),
ha='center', va='bottom', **ann_kwargs)
ax.annotate(port_string, xy=(0, .5), xytext=(1, 0),
ha='left', va='center', rotation=90,
**ann_kwargs)
ax.annotate(starboard_string, xy=(1, .5), xytext=(-1, 0),
ha='right', va='center', rotation=-90,
**ann_kwargs)
ax.set_title(f'origin: {origin}')
# index labels
for index in ["[0, 0]", "[0, N']", "[M', 0]", "[M', N']"]:
tx, ty, halign = get_index_label_pos(index, extent, origin,
inverted_xindex)
facecolor = get_color(index, data, im.get_cmap())
ax.text(tx, ty, index, color='white', ha=halign, va='center',
bbox={'boxstyle': 'square', 'facecolor': facecolor})
if xlim:
ax.set_xlim(*xlim)
if ylim:
ax.set_ylim(*ylim)
def generate_imshow_demo_grid(extents, xlim=None, ylim=None):
N = len(extents)
fig = plt.figure(tight_layout=True)
fig.set_size_inches(6, N * (11.25) / 5)
gs = GridSpec(N, 5, figure=fig)
columns = {'label': [fig.add_subplot(gs[j, 0]) for j in range(N)],
'upper': [fig.add_subplot(gs[j, 1:3]) for j in range(N)],
'lower': [fig.add_subplot(gs[j, 3:5]) for j in range(N)]}
x, y = np.ogrid[0:6, 0:7]
data = x + y
for origin in ['upper', 'lower']:
for ax, extent in zip(columns[origin], extents):
plot_imshow_with_labels(ax, data, extent, origin, xlim, ylim)
columns['label'][0].set_title('extent=')
for ax, extent in zip(columns['label'], extents):
if extent is None:
text = 'None'
else:
left, right, bottom, top = extent
text = (f'left: {left:0.1f}\nright: {right:0.1f}\n'
f'bottom: {bottom:0.1f}\ntop: {top:0.1f}\n')
ax.text(1., .5, text, transform=ax.transAxes, ha='right', va='center')
ax.axis('off')
return columns
預設 extent#
首先,讓我們看看預設的 extent=None
generate_imshow_demo_grid(extents=[None])

一般來說,對於形狀為 (M, N) 的陣列,第一個索引沿著垂直方向執行,第二個索引沿著水平方向執行。像素中心位於整數位置,水平範圍從 0 到 N' = N - 1
,垂直範圍從 0 到 M' = M - 1
。 origin 決定資料如何填充在邊界框中。
對於 origin='lower'
[0, 0] 位於 (左, 下)
[M', 0] 位於 (左, 上)
[0, N'] 位於 (右, 下)
[M', N'] 位於 (右, 上)
origin='upper'
反轉垂直軸方向和填充
[0, 0] 位於 (左, 上)
[M', 0] 位於 (左, 下)
[0, N'] 位於 (右, 上)
[M', N'] 位於 (右, 下)
總結來說,[0, 0] 索引的位置以及 extent 都會受到 origin 的影響
origin |
[0, 0] 位置 |
extent |
---|---|---|
upper |
左上 |
|
lower |
左下 |
|
origin 的預設值由 rcParams["image.origin"]
(預設:'upper'
) 設定,預設為 'upper'
,以符合數學和電腦圖形影像索引慣例中的矩陣索引慣例。
明確的 extent#
透過設定 extent,我們定義影像區域的座標。基礎影像資料會進行插值/重新取樣,以填充該區域。
如果將軸設定為自動縮放,則軸的檢視限制會設定為符合 extent,這可確保由 (左, 下)
設定的座標位於軸的左下角!但是,這可能會反轉軸,使其不會以「自然」方向增加。

明確的 extent 和軸限制#
如果我們透過明確設定 set_xlim
/ set_ylim
來固定軸限制,我們會強制軸具有特定的大小和方向。這可以將影像的「左右」和「上下」感覺與螢幕上的方向分離。
在下面的範例中,我們選擇的限制略大於 extent (請注意軸內部的白色區域)。
當我們保持與先前範例相同的 extent 時,座標 (0, 0) 現在會明確地放置在左下角,且值會從檢視者的角度往上和往右增加。我們可以看到
座標
(左, 下)
會錨定影像,然後填滿朝向資料空間中(右, 上)
點的方塊。第一欄永遠最靠近「左」。
origin 控制第一列是否最靠近「上」或「下」。
影像可能會沿任一方向反轉。
影像的「左右」和「上下」感覺可能會與螢幕上的方向分離。

腳本的總執行時間: (0 分鐘 5.046 秒)