#Spectral Python
Spectral Python(SPy)とは純度100%のpythonのモジュールで、ハイパースペクトル(HS)データの処理ができる。HSデータの読み込み、表示、計算そして分類まで一括して行える。MITライセンスのため、自由に使うことができる。本記事ではこのライブラリのチュートリアルを和訳したものを掲載する。なお本記事の翻訳に関しては許諾を得ている。
##Introduction
このユーザーガイドでは、下記の論文のデータを参照しチュートリアルを進める。またチュートリアルでは利便性のためfrom spectral import *
としているが、モジュール内ネームスペースのコンテンツをすべてインポートすることは非推奨である。データはここから。
File Name | Description |
---|---|
92AV3C.lan | ERDAS/LanフォーマットのHS画像。AVRISでの撮影で得られた145*145ピクセル、220バンドのデータ。 |
92AV3GT.GIS | 上のデータの土地利用図。 |
92AV3C.spc | 上のデータのAVIRISフォーマットのバンドカリブレーションファイル |
Landgrebe, D. Multispectral data analysis: A signal theory perspective. School of Electr. Comput. Eng., Purdue Univ., West Lafayette, IN (1998).
##Installing Spy
基本的にはPythonの組み込みのものとNumpyがあればHSデータの処理は可能である。グラフィカルな機能を使用して解析を行いたい場合には別途モジュールが必要となる。下表にそれぞれの機能の要件を示す。
Dependency | Notes |
---|---|
Python 2.6+ or 3.3+ | (1) |
Numpy | Required |
Pillow or Python Imaging Library(PIL) | Required if displaying or saving images |
wxPython | (2) |
matplotlib | Required if rendering raster displays or spectral plots |
IPython | Required for interactive, non-blocking GUI windows |
PyOpenGL | (2) |
Notes:
(1): view_cube
、view_nd
以外はPython 3.3+で動作
(2): view_cube
、view_nd
を呼び出す際に必要
pip でのインストールは下記のコマンドで。
その他の方法はここから
pip install spectral
基本的にHSデータは容量が大きいため、特定のディレクトリに保存されている。SPyでデータを開こうとするたびに絶対パスを入力しなくて済むようにSPECTRAL_DATA
という環境変数を設定できる。SPyはこの環境変数に記されているディレクトリからイメージファイルを探す。またディレクトリパスのリストは:
区切りで記載されなければならない。
##Reading HSI Data Files
通常、SPyではHSイメージファイルにアクセスし開くためにimage
関数を使用する。この関数はSpyFile
オブジェクトのインスタンスを返す。
###The SpyFile Interface
SpyFile
はHSデータを読み込むオブジェクトの基本的なクラスである。SpyFile
オブジェクトの作成時、対応するファイルからデータを読み込むインターフェースが与えられる。画像を開いたとき、返される実際のオブジェクトはSpyFile
のサブクラス(BipFile, BilFile, BsqFile)で、このサブクラスはデータの格納方法(interleaves)にそれぞれ対応している。
下記のコードではサンプル画像を開いている。
In [1]: from spectral import *
In [2]: img = open_image('92AV3C.lan')
In [3]: img.class
Out[3]: spectral.io.bilfile.BilFile
In [4]: print(img)
Data Source: '/home/thomas/spectral_data/92AV3C.lan'
# Rows: 145
# Samples: 145
# Bands: 220
Interleave: BIL
Quantization: 16 bits
Data format: int16
HS画像はワーキングディレクトリには存在しないが、SPECTRAL_DATA環境変数のディレクトリから探している。また画像のピクセルデータがlineごとにinterleaveされているため、image
関数はBilFileインスタンスを返す。(BILはデータの格納方式)
HSデータファイルはサイズが大きいため、SpyFile
オブジェクトが作られるときメタデータだけが読み込まれる。実際のイメージデータの値はSpyFile
メソッドによってリクエストされた時のみ読み込まれる。Numpyのように配列に対して添字演算子(たぶんインデックスとスライシングとか)を適用することができる。SpyFile
オブジェクトはM×N×Bの配列でMが画像の行数、Nが画像の列数、Bがバンド数にそれぞれなる。thenumberになってる。
In [5]: img.shape
Out[5]: (145, 145, 220)
In [6]: pixel = img[50,100]
In [7]: pixel.shape
Out[7]: (220,)
In [8]: band6 = img[:,:,5]
In [9]: band6.shape
Out[9]: (145, 145, 1)
画像データの各ピクセルの値は添字演算子が適用されるまで(インデクシングやスライシングされるまで)読み込まれない。またPythonではインデックスは0から始まるため、img[50, 100]
のような場合、51行、101列目のピクセルデータが読み込まれる。同様に、img[:,:,6]
では画像全体での6バンド目の情報が読み込まれる。
SpyFile
にはサブクラスのインスタンスが存在し、特定のイメージファイルを返すメソッドが実装されている。
Method | Description |
---|---|
read_band | Reads a single band into an M×N array |
read_bands | Reads multiple bands into an M×N×C array |
read_pixel | Reads a single pixel into a length B array |
read_subregion | Reads multiple bands from a rectangular sub-reagion of the image |
read_subimage | Reads specified rows, columns, and bands |
SpyFile
オブジェクトはbands
メンバーを持っており、このメンバーはイメージスペクトルバンドについての補足的な情報を持つBandInfo
オブジェクトのインスタンスである。
###Loading Entire Images
繰り返しにはなるが、画像データはSpyFile
オブジェクトによって必要となったときに呼び出され、データはキャッシュされない。添字演算子やメソッドの呼び出しごとに対応する画像データファイルが読み込まれる。これは事前に同じデータが読み込まれていたとしても関係はない。都度読み込みを行うことで、巨大な画像データに対して処理を行う際に激しいメモリの消費を防ぐ。また画像データ中の一部だけを利用する際には無駄を省くことができる(画像表示のためにRGBだけ読み込むなど)。
しかし、データ全体に対して適用するようなアルゴリズムを走らせた場合には処理に時間がかかる。さらに何度も繰り返しデータにアクセスする必要があるアルゴリズムではよりひどい。
前述のような欠点を解消するために、load
メソッドを利用しデータ全体をメモリにロードすることが望ましい。このメソッドではImageArray
オブジェクトが返されるが、SpyFile
インターフェースと同様にnumpy.ndarray
のインターフェース(インデクシングとかスライシングとか)をもつ。
In [1]: arr = img.load()
In [2]: arr.class
Out[2]: spectral.image.ImageArray
In [3]: print(arr.info())
# Rows: 145
# Samples: 145
# Bands: 220
Data format: float32
In [4]: arr.shape
Out[4]: (145, 145, 220)
SPyは主にスペクトル分野での処理用途にデザインされているため、メモリ中のspectral.ImageArray
オブジェクトはもとのデータファイルのインターリーブスに関係なく常にピクセルごとのインターリーブスをもつ。言い換えるならば、numpy.ndarray
のshape
は(numRows, numCols, numBands)
である。また配列の要素は常に32-bit floatsのデータ型である。
Note:
load
メソッドを呼び出す前に、出力されうるImageArray
オブジェクトの消費メモリ量を考慮すべきである。spectral.ImageArray
オブジェクトは32-bit 浮動小数点の要素を持つため、メモリ消費量は4*numRows*numCols*numBands
バイトと概算される。
Numpy memmap
Interface
ファイル全体を読み込んでおく方法は他にもあり、遅いもののメモリ効率のよいnumpy memmapオブジェクトを利用した方法がある。ここではSpyFileオブジェクトをopen_memmap
メソッドで開く。このmemmapオブジェクトはdate(dataの間違い?)をイメージファイルに書き込むことにも使われる。
##File Formats Supported
###ENVI Headers
ENVI*は地理空間画像情報を処理し解析するための商用ソフトウェアパッケージのひとつである。SPyはENVIヘッダーでまとめられた画像を読み込み、ENVIヘッダーでスペクトルライブラリの読み込みと書き込みができる。ENVIファイルはSPyのimage
関数で自動的に開かれるが、明示的にENVIファイルと指定して開くことも可能である。ヘッダーとデータのディレクトリが異なる場合や、データがSPyで特定できない拡張子を持つ場合、ENVIファイルと明示的に指定しデータをひらく必要がある。
*ENVI is a registered trademark of Exelis Visual Information Solutions.
In [5]: import spectral.io.envi as envi
In [6]: img = envi.open('cup95eff.int.hdr', 'cup95eff.int')
In [7]: import spectral.io.envi as envi
In [8]: lib = envi.open('spectra.hdr')
In [9]: lib.names[:5]
Out[9]:
['construction asphalt',
'construction concrete',
'red smooth-faced brick',
'weathered red brick',
'bare red brick']
See also: ファイルに画像データを書き込むための関数:
create_image
: ディスク上の割り当てられたストレージに新しい画像ファイルを作成
save_image
: ENVIヘッダーで既存の画像、またはndarrayを保存
###AVIRIS
SPyはAirborne Visible/Infrared Imaging Spectrometer (AVIRIS)**によって生成されたデータファイルをサポートしている。AVIRISファイルはopen_image
関数によって自動的に認識されるが、スペクトルバンドのカリブレーションファイルは自動的には認識されない。そのため、それぞれのファイルを明示的に開くことになるかもしれない。
In [10]: img = aviris.open('f970619t01p02_r02_sc01.a.rfl', 'f970619t01p02_r02.a.spc')
バンドカリブレーションファイルを別々に読み込むこともできる(AVIRISフォーマット中にバンドカリブレーションファイルはあるが、イメージファイルがない場合などに必要となる。)
In [11]: img = open_image('92AV3C.lan')
In [12]: img.bands = aviris.read_aviris_bands('92AV3C.spc')
**AVIRIS
###ERDAS/Lan
ERDAS/Lanファイルフォーマットはimage
関数により自動的に認識される。ファイルをLanファイルとして明示的に開く必要があるとは考えにくいが、以下のようにして開くことができる。
In [13]: import spectral.io.erdas as erdas
In [14]: img = erdas.open('92AV3C.lan')
次回に続く。