画像チュートリアル#

Matplotlib を使用した画像のプロットに関する短いチュートリアル。

起動コマンド#

まず、IPython を起動します。これは、標準の Python プロンプトに対する最も優れた拡張機能であり、特に Matplotlib とうまく連携します。IPython をシェルで直接起動するか、Jupyter Notebook (IPython を実行中のカーネルとして使用) を使用して起動します。

IPython を開始したら、GUI イベント ループに接続する必要があります。これにより、プロットを表示する場所 (および方法) が IPython に伝えられます。GUI ループに接続するには、IPython プロンプトで%matplotlibマジックを実行します。これが正確に何をするかについての詳細は、IPython の GUI イベント ループに関するドキュメント にあります

Jupyter Notebook を使用している場合、同じコマンドを使用できますが、%matplotlib マジックに対して特定の引数を使用するのが一般的です。

In [1]: %matplotlib inline

これにより、インライン プロットがオンになり、ノートブックにプロット グラフィックが表示されます。これは、インタラクティブ性に重要な意味を持ちます。インライン プロットの場合、プロットを出力するセルの下のセルのコマンドはプロットに影響しません。たとえば、プロットを作成するセルの下のセルからカラーマップを変更することはできません。ただし、別のウィンドウを開く Qt などの他のバックエンドの場合、プロットを作成するセルの下のセルはプロットを変更します。これはメモリ内のライブ オブジェクトです。

このチュートリアルでは、Matplotlib の暗黙的なプロット インターフェイスである pyplot を使用します。このインターフェイスはグローバルな状態を維持し、さまざまなプロット設定をすばやく簡単に試すのに非常に役立ちます。もう 1 つの方法は明示的であり、大規模なアプリケーション開発により適しています。暗黙的インターフェイスと明示的インターフェイスの間のトレードオフの説明については、 Matplotlib アプリケーション インターフェイス (API)と明示的インターフェイスの使用を開始するためのクイック スタート ガイドを参照してください。とりあえず、暗黙のアプローチに取り掛かりましょう。

import matplotlib.pyplot as plt
import matplotlib.image as mpimg

画像データを Numpy 配列にインポートする#

Matplotlib は、 Pillowライブラリに依存して画像データを読み込みます。

再生する画像は次のとおりです。

../../_images/stinkbug.png

24 ビット RGB PNG 画像 (R、G、B 各 8 ビット) です。データを取得する場所に応じて、他の種類の画像に最も遭遇する可能性が高いのは、透過性を可能にする RGBA 画像、または単一チャネルのグレースケール (輝度) 画像です。 このチュートリアルの残りの部分では、stinkbug.pngをコンピューターにダウンロードします。

さあ、いくぞ...

img = mpimg.imread('../../doc/_static/stinkbug.png')
print(img)
[[[0.40784314 0.40784314 0.40784314]
  [0.40784314 0.40784314 0.40784314]
  [0.40784314 0.40784314 0.40784314]
  ...
  [0.42745098 0.42745098 0.42745098]
  [0.42745098 0.42745098 0.42745098]
  [0.42745098 0.42745098 0.42745098]]

 [[0.4117647  0.4117647  0.4117647 ]
  [0.4117647  0.4117647  0.4117647 ]
  [0.4117647  0.4117647  0.4117647 ]
  ...
  [0.42745098 0.42745098 0.42745098]
  [0.42745098 0.42745098 0.42745098]
  [0.42745098 0.42745098 0.42745098]]

 [[0.41960785 0.41960785 0.41960785]
  [0.41568628 0.41568628 0.41568628]
  [0.41568628 0.41568628 0.41568628]
  ...
  [0.43137255 0.43137255 0.43137255]
  [0.43137255 0.43137255 0.43137255]
  [0.43137255 0.43137255 0.43137255]]

 ...

 [[0.4392157  0.4392157  0.4392157 ]
  [0.43529412 0.43529412 0.43529412]
  [0.43137255 0.43137255 0.43137255]
  ...
  [0.45490196 0.45490196 0.45490196]
  [0.4509804  0.4509804  0.4509804 ]
  [0.4509804  0.4509804  0.4509804 ]]

 [[0.44313726 0.44313726 0.44313726]
  [0.44313726 0.44313726 0.44313726]
  [0.4392157  0.4392157  0.4392157 ]
  ...
  [0.4509804  0.4509804  0.4509804 ]
  [0.44705883 0.44705883 0.44705883]
  [0.44705883 0.44705883 0.44705883]]

 [[0.44313726 0.44313726 0.44313726]
  [0.4509804  0.4509804  0.4509804 ]
  [0.4509804  0.4509804  0.4509804 ]
  ...
  [0.44705883 0.44705883 0.44705883]
  [0.44705883 0.44705883 0.44705883]
  [0.44313726 0.44313726 0.44313726]]]

