概要
matplotlib で指定した解像度の図を画像で保存する方法について解説します。
figsize, dpi と出力される図の解像度の関係
画像化した際の解像度は Figure オブジェクトの figsize
と dpi
によって決定されます。
figsize=(w_in, h_in)
: Figure の大きさ。インチ単位で指定する。dpi
: 1インチあたりのドット数。
$\text{figsize}=(w_{in}, h_{in}), dpi$ が与えられたとき、生成された図のピクセル単位の大きさ $w_{px}, h_{px}$ は以下の関係のように計算されます。
$$ \begin{aligned} w_{px} &= w_{in} * dpi \\ h_{px} &= h_{in} * dpi \end{aligned} $$figsize, dpi
を指定しない場合はデフォルト値が使用されます。
import matplotlib as mpl
w_in, h_in = mpl.rcParams["figure.figsize"]
dpi = mpl.rcParams["figure.dpi"]
print("figsize (inch)", (w_in, h_in))
print("dpi (px/inch)", dpi)
print("save size (px)", (w_in * dpi, h_in * dpi))
figsize (inch) (6.0, 4.0) dpi (px/inch) 72.0 save size (px) (432.0, 288.0)
例えば、解像度が (640px, 480px)
の図を作成したい場合、先の計算式を元に figsize
を以下のように設定すればよいです。
import numpy as np
from matplotlib import pyplot as plt
x = np.linspace(0, np.pi * 4, 1000)
y = np.sin(x)
figsize_px = np.array([640, 480])
dpi = 100
figsize_inch = figsize_px / dpi
print("figsize", figsize_inch) # figsize (6.4, 4.8)
fig, ax = plt.subplots(figsize=figsize_inch, dpi=dpi)
ax.plot(x, y)
# 図を画像として保存して、画像の大きさを確認する。
fig.savefig("figure.png")
img = plt.imread("figure.png")
print(img.shape) # (480, 640, 4)
figsize [6.4 4.8] (480, 640, 4)
サイズを変更せずに画像に図を描画したい場合
matplotlib は imshow()
で画像を図に描画できますが、あくまでグラフ描画ライブラリです。
画像認識の結果を矩形やテキストで画像に描画したい場合などは matplotlib ではなく、OpenCV や Pillow の図形描画機能を使用しましょう。
[blogcard url=”https://pystyle.info/opencv-drawing-functions”]
Jupyter Notebook で inline で図を表示する場合の注意点
Jupyter Notebook で inline で図を表示する場合、設定が bbox_inches="tight"
で上書きされてしまうので、指定した figsize, dpi
を反映させたい場合、以下のように設定を無効にします。
%matplotlib inline
%config InlineBackend.print_figure_kwargs = {'bbox_inches': None}
ポイントと出力される図の解像度の関係
fontsize
など matplotlib の一部のパラメータはポイント (pt) 単位で指定するようになっています。
1pt = 1/72インチであるため、x インチをポイントに換算するには x (inch) * 72 (pt/inch) と計算します。
例えば、figsize
の横幅が6インチであるとき、This is title
という長さ13の文字列をちょうどこの幅に収まるように fontsize
を指定することを考えます。
figsize
の横幅の6インチをポイント単位にすると、 6 pt * 72 pt/inch = 432 pt
となるため、1文字あたりのフォントサイズは 432 / 13 = 33.23
より 33 pt
とすればよいとわかります。
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, np.pi * 4, 1000)
y = np.sin(x)
text = "This is title"
figsize = 6, 4
dpi = 100
fontsize = int(figsize[0] * 72 / len(text))
print(fontsize) # 33
fig, ax = plt.subplots(figsize=figsize, dpi=dpi)
fig.suptitle(text, fontsize=fontsize)
plt.show()
33
コメント