macOSでpyenvを使用してセットアップしたPython環境でscikit-imageを使う場合の話。
scikit-imageで画像表示をしようとするとプラグインとしてmatplotlibを使わざるを得ない。
macOS上でpyenvでインストールしたPython環境ではmatplotlibのbackendを変更しないとエラーが出て動かないので対処方法。
結論を先に書くと、matplotlibのバックエンドをTkAgg
かQt5Agg
にする(必要なライブラリはインストールする前提)。
環境
- macOS Sierra
- Python 3.5 (pyenv)
- scikit-image
scikit-image のインストール手順
そもそもどうやってインストールしたのかというと下記の手順。
$ pip install -U scikit-image
$ pip install scipy
$ pip install matplotlib
pip
はpyenv
でインストールしたPython 3.5.3のもの。
やりたいこと
scikit-imageというライブラリの、io.show()
で画像を表示したい。
問題
何も考えずにpip
で scikit-image パッケージをインストールすると、下記のエラーに遭遇して画像を表示できない。
io.show()
を呼び出して画像を表示したいが、その前にio.imshow()
で表示する画像を割り当てる必要がある。
この時点でRuntimeError。
>>> io.imshow(img)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/atuyosi/.pyenv/versions/3.5.3/lib/python3.5/site-packages/skimage/io/_io.py", line 156, in imshow
return call_plugin('imshow', arr, plugin=plugin, **plugin_args)
File "/Users/atuyosi/.pyenv/versions/3.5.3/lib/python3.5/site-packages/skimage/io/manage_plugins.py", line 198, in call_plugin
raise RuntimeError(msg % kind)
RuntimeError: No suitable plugin registered for imshow.
You may load I/O plugins with the `skimage.io.use_plugin` command. A list of all available plugins are shown in the `skimage.io` docstring.
画面表示に利用可能なプラグインがないというメッセージのようなので、まずはプラグインを調べる。
>>> io.find_available_plugins()
{'gdal': ['imread', 'imread_collection'], 'imread': ['imread', 'imsave', 'imread_collection'], 'simpleitk': ['imread', 'imsave', 'imread_collection'], 'test': ['imsave', 'imshow', 'imread', 'imread_collection', 'imshow_collection'], 'pil': ['imread', 'imsave', 'imread_collection'], 'matplotlib': ['imshow', 'imread', 'imshow_collection', 'imread_collection'], 'imageio': ['imread', 'imsave', 'imread_collection'], 'qt': ['imshow', 'imsave', 'imread', 'imread_collection'], 'gtk': ['imshow'], 'freeimage': ['imread', 'imsave', 'imread_collection'], 'tifffile': ['imread', 'imsave', 'imread_collection'], 'fits': ['imread', 'imread_collection']}
プラグインごとに使用可能な機能がプラグインの名称の後に配列として保持されている。imshow
に対応しているのは、test
を覗くとmatplotlib
と、qt
、gtk
の3つ。このうちqt
はPyQt4を要求する。
インストール済みのMatplotlib を使おうとすると、下記のエラーに遭遇する。
>>> io.use_plugin('matplotlib')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/atuyosi/.pyenv/versions/3.5.3/lib/python3.5/site-packages/skimage/io/manage_plugins.py", line 255, in use_plugin
_load(name)
File "/Users/atuyosi/.pyenv/versions/3.5.3/lib/python3.5/site-packages/skimage/io/manage_plugins.py", line 299, in _load
fromlist=[modname])
File "/Users/atuyosi/.pyenv/versions/3.5.3/lib/python3.5/site-packages/skimage/io/_plugins/matplotlib_plugin.py", line 3, in <module>
import matplotlib.pyplot as plt
File "/Users/atuyosi/.pyenv/versions/3.5.3/lib/python3.5/site-packages/matplotlib/pyplot.py", line 115, in <module>
_backend_mod, new_figure_manager, draw_if_interactive, _show = pylab_setup()
File "/Users/atuyosi/.pyenv/versions/3.5.3/lib/python3.5/site-packages/matplotlib/backends/__init__.py", line 32, in pylab_setup
globals(),locals(),[backend_name],0)
File "/Users/atuyosi/.pyenv/versions/3.5.3/lib/python3.5/site-packages/matplotlib/backends/backend_macosx.py", line 19, in <module>
from matplotlib.backends import _macosx
RuntimeError: Python is not installed as a framework. The Mac OS X backend will not be able to function correctly if Python is not installed as a framework. See the Python documentation for more information on installing Python as a framework on Mac OS X. Please either reinstall Python as a framework, or try one of the other backends. If you are using (Ana)Conda please install python.app and replace the use of 'python' with 'pythonw'. See 'Working with Matplotlib on OSX' in the Matplotlib FAQ for more information.
と言われてmatplotlib側のバックエンド設定の問題で利用できない。Python自体をframework形式でインストールしろと言っているようだがさすがに面倒。
存在するプラグインではなく実際に有効なプラグインを調べる。
>>> io.find_available_plugins(loaded=True)
{'pil': ['imread', 'imsave', 'imread_collection']}
pil
というプラグインしか有効になっていない。
対処方法
何らかのバックエンドが利用できるようにすれば良い。Qt4自体がサポート切れなのでPyQt4はやめておく。Tkを使ってもいいが、Qt5の方がモダンでいいような気がする。
そこでPyQt5をインストールし、matplotlib 経由で使うことにする。
まずはQt5本体をインストール。
$ brew install qt
続いてPyQt5。
$ pip install PyQt5
PyQt5-5.9 がインストールされる。依存関係で必要なライブラリも勝手に入るはず。
設定ファイルの修正。
matplotlibの設定ファイルの場所は下記の手順で確認できる。
>>> import matplotlib
>>> matplotlib.matplotlib_fname()
'/Users/atuyosi/.pyenv/versions/3.5.3/lib/python3.5/site-packages/matplotlib/mpl-data/matplotlibrc'
エディタで上記のファイルを編集。
$ vi .pyenv/versions/3.5.3/lib/python3.5/site-packages/matplotlib/mpl-data/matplotlibrc
バックエンドを指定している箇所を探す。
backend : macosx
使用するバックエンドを指定する。
backend : Qt5Agg
動作確認
ちゃんとプラグインが有効かを確かめる。
>>> from skimage import io
>>> io.use_plugin('matplotlib')
>>> io.find_available_plugins(loaded=True)
{'matplotlib': ['imshow', 'imread', 'imshow_collection', 'imread_collection'], 'pil': ['imread', 'imsave', 'imread_collection']}
画像の表示は以下のようにする。
>>> from skimage import io
>>> img = io.imread("test.jpg")
>>> io.imshow(img)
<matplotlib.image.AxesImage object at 0x110ba1160>
>>> io.show()
^C
io.imshow()
を呼び出さずにio.show()
を呼び出しても何も表示されないので注意。
実際の表示は以下のようになる。
scikit-image ライブラリの、data
モジュールを読み込むとテスト画像が読み込めるのでこれを使う。
>>> from skimage import data
>>> io.imshow(data.camera())
<matplotlib.image.AxesImage object at 0x1138707b8>
>>> io.show()
プラグインの順序によっては明示的にmatplotlib
を使うように指定すればいい。
>>> io.use_plugin('matplotlib')