そこのdtypeに注意してください-float32。Matplotlib は、各チャネルの 8 ビット データを 0.0 から 1.0 の間の浮動小数点データに再スケーリングしました。ちなみに、Pillow で使用できるデータ型は uint8 のみです。Matplotlib プロットは float32 と uint8 を処理できますが、PNG 以外の形式の画像の読み取り/書き込みは uint8 データに限定されます。なぜ8ビット?ほとんどのディスプレイは、チャネルあたり 8 ビットのカラー グラデーションしかレンダリングできません。8 ビット/チャンネルしかレンダリングできないのはなぜですか? それは人間の目で見ることができるほぼすべてだからです。詳細はこちら (写真の観点から): Luminous Landscape bit depth tutorial .

各内部リストはピクセルを表します。ここで、RGB イメージでは、3 つの値があります。白黒画像なので、R、G、Bはすべて似ています。RGBA (A はアルファまたは透明度) は内部リストごとに 4 つの値を持ち、単純な輝度イメージは値を 1 つだけ持ちます (したがって、3 次元配列ではなく 2 次元配列にすぎません)。RGB および RGBA 画像の場合、Matplotlib は float32 および uint8 データ型をサポートします。グレースケールの場合、Matplotlib は float32 のみをサポートします。配列データがこれらの説明のいずれにも適合しない場合は、再スケーリングする必要があります。

numpy 配列を画像としてプロットする#

したがって、データを numpy 配列に (インポートするか、生成することによって) 保持します。レンダリングしましょう。Matplotlib では、これはimshow()関数を使用して実行されます。ここで、プロット オブジェクトを取得します。このオブジェクトを使用すると、プロンプトからプロットを簡単に操作できます。

画像

numpy 配列をプロットすることもできます。

画像プロットへの擬似配色の適用#

疑似カラーは、コントラストを強調し、データをより簡単に視覚化するための便利なツールです。これは、プロジェクタを使用してデータのプレゼンテーションを作成する場合に特に役立ちます。プロジェクタのコントラストは通常​​非常に貧弱です。

疑似カラーは、単一チャネル、グレースケール、明度の画像にのみ関連します。現在、RGB 画像があります。R、G、および B はすべて類似しているため (上記またはデータを参照してください)、データのチャネルを 1 つだけ選択できます。

lum_img = img[:, :, 0]

# This is array slicing.  You can read more in the `Numpy tutorial
# <https://numpy.org/doc/stable/user/quickstart.html>`_.

plt.imshow(lum_img)
画像
<matplotlib.image.AxesImage object at 0x7f2cdd608610>

これで、明度 (2D、色なし) 画像で、デフォルトのカラーマップ (別名ルックアップ テーブル、LUT) が適用されます。デフォルトは viridis です。他にもたくさんの選択肢があります。

plt.imshow(lum_img, cmap="hot")
画像
<matplotlib.image.AxesImage object at 0x7f2cddcc2aa0>

set_cmap()次のメソッドを使用して、既存のプロット オブジェクトのカラーマップを変更することもできます 。

画像

ノート

ただし、インライン バックエンドを使用する Jupyter Notebook では、既にレンダリングされたプロットを変更できないことに注意してください。ここで 1 つのセルに imgplot を作成すると、後のセルで set_cmap() を呼び出すことはできず、以前のプロットが変更されることを期待できません。これらのコマンドは、必ず 1 つのセルにまとめて入力してください。plt コマンドは、以前のセルからプロットを変更しません。

他にも多くのカラーマップ スキームが利用可能です。カラーマップのリストと画像を参照してください。

カラースケール参照番号

色が表す値を把握しておくと役に立ちます。Figure にカラー バーを追加することで、これを行うことができます。

画像
<matplotlib.colorbar.Colorbar object at 0x7f2cdf5297e0>

特定のデータ範囲を調べる#

