4

個別のヘッダー ファイルと共に、バンド インターリーブ ピクセル (BIP) 形式で保存されたマルチバンド衛星画像があります。ヘッダー ファイルは、イメージの行数と列数、バンド数 (標準の 3 より多い場合もあります) などの詳細を提供します。

画像自体は次のように保存されます (5 バンドの画像を想定)。

[B1][B2][B3][B4][B5][B1][B2][B3][B4][B5] ... など (基本的に 5 バイト - 各バンドに 1 つ - 各ピクセルの開始)画像の左上隅から)。

これらの各バンドを Python 3.2 (Windows 7 64 ビット) で PIL イメージとして分離する必要がありますが、現在、問題に間違って取り組んでいると思います。私の現在のコードは次のとおりです。

def OpenBIPImage(file, width, height, numberOfBands):
    """
    Opens a raw image file in the BIP format and returns a list
    comprising each band as a separate PIL image.
    """
    bandArrays = []
    with open(file, 'rb') as imageFile:
        data = imageFile.read()
    currentPosition = 0
    for i in range(height * width):
        for j in range(numberOfBands):
            if i == 0:
                bandArrays.append(bytearray(data[currentPosition : currentPosition + 1]))
            else:
                bandArrays[j].extend(data[currentPosition : currentPosition + 1])
            currentPosition += 1
    bands = [Image.frombytes('L', (width, height), bytes(bandArray)) for bandArray in bandArrays]
    return bands

このコードは BIP ファイルを開くのに時間がかかりすぎます。これを行うためのより良い方法があるはずです。numpy および scipy ライブラリも持っていますが、それらをどのように使用できるか、またはそれらが何らかの形で役立つかどうかはわかりません。

画像内のバンド数も可変であるため、ファイルをすばやく読み取り、画像をコンポーネント バンドに分離する方法を見つけるのが難しいと感じています。

記録のために、ループ内でリストメソッドをいじってみました(スライスを使用する、スライスを使用しない、追加のみを使用する、拡張のみを使用するなど)が、主要な時間が失われるため、特に違いはありません。関連する反復回数 - (幅 * 高さ * numberOfBands)。

提案やアドバイスは本当に役に立ちます。ありがとう。

4

3 に答える 3

4

大きなpythonリスト(またはnumpy配列)にバイナリデータをロードする高速関数を見つけることができれば、スライス表記を使用してデータのインターリーブを解除できます。

band0 = biglist[::nbands]
band1 = biglist[1::nbands]
....

それは役に立ちますか?

于 2011-09-02T11:15:12.317 に答える
1

拡張の繰り返しは良くないのではないかと思います

def OpenBIPImage(file, width, height, numberOfBands):
    """
    Opens a raw image file in the BIP format and returns a list
    comprising each band as a separate PIL image.
    """
    bandArrays = []
    with open(file, 'rb') as imageFile:
        data = imageFile.read()
    currentPosition = 0
    for j in range(numberOfBands):
        bandArrays[j]= bytearray(b"\0"*(height * width)):


    for i in xrange(height * width):
        for j in xrange(numberOfBands):
                bandArrays[j][i]=data[currentPosition])
            currentPosition += 1
    bands = [Image.frombytes('L', (width, height), bytes(bandArray)) for bandArray in bandArrays]
    return bands

私の測定では、それほど遅くはありません

def x():
    height,width,numberOfBands=1401,801,6
    before = time.time()
    for i in range(height * width):
        for j in range(numberOfBands):
            pass
    print (time.time()-before)

>>> x()
0.937999963760376

編集済み

于 2011-09-02T09:50:46.057 に答える
1

標準 PIL

ファイルから画像を読み込むには、Image モジュールで関数 open を使用します。

>>> import Image
>>> im = Image.open("lena.ppm")

成功した場合、この関数は Image オブジェクトを返します。インスタンス属性を使用して、ファイルの内容を調べることができるようになりました。

>>> print im.format, im.size, im.mode
PPM (512, 512) RGB

format 属性は、画像のソースを識別します。イメージがファイルから読み取られなかった場合は、[なし] に設定されます。size 属性は、幅と高さ (ピクセル単位) を含む 2 つのタプルです。mode 属性は、画像内のバンドの数と名前、およびピクセル タイプと深さを定義します。一般的なモードは、グレースケール イメージの "L" (輝度)、トゥルー カラー イメージの "RGB"、プリプレス イメージの "CMYK" です。

Python Imaging Library を使用すると、RGB イメージなどのマルチバンド イメージの個々のバンドを操作することもできます。split メソッドは、元のマルチバンド イメージから 1 つのバンドを含む新しいイメージのセットを作成します。マージ関数は、モードと画像のタプルを取り、それらを新しい画像に結合します。次のサンプルは、RGB イメージの 3 つのバンドを交換します。

バンドの分割と結合

r, g, b = im.split()
im = Image.merge("RGB", (b, g, r))

したがって、単にモードを派生させてから、それに応じて分割する必要があると思います。

Spectral Python を使用した PIL (SPy Python モジュール)

ただし、以下のコメントで指摘したように、3 バンドの通常の RGB イメージを扱っているわけではありません。そのため、SpectralPython (PIL を必要とする純粋な python モジュール) はまさにあなたが探しているものかもしれません。

具体的には - http://spectralpython.sourceforge.net/class_func_ref.html#spectral.io.bipfile.BipFile

spectral.io.bipfile.BipFile は、Band Interleaved Pixel (BIP) 形式の画像ファイルを扱います。

お役に立てれば。

于 2011-09-02T05:42:40.780 に答える