2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Matplotlibでimshow画像の軸目盛りの調整:extentとsecondary_axisの活用

Last updated at Posted at 2023-10-18

はじめに

Matplotlibを使用して画像を表示する際、軸の目盛りの調整や2軸を使いたい場合があります。本記事では、imshow関数の引数であるextentを使用して軸の目盛りを調整する方法を紹介します。

そして、このextentの方法を知る前まで筆者が愛用していたSecondary Axisでの実装コードも紹介します。この方法は少し複雑ですが、extentと同様の指定方法でimshowで2軸を表示したい場合に活用していただければ幸いです。

以下が、本記事の概要のイメージです。

image.png

本記事で使用したコードは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()

image.png

各軸の座標が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()

image.png

extentに指定した通りの目盛り表示になります。
extentaspectの見た目の違いは、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()

image.png

同じものが得られました。

簡単にコートの説明をします。

  1. extentの引数指定と同じような見た目になるように頑張ってsecondary_axis(img, ax, extent, location_x, location_y)関数を作ります。具体的には、変換前後の軸目盛り関数を作ります。詳しくは、公式のSecondary Axisをご覧ください。
  2. 今のケースでは1軸目は不要なので、ax.tick_params()で消します。
  3. 2軸目のオブジェクト情報をsecax_x, secax_yで受け取り軸ラベルなどを書く場合は、secax_x.set_xlabel('x')のように書きます。

2軸表示

1軸表示の例とほとんど同じです。1軸表示との違いは、1軸目を削除するか、2軸目の配置場所くらいです。

2軸表示のサンプルコード
secondary axisを使った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()

image.png

2軸表示できているのがわかります。このように、imshow関数のextent引数の指定方法と同じように2軸が表示できます。

まとめ

本記事では、Matplotlibを使用して画像を表示する際に、軸の目盛りを調整する方法について説明しました。以下はまとめのポイントです。

  • extentを使用した軸目盛の設定:

    • imshow関数のextent引数を使用することで、軸の目盛りを自由に設定できます。
    • extentを使うことで、画像データの各ピクセルが指定された範囲内にどのようにマッピングされるかを制御できます。
  • Secondary Axisを使用した軸目盛りの設定:

    • secondary_xaxisとsecondary_yaxisを使用する方法を紹介しました。
    • この方法は、extentの代替方法として活用できますが、やや複雑であり、2つの軸を組み合わせたい場合に有用です。

本記事が、どなたかの役に立てば幸いです。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?