0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[Python / matplotlib] AttributeError: 'FigureCanvasAgg' object has no attribute 'tostring_rgb' が発生した時の対応策

Posted at

概要

matplotlib を使っていたら以下のようなエラーが発生した。

AttributeError: 'FigureCanvasAgg' object has no attribute 'tostring_rgb'

この時の対策について記す。

実行時の状況によって、対策は異なるものと思われる。

場合分け

1. 外部ライブラリで tostring_rgb が使われていた場合

以下の記事に対策が書かれている。

matplotlib のバージョンを 3.7.0 に落とせば解決するらしい。
つまり、以下のようにすれば良い、ということだろう。

$ pip uninstall matplotlib
$ pip install -q matplotlib==3.7.0

自分はこの場合ではなかった。

2. 自分が書いたソースコードで tostring_rgb を使っている場合

tostring_rgbbuffer_rgba に置き換えたら解決した。

先に前期の github の issue を見たので混乱してしまったが、呼び出すメソッドを変更すれば問題が解決に向かう。

以下の例を参考にされたい。

# 修正前
import matplotlib.pyplot as plt


fig: plt.Figure = plt.figure(figsize=(4, 4))
fig.canvas.draw()

# なんやかんや描画処理...

data = fig.canvas.tostring_rgb()  # ここを変更する
# 修正後
import matplotlib.pyplot as plt


fig: plt.Figure = plt.figure(figsize=(4, 4))
fig.canvas.draw()

# なんやかんや描画処理...

# ❌ボツ対策
data = fig.canvas.tostring_argb()  # これをすると、順番がおかしくなって結果的に色がおかしくなる

# ⭕️こっちがよかった
buffer = fig.canvas.buffer_rgba()  # なので、こうする

ただし、このままだと buffer は上手く扱えない。

その続きを例えば以下のようにしたところ、自然な numpy 配列型のデータに変換された。

# 画像をバイト列で取得する。
# data = fig.canvas.tostring_argb()  # 色がおかしくなる
buffer = fig.canvas.buffer_rgba()

# この時点では、画像の各ピクセルが1次元の配列として格納されている。
one_line_img: np.ndarray = np.frombuffer(buffer, dtype=np.uint8)

# 画像の大きさを取得する。
w, h = fig.canvas.get_width_height()
c = len(one_line_img) // (w * h)  # channel 数

# numpy 配列に変換する
img = one_line_img.reshape(h, w, c)

参考

.buffer_rgba() について

fig.canvas.buffer_rgba() を使うアイデアはこの記事に書かれていた。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?