場合によっては、画像のコントラストを強調したり、特定の領域のコントラストを拡大したりしながら、あまり変化しない、または問題にならない色の詳細を犠牲にしたいことがあります。興味深い領域を見つけるための優れたツールは、ヒストグラムです。画像データのヒストグラムを作成するには、hist()関数を使用します。

plt.hist(lum_img.ravel(), bins=256, range=(0.0, 1.0), fc='k', ec='k')
画像
(array([2.000e+00, 2.000e+00, 3.000e+00, 3.000e+00, 2.000e+00, 2.000e+00,
       3.000e+00, 1.000e+00, 7.000e+00, 9.000e+00, 7.000e+00, 2.000e+00,
       7.000e+00, 1.000e+01, 1.100e+01, 1.500e+01, 1.400e+01, 2.700e+01,
       2.100e+01, 2.400e+01, 1.400e+01, 3.100e+01, 2.900e+01, 2.800e+01,
       2.400e+01, 2.400e+01, 4.000e+01, 2.600e+01, 5.200e+01, 3.900e+01,
       5.700e+01, 4.600e+01, 8.400e+01, 7.600e+01, 8.900e+01, 8.000e+01,
       1.060e+02, 1.130e+02, 1.120e+02, 9.000e+01, 1.160e+02, 1.090e+02,
       1.270e+02, 1.350e+02, 9.800e+01, 1.310e+02, 1.230e+02, 1.110e+02,
       1.230e+02, 1.160e+02, 1.010e+02, 1.170e+02, 1.000e+02, 1.010e+02,
       9.000e+01, 1.060e+02, 1.260e+02, 1.040e+02, 1.070e+02, 1.110e+02,
       1.380e+02, 1.000e+02, 1.340e+02, 1.210e+02, 1.400e+02, 1.320e+02,
       1.390e+02, 1.160e+02, 1.330e+02, 1.180e+02, 1.080e+02, 1.170e+02,
       1.280e+02, 1.200e+02, 1.210e+02, 1.100e+02, 1.160e+02, 1.180e+02,
       9.700e+01, 9.700e+01, 1.140e+02, 1.070e+02, 1.170e+02, 8.700e+01,
       1.070e+02, 9.800e+01, 1.040e+02, 1.120e+02, 1.110e+02, 1.180e+02,
       1.240e+02, 1.340e+02, 1.200e+02, 1.410e+02, 1.520e+02, 1.360e+02,
       1.610e+02, 1.380e+02, 1.620e+02, 1.570e+02, 1.350e+02, 1.470e+02,
       1.690e+02, 1.710e+02, 1.820e+02, 1.980e+02, 1.970e+02, 2.060e+02,
       2.160e+02, 2.460e+02, 2.210e+02, 2.520e+02, 2.890e+02, 3.450e+02,
       3.620e+02, 3.760e+02, 4.480e+02, 4.630e+02, 5.170e+02, 6.000e+02,
       6.200e+02, 6.410e+02, 7.440e+02, 7.120e+02, 8.330e+02, 9.290e+02,
       1.061e+03, 1.280e+03, 1.340e+03, 1.638e+03, 1.740e+03, 1.953e+03,
       2.151e+03, 2.290e+03, 2.440e+03, 2.758e+03, 2.896e+03, 3.384e+03,
       4.332e+03, 5.584e+03, 6.197e+03, 6.422e+03, 6.404e+03, 7.181e+03,
       8.196e+03, 7.968e+03, 7.474e+03, 7.926e+03, 8.460e+03, 8.091e+03,
       9.148e+03, 8.563e+03, 6.747e+03, 6.074e+03, 6.328e+03, 5.291e+03,
       6.472e+03, 6.268e+03, 2.864e+03, 3.760e+02, 1.620e+02, 1.180e+02,
       1.270e+02, 9.500e+01, 7.600e+01, 8.200e+01, 6.200e+01, 6.700e+01,
       5.600e+01, 5.900e+01, 4.000e+01, 4.200e+01, 3.000e+01, 3.400e+01,
       3.200e+01, 4.300e+01, 4.200e+01, 2.300e+01, 2.800e+01, 1.900e+01,
       2.200e+01, 1.600e+01, 1.200e+01, 1.800e+01, 9.000e+00, 1.000e+01,
       1.700e+01, 5.000e+00, 2.100e+01, 1.300e+01, 8.000e+00, 1.200e+01,
       1.000e+01, 8.000e+00, 8.000e+00, 5.000e+00, 1.300e+01, 6.000e+00,
       3.000e+00, 7.000e+00, 6.000e+00, 2.000e+00, 1.000e+00, 5.000e+00,
       3.000e+00, 3.000e+00, 1.000e+00, 1.000e+00, 1.000e+00, 5.000e+00,
       0.000e+00, 1.000e+00, 3.000e+00, 0.000e+00, 1.000e+00, 1.000e+00,
       2.000e+00, 1.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00,
       0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00,
       0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00,
       0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00,
       0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00,
       0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00,
       0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00]), array([0.        , 0.00390625, 0.0078125 , 0.01171875, 0.015625  ,
       0.01953125, 0.0234375 , 0.02734375, 0.03125   , 0.03515625,
       0.0390625 , 0.04296875, 0.046875  , 0.05078125, 0.0546875 ,
       0.05859375, 0.0625    , 0.06640625, 0.0703125 , 0.07421875,
       0.078125  , 0.08203125, 0.0859375 , 0.08984375, 0.09375   ,
       0.09765625, 0.1015625 , 0.10546875, 0.109375  , 0.11328125,
       0.1171875 , 0.12109375, 0.125     , 0.12890625, 0.1328125 ,
       0.13671875, 0.140625  , 0.14453125, 0.1484375 , 0.15234375,
       0.15625   , 0.16015625, 0.1640625 , 0.16796875, 0.171875  ,
       0.17578125, 0.1796875 , 0.18359375, 0.1875    , 0.19140625,
       0.1953125 , 0.19921875, 0.203125  , 0.20703125, 0.2109375 ,
       0.21484375, 0.21875   , 0.22265625, 0.2265625 , 0.23046875,
       0.234375  , 0.23828125, 0.2421875 , 0.24609375, 0.25      ,
       0.25390625, 0.2578125 , 0.26171875, 0.265625  , 0.26953125,
       0.2734375 , 0.27734375, 0.28125   , 0.28515625, 0.2890625 ,
       0.29296875, 0.296875  , 0.30078125, 0.3046875 , 0.30859375,
       0.3125    , 0.31640625, 0.3203125 , 0.32421875, 0.328125  ,
       0.33203125, 0.3359375 , 0.33984375, 0.34375   , 0.34765625,
       0.3515625 , 0.35546875, 0.359375  , 0.36328125, 0.3671875 ,
       0.37109375, 0.375     , 0.37890625, 0.3828125 , 0.38671875,
       0.390625  , 0.39453125, 0.3984375 , 0.40234375, 0.40625   ,
       0.41015625, 0.4140625 , 0.41796875, 0.421875  , 0.42578125,
       0.4296875 , 0.43359375, 0.4375    , 0.44140625, 0.4453125 ,
       0.44921875, 0.453125  , 0.45703125, 0.4609375 , 0.46484375,
       0.46875   , 0.47265625, 0.4765625 , 0.48046875, 0.484375  ,
       0.48828125, 0.4921875 , 0.49609375, 0.5       , 0.50390625,
       0.5078125 , 0.51171875, 0.515625  , 0.51953125, 0.5234375 ,
       0.52734375, 0.53125   , 0.53515625, 0.5390625 , 0.54296875,
       0.546875  , 0.55078125, 0.5546875 , 0.55859375, 0.5625    ,
       0.56640625, 0.5703125 , 0.57421875, 0.578125  , 0.58203125,
       0.5859375 , 0.58984375, 0.59375   , 0.59765625, 0.6015625 ,
       0.60546875, 0.609375  , 0.61328125, 0.6171875 , 0.62109375,
       0.625     , 0.62890625, 0.6328125 , 0.63671875, 0.640625  ,
       0.64453125, 0.6484375 , 0.65234375, 0.65625   , 0.66015625,
       0.6640625 , 0.66796875, 0.671875  , 0.67578125, 0.6796875 ,
       0.68359375, 0.6875    , 0.69140625, 0.6953125 , 0.69921875,
       0.703125  , 0.70703125, 0.7109375 , 0.71484375, 0.71875   ,
       0.72265625, 0.7265625 , 0.73046875, 0.734375  , 0.73828125,
       0.7421875 , 0.74609375, 0.75      , 0.75390625, 0.7578125 ,
       0.76171875, 0.765625  , 0.76953125, 0.7734375 , 0.77734375,
       0.78125   , 0.78515625, 0.7890625 , 0.79296875, 0.796875  ,
       0.80078125, 0.8046875 , 0.80859375, 0.8125    , 0.81640625,
       0.8203125 , 0.82421875, 0.828125  , 0.83203125, 0.8359375 ,
       0.83984375, 0.84375   , 0.84765625, 0.8515625 , 0.85546875,
       0.859375  , 0.86328125, 0.8671875 , 0.87109375, 0.875     ,
       0.87890625, 0.8828125 , 0.88671875, 0.890625  , 0.89453125,
       0.8984375 , 0.90234375, 0.90625   , 0.91015625, 0.9140625 ,
       0.91796875, 0.921875  , 0.92578125, 0.9296875 , 0.93359375,
       0.9375    , 0.94140625, 0.9453125 , 0.94921875, 0.953125  ,
       0.95703125, 0.9609375 , 0.96484375, 0.96875   , 0.97265625,
       0.9765625 , 0.98046875, 0.984375  , 0.98828125, 0.9921875 ,
       0.99609375, 1.        ]), <BarContainer object of 256 artists>)

ほとんどの場合、画像の「興味深い」部分はピーク付近にあり、ピークの上および/または下の領域をクリッピングすることで、さらにコントラストを得ることができます。私たちのヒストグラムでは、ハイエンドにはあまり有用な情報がないように見えます (画像内の白いものはあまりありません)。上限を調整して、ヒストグラムの一部を効果的に「ズームイン」します。これを行うには、clim 引数を imshow に渡します。画像プロット オブジェクトのメソッドを呼び出してこれを行うこともでき set_clim()ますが、Jupyter Notebook を使用する場合は、プロット コマンドと同じセルで行うようにしてください。以前のセルからのプロットは変更されません。

への呼び出しで clim を指定できますplot

imgplot = plt.imshow(lum_img, clim=(0.0, 0.7))
画像

返されたオブジェクトを使用して clim を指定することもできます

fig = plt.figure()
ax = fig.add_subplot(1, 2, 1)
imgplot = plt.imshow(lum_img)
ax.set_title('Before')
plt.colorbar(ticks=[0.1, 0.3, 0.5, 0.7], orientation='horizontal')
ax = fig.add_subplot(1, 2, 2)
imgplot = plt.imshow(lum_img)
imgplot.set_clim(0.0, 0.7)
ax.set_title('After')
plt.colorbar(ticks=[0.1, 0.3, 0.5, 0.7], orientation='horizontal')
ビフォアーアフター
<matplotlib.colorbar.Colorbar object at 0x7f2cdf75fa30>

配列補間スキーム#

補間は、さまざまな数学的スキームに従って、ピクセルの「あるべき」色または値を計算します。これが発生する一般的な場所の 1 つは、画像のサイズを変更するときです。ピクセル数は変わりますが、同じ情報が必要です。ピクセルは離散しているため、スペースがありません。補間は、そのスペースを埋める方法です。これが、画像を拡大したときに画像がピクセル化されたように見えることがある理由です。元の画像と拡大した画像の差が大きいほど、効果が顕著になります。画像を縮小してみましょう。選択した少数のみを保持して、効果的にピクセルを破棄しています。これをプロットすると、そのデータは画面上のサイズまで拡大されます。古いピクセルはもう存在しないため、コンピューターはそのスペースを埋めるためにピクセルを描画する必要があります。

画像の読み込みに使用した Pillow ライブラリを使用して、画像のサイズを変更します。

from PIL import Image

img = Image.open('../../doc/_static/stinkbug.png')
img.thumbnail((64, 64))  # resizes image in-place
imgplot = plt.imshow(img)
画像

imshow()ここでは、補間引数を指定しなかったため、デフォルトの補間である双一次があります。

他にも試してみましょう。これは、補間を行わない「最も近い」です。

imgplot = plt.imshow(img, interpolation="nearest")
画像

バイキュービック:

imgplot = plt.imshow(img, interpolation="bicubic")
画像

バイキュービック補間は、写真を拡大するときによく使用されます。人々は、ピクセル化よりもぼやけたものを好む傾向があります。

スクリプトの合計実行時間: ( 0 分 8.344 秒)

Sphinx-Gallery によって生成されたギャラリー