PythonのMatplotlibのグラフをNumPy行列に変換してOpenCVやPillowで使う

PythonのMatplotlibで描いたグラフを、NumPyのndarrayに変換して、OpenCVやPillowで使えるようにします。

目次

  1. Matplotlibのグラフをndarrayに変換する
  2. サンプルのグラフの作成
  3. グラフをndarrayに変換してPillow(PIL)で表示する
  4. グラフをndarrayに変換してOpenCVで表示する

Matplotlibのグラフをndarrayに変換する

Matplotlibはグラフを描いて表示して保存するだけなら非常に便利なのですが、出力をいじろうとするとなかなか難しいものです。 公式のチュートリアル を参考にしましたが、APIのマニュアルを読んでもよくわからないところがあります。

本投稿の環境は、Python 3.7とmatplotlib 3.1.1です。動作しないようでしたら、matplotlibのバージョンを確認してみてください。

手順は次の通りです。

  1. matplotlibのpyplotでFigureオブジェクトを作る。
  2. グラフをプロットする。
  3. Figureオブジェクトのcanvasに書き込む。
  4. canvasのデータを取り出してndarrayに変換する。
  5. ndarrayをOpenCVやPillowで利用する。

サンプルのグラフの作成

まず、単純にmatplotlibでグラフを描画してみます。

from matplotlib import pyplot as plt
import numpy as np

x = np.linspace(0, 2*np.pi, 21)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = y1-y2

fig, ax = plt.subplots()
ax.plot(x, y1, 'b.-')
ax.plot(x, y2, 'g,-.')
ax.plot(x, y3, 'r,-.')
plt.show()
元画像

y=sin(x)とy=cos(x)とy=sin(x)-cos(x)が描かれたグラフです。

グラフをndarrayに変換してPillow(PIL)で表示する

ではndarrayに変換してPillowで表示してみましょう。

from matplotlib import pyplot as plt
import numpy as np
from PIL import Image

x = np.linspace(0, 2*np.pi, 21)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = y1-y2

fig, ax = plt.subplots()
ax.plot(x, y1, 'b.-')
ax.plot(x, y2, 'g,-.')
ax.plot(x, y3, 'r,-.')

fig.canvas.draw()
im = np.array(fig.canvas.renderer.buffer_rgba())
# im = np.array(fig.canvas.renderer._renderer) # matplotlibが3.1より前の場合

img = Image.fromarray(im)
img.show()

fig.canvas.draw()というところで、canvasにグラフを描画しています。

その次の行でcanvasからデータを取り出しています。burrer_rgba()という関数は私の環境ではmatplotlibを3.1にアップグレードしないと使えませんでした。

PillowのImageクラスのfromarrayメソッドで、ndarrayをImageオブジェクトに変換します。

で、表示するとこうなります。

Pillowで表示

グラフをndarrayに変換してOpenCVで表示する

ndarrayに変換できるのであれば、OpenCVでも使えます。

from matplotlib import pyplot as plt
import numpy as np
import cv2

x = np.linspace(0, 2*np.pi, 21)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = y1-y2

fig, ax = plt.subplots()
ax.plot(x, y1, 'b.-')
ax.plot(x, y2, 'g,-.')
ax.plot(x, y3, 'r,-.')

fig.canvas.draw()
im = np.array(fig.canvas.renderer.buffer_rgba())
# im = np.array(fig.canvas.renderer._renderer) # matplotlibが3.1より前の場合

im = cv2.cvtColor(im, cv2.COLOR_RGBA2BGR)
cv2.imshow('test', im)
cv2.waitKey()
cv2.destroyAllWindows()

matplotlibのグラフの描画データをndarrayに変換するとRGBA形式になります。Pillowでは問題になりませんが、OpenCVでこのまま使うと色が変わってしまいます。そこで、OpenCVで標準的なBGRまたはBGRA形式への変換が必要になります。

この色変換を行っているのがcvtColorメソッドです。

色変換すればいかようにも扱えます。

表示するとこんな感じです。

OpenCVで表示

広告

Pythonでグラフカテゴリの投稿