はじめに
matplotlibで画像を対数(log)スケールで表示するとき、以下のようにそのlogスケールにした後の色情報値として持っておきたい場合があると思います。その値を取得する方法と、対数の正規化の簡易的な実装コードを紹介します。
実装
Google Colabで作成した本記事のコードは、こちらにあります。
各種インポート
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LogNorm
実行時の各種バージョン
Name | Version |
---|---|
numpy | 1.22.4 |
matplotlib | 3.5.3 |
方法
matplotlibのLogNormを使います。LogNormクラスのインスタンスを生成して、__call__()
メソッドを呼び出して、値を受け取れば終了です。
data = np.array([[1, 10] ,[100, 1000]])
# インスタンス生成
log_norm = LogNorm(vmin=data.min(), vmax=data.max())
# log正規化(__call__()メソッドを呼ぶ)
log_norm_data = log_norm(data, clip=True)
fig, (ax0, ax1, ax2) = plt.subplots(1, 3, figsize=(14, 4))
im0 = ax0.imshow(data)
ax0.set_title('data')
cbar0 = fig.colorbar(im0, ax=ax0, shrink=0.9)
im1 = ax1.imshow(data, norm=log_norm)
ax1.set_title('data with logsale')
cbar1 = fig.colorbar(im1, ax=ax1, shrink=0.9)
im2 = ax2.imshow(log_norm_data)
ax2.set_title('log_norm_data')
cbar2 = fig.colorbar(im2, ax=ax2, shrink=0.9)
plt.show()
- 左側のdata: 生データを線形のカラーバで表示
- 中央のdata with logscale: 生データを対数スケールのカラーバで表示
- 右側のlog_norm_data: 生データを対数で正規化した後、線形のカラーバで表示
中央と右側の図で、同じ色情報で表示できているのがわかります。
簡易的な実装方法
matplotlibのLogNormの__call__()メソッドのソースコードの本質的な部分だけ抜き出して簡易的に実装すると以下のようになります。
def my_log_norm(data, vmin, vmax):
clip_data = np.clip(data, vmin, vmax)
log_data = np.log(clip_data)
log_norm_data = (log_data-log_data.min()) / (log_data.max()-log_data.min())
return log_norm_data
コードの意味は、まず、np.clip()
でvmin
, vmax
の外側の値をその値に置換します。
そして、あとはnp.log()
でlogスケール化し、min-max normalizationのコードを書くだけです。
matplotlib公式のlogスケールの説明ではlogの底を10としていますが、min-max normalizationで底が打ち消されるので実際は何でも良いと思います。(my_log_norm()
では、底はeとしています。)
※matplotlibのLogNormでは、もう少し高級なコードになっているので、基本的にこの関数(my_log_norm()
)は使わない方が無難です。
my_log_norm()関数の動作確認
data = np.array([[1, 10] ,[100, 1000]])
cbar_min, cbar_max = (1, 100)
# インスタンス生成
log_norm = LogNorm(vmin=cbar_min, vmax=cbar_max)
# log正規化(__call__()メソッドを呼ぶ)
log_norm_data = log_norm(data, clip=True)
# 自作のlognorm
my_log_norm_data = my_log_norm(data, vmin=cbar_min, vmax=cbar_max)
fig, (ax0, ax1) = plt.subplots(1, 2, figsize=(9, 4))
im0 = ax0.imshow(log_norm_data)
ax0.set_title('log_norm_data')
cbar0 = fig.colorbar(im0, ax=ax0, shrink=0.9)
im1 = ax1.imshow(my_log_norm_data)
ax1.set_title('my_log_norm_data')
cbar1 = fig.colorbar(im1, ax=ax1, shrink=0.9)
plt.show()
まとめ
matplotlibのlogスケールの色を値として保持する方法を紹介しました。対数スケールでの正規化は、値の範囲が大きい画像などに便利なので、ぜひご活用していただけると幸いです。
参考資料