matplotlib – 指定した解像度で図を保存する方法について

目次

概要

matplotlib で指定した解像度の図を画像で保存する方法について解説します。

figsize, dpi と出力される図の解像度の関係

画像化した際の解像度は Figure オブジェクトの figsizedpi によって決定されます。

  • 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 を指定しない場合はデフォルト値が使用されます。

In [1]:
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 を以下のように設定すればよいです。

In [2]:
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 を反映させたい場合、以下のように設定を無効にします。

In [3]:
%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 とすればよいとわかります。

In [4]:
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

コメント

コメントする

目次