macos
matplotlib
pyenv
scikit-image

macOS上の scikit-image で画像表示(pyenv/Python 3)

More than 1 year has passed since last update.

macOSでpyenvを使用してセットアップしたPython環境でscikit-imageを使う場合の話。

scikit-imageで画像表示をしようとするとプラグインとしてmatplotlibを使わざるを得ない。
macOS上でpyenvでインストールしたPython環境ではmatplotlibのbackendを変更しないとエラーが出て動かないので対処方法。

結論を先に書くと、matplotlibのバックエンドをTkAggQt5Aggにする(必要なライブラリはインストールする前提)。

環境

  • macOS Sierra
  • Python 3.5 (pyenv)
  • scikit-image

scikit-image のインストール手順

そもそもどうやってインストールしたのかというと下記の手順。

$ pip install -U scikit-image
$ pip install scipy
$ pip install matplotlib

pippyenvでインストールした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と、qtgtkの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()

スクリーンショット 2017-09-13 5.00.41.png

プラグインの順序によっては明示的にmatplotlibを使うように指定すればいい。

>>> io.use_plugin('matplotlib')

参考