Pertanyaan Mengoptimalkan kinerja saat membaca file citra satelit dengan python


Saya memiliki citra satelit multiband yang disimpan dalam format band interleaved pixel (BIP) bersama dengan file header terpisah. File header memberikan rincian seperti jumlah baris dan kolom dalam gambar, dan jumlah band (bisa lebih dari standar 3).

Gambar itu sendiri disimpan seperti ini (asumsikan gambar 5 band):

[B1] [B2] [B3] [B4] [B5] [B1] [B2] [B3] [B4] [B5] ... dan seterusnya (pada dasarnya 5 byte - satu untuk setiap band - untuk setiap piksel dimulai dari sudut kiri atas gambar).

Saya perlu memisahkan masing-masing band-band ini sebagai gambar PIL di Python 3.2 (pada Windows 7 64 bit), dan saat ini saya pikir saya mendekati masalah dengan tidak benar. Kode saya saat ini adalah sebagai berikut:

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

Kode ini membutuhkan waktu terlalu lama untuk membuka file BIP, tentunya harus ada cara yang lebih baik untuk melakukan ini. Saya memang memiliki perpustakaan numpy dan scipy juga, tapi saya tidak yakin bagaimana saya bisa menggunakannya, atau apakah mereka akan membantu dengan cara apa pun.

Karena jumlah band dalam gambar juga bervariasi, saya merasa sulit untuk mencari cara untuk membaca file dengan cepat dan memisahkan gambar ke dalam band komponennya.

Dan hanya untuk catatan, saya telah mencoba mengotak-atik metode daftar dalam loop (menggunakan irisan, tidak menggunakan irisan, menggunakan hanya menambahkan, menggunakan hanya memperpanjang dll), itu tidak terlalu membuat perbedaan karena waktu utama hilang karena dari jumlah iterasi yang terlibat - (lebar * tinggi * numberOfBands).

Setiap saran atau saran akan sangat membantu. Terima kasih.


4
2017-09-02 05:03


asal


Jawaban:


Jika Anda dapat menemukan fungsi cepat untuk memuat data biner dalam daftar python besar (atau numpy array), Anda dapat menonaktifkan data menggunakan notasi pemotongan:

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

Apakah itu membantu?


4
2017-09-02 11:15



PIL Standar

Untuk memuat gambar dari file, gunakan fungsi terbuka di modul Gambar.

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

Jika berhasil, fungsi ini mengembalikan objek Image. Anda sekarang dapat menggunakan atribut instan untuk memeriksa isi file.

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

Atribut format mengidentifikasi sumber gambar. Jika gambar tidak dibaca dari file, itu diatur ke Tidak ada. Atribut ukuran adalah 2-tuple yang berisi lebar dan tinggi (dalam piksel). Atribut mode menentukan jumlah dan nama band dalam gambar, dan juga jenis dan kedalaman piksel. Mode umum adalah "L" (luminance) untuk gambar grayscale, "RGB" untuk gambar warna yang benar, dan "CMYK" untuk gambar pra-tekan.

Perpustakaan Pencitraan Python juga memungkinkan Anda untuk bekerja dengan pita individual dari gambar multi-band, seperti gambar RGB. Metode split menciptakan satu set gambar baru, masing-masing berisi satu band dari gambar multi-band asli. Fungsi gabungan mengambil mode dan tupel gambar, dan menggabungkannya menjadi gambar baru. Contoh berikut ini menukar tiga pita gambar RGB:

Memisahkan dan menggabungkan band

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

Jadi saya pikir Anda hanya harus menurunkan mode dan kemudian membaginya dengan tepat.

PIL dengan Spectral Python (modul python SPy)

Namun, seperti yang Anda tunjukkan dalam komentar Anda di bawah, Anda tidak berurusan dengan gambar RGB normal dengan 3 band. Jadi untuk menghadapi itu, SpectralPython (modul python murni yang membutuhkan PIL) mungkin hanya menjadi apa yang Anda cari.

Khususnya - http://spectralpython.sourceforge.net/class_func_ref.html#spectral.io.bipfile.BipFile

spectral.io.bipfile.BipFile berurusan dengan file Gambar dengan format Band Interleaved Pixel (BIP).

Semoga ini membantu.


1
2017-09-02 05:42



Saya menduga bahwa pengulangan memperpanjang tidak baik lebih baik mengalokasikan semuanya terlebih dahulu

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

pengukuran saya tidak menunjukkan nsuch yang melambat

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

DIEDIT


1
2017-09-02 09:50