2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Spectral Python Tutorial 導入からデータの読み込みまで

Last updated at Posted at 2021-06-24

#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_cubeview_nd以外はPython 3.3+で動作
(2): view_cubeview_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.ndarrayshape(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')

次回に続く。

2
4
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
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?