はじめに
Matplotlibを使用して画像を表示する際、軸の目盛りの調整や2軸を使いたい場合があります。本記事では、imshow
関数の引数であるextent
を使用して軸の目盛りを調整する方法を紹介します。
そして、このextent
の方法を知る前まで筆者が愛用していたSecondary Axisでの実装コードも紹介します。この方法は少し複雑ですが、extent
と同様の指定方法でimshow
で2軸を表示したい場合に活用していただければ幸いです。
以下が、本記事の概要のイメージです。
本記事で使用したコードはGoogle Colabのこちらに載せています。
デフォルトの軸目盛り
まずは軸ラベルの設定をしなかった場合の結果について一応見ておきます。
軸ラベルの設定をしなかった場合のコード
# デフォルトの目盛り
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(2023)
img = np.random.rand(8,12)
fig, ax = plt.subplots()
ax.imshow(img)
ax.set_title('Original ticks')
ax.set_xlabel('x')
ax.set_ylabel('y')
plt.show()
各軸の座標が0
スタートのお馴染みの目盛り表示になります。
extentを使った軸目盛りの設定方法
imshow
関数のextent
引数を使うことで、任意の軸目盛を設定できます。
plt.imshow(image, extent=(left, right, bottom, top))
のように使います。ここで、extent
の引数は以下のようになります。
- left: X軸の最小値
- right: X軸の最大値
- bottom: Y軸の最小値
- top: Y軸の最大値
実際に先の例で、extent=(-4, 4, -1, 1)
として表示します。
# extentを使った軸目盛りの設定例
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(2023)
img = np.random.rand(8,12)
extent = (-4, 4, -1, 1)
fig, ax = plt.subplots()
ax.imshow(img, extent=extent, aspect='auto')
ax.set_title('Using extent')
ax.set_xlabel('x')
ax.set_ylabel('y')
plt.show()
extent
に指定した通りの目盛り表示になります。
extent
のaspect
の見た目の違いは、Stack Overflow imshow: extent and aspectが参考になります。
Secondary Axisを使った軸目盛りの設定方法
こちらの方法は、extent
の引数のままに2軸を表示したい場合には活用できますが、それ以外の場合はextent
を使うことをおすすめします。
1軸表示
まずは、extent
を使った軸目盛りの設定方法と同じ結果が得られることを確認します。
# secondary axisを使った軸目盛りの設定例
import numpy as np
import matplotlib.pyplot as plt
def secondary_axis(img, ax, extent, location_x, location_y):
"""
imshowの軸に対して、与えられた画像に対する2次のx軸とy軸を作成する関数
パラメータ:
img (ndarray): 表示する画像
ax (matplotlib.axes._subplots.AxesSubplot): 2次の軸を追加するMatplotlib軸
extent (tuple): 画像の範囲 (left, right, bottom, top)
location_x (str): 2次のx軸の位置 ('bottom', 'top')
location_y (str): 2次のy軸の位置 ('left', 'right')
戻り値:
ax: 2次の軸が追加された元の軸
secax_x: 2次のx軸
secax_y: 2次のy軸
"""
X_step = (extent[1]-extent[0]) / (img.shape[1])
X_start = extent[0]+0.5*X_step
Y_step = (extent[2]-extent[3]) / (img.shape[0])
Y_start = extent[3]+0.5*Y_step
secax_x = ax.secondary_xaxis(location_x,
functions=(lambda x: x*X_step + X_start, lambda x: (x - X_start) / X_step))
secax_y = ax.secondary_yaxis(location_y,
functions=(lambda y: y*Y_step + Y_start, lambda y: (y - Y_start) / Y_step))
return ax, secax_x, secax_y
np.random.seed(2023)
img = np.random.rand(8,12)
extent = (-4, 4, -1, 1)
fig, ax = plt.subplots()
ax.imshow(img, aspect='auto')
ax.set_title('Using secondary_axis')
ax.tick_params(labelbottom=False, labelleft=False, bottom=False, left=False)
ax, secax_x, secax_y = secondary_axis(img, ax, extent, 'bottom', 'left')
secax_x.set_xlabel('x')
secax_y.set_ylabel('y')
plt.show()
同じものが得られました。
簡単にコートの説明をします。
-
extent
の引数指定と同じような見た目になるように頑張ってsecondary_axis(img, ax, extent, location_x, location_y)
関数を作ります。具体的には、変換前後の軸目盛り関数を作ります。詳しくは、公式のSecondary Axisをご覧ください。 - 今のケースでは1軸目は不要なので、
ax.tick_params()
で消します。 - 2軸目のオブジェクト情報を
secax_x
,secax_y
で受け取り軸ラベルなどを書く場合は、secax_x.set_xlabel('x')
のように書きます。
2軸表示
1軸表示の例とほとんど同じです。1軸表示との違いは、1軸目を削除するか、2軸目の配置場所くらいです。
2軸表示のサンプルコード
# secondary axisを使った2軸目盛りの設定例
import numpy as np
import matplotlib.pyplot as plt
def secondary_axis(img, ax, extent, location_x, location_y):
"""
imshowの軸に対して、与えられた画像に対する2次のx軸とy軸を作成する関数
パラメータ:
img (ndarray): 表示する画像
ax (matplotlib.axes._subplots.AxesSubplot): 2次の軸を追加するMatplotlib軸
extent (tuple): 画像の範囲 (left, right, bottom, top)
location_x (str): 2次のx軸の位置 ('bottom', 'top')
location_y (str): 2次のy軸の位置 ('left', 'right')
戻り値:
ax: 2次の軸が追加された元の軸
secax_x: 2次のx軸
secax_y: 2次のy軸
"""
X_step = (extent[1]-extent[0]) / (img.shape[1])
X_start = extent[0]+0.5*X_step
Y_step = (extent[2]-extent[3]) / (img.shape[0])
Y_start = extent[3]+0.5*Y_step
secax_x = ax.secondary_xaxis(location_x,
functions=(lambda x: x*X_step + X_start, lambda x: (x - X_start) / X_step))
secax_y = ax.secondary_yaxis(location_y,
functions=(lambda y: y*Y_step + Y_start, lambda y: (y - Y_start) / Y_step))
return ax, secax_x, secax_y
np.random.seed(2023)
img = np.random.rand(8,12)
extent = (-4, 4, -1, 1)
fig, ax = plt.subplots()
ax.imshow(img, aspect='auto')
ax.set_title('Using secondary_axis 2 axis show')
ax.set_xlabel('x')
ax.set_ylabel('x')
# 2軸目
ax, secax_x, secax_y = secondary_axis(img, ax, extent, 'top', 'right')
secax_x.set_xlabel('x second')
secax_y.set_ylabel('y second')
plt.show()
2軸表示できているのがわかります。このように、imshow
関数のextent
引数の指定方法と同じように2軸が表示できます。
まとめ
本記事では、Matplotlibを使用して画像を表示する際に、軸の目盛りを調整する方法について説明しました。以下はまとめのポイントです。
-
extentを使用した軸目盛の設定:
- imshow関数のextent引数を使用することで、軸の目盛りを自由に設定できます。
- extentを使うことで、画像データの各ピクセルが指定された範囲内にどのようにマッピングされるかを制御できます。
-
Secondary Axisを使用した軸目盛りの設定:
- secondary_xaxisとsecondary_yaxisを使用する方法を紹介しました。
- この方法は、extentの代替方法として活用できますが、やや複雑であり、2つの軸を組み合わせたい場合に有用です。
本記事が、どなたかの役に立てば幸いです。