在python中读取卫星图像文件时优化性能

时间:2011-09-02 05:03:20

标签: python image-processing file-io python-imaging-library satellite-image

我有一个以带交错像素(BIP)格式存储的多频段卫星图像以及一个单独的头文件。头文件提供了详细信息,例如图像中的行数和列数,以及波段数(可以超过标准3)。

图像本身就像这样存储(假设一个5波段图像):

[B1] [B2] [B3] [B4] [B5] [B1] [B2] [B3] [B4] [B5] ......等等(基本上是5个字节 - 每个频段一个 - 用于每个像素从图像的左上角开始。)

我需要将这些频段中的每一个分离为Python 3.2中的PIL图像(在Windows 7 64位上),目前我认为我正在接近这个问题。我目前的代码如下:

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库,但我不确定如何使用它们,或者它们是否会以任何方式提供帮助。

由于图像中的波段数也是可变的,我发现很难找到一种快速读取文件并将图像分离成组件波段的方法。

仅仅为了记录,我已经尝试搞乱循环中的列表方法(使用切片,不使用切片,仅使用追加,仅使用扩展等),它并不特别有所作为主要时间由于涉及的迭代次数而丢失 - (width * height * numberOfBands)。

任何建议或建议都会非常有用。感谢。

3 个答案:

答案 0 :(得分:4)

如果你能找到一个快速函数来加载一个大python列表(或numpy数组)中的二进制数据,你可以使用切片表示法对数据进行解交错:

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

这有帮助吗?

答案 1 :(得分:1)

标准PIL

要从文件加载图像,请使用图像模块中的打开功能。

>>> 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方法创建一组新图像,每个图像包含来自原始多波段图像的一个波段。合并函数采用图像的模式和元组,并将它们组合成新图像。以下示例交换RGB图像的三个波段:

分裂和合并乐队

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处理带有交错像素(BIP)格式的图像文件。

希望这有帮助。

答案 2 :(得分: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

<强> EDITED