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

在python中读取卫星图像文件时优化性能,python,image-processing,file-io,python-imaging-library,satellite-image,Python,Image Processing,File Io,Python Imaging Library,Satellite Image,我有一个多波段卫星图像存储在波段交错像素(BIP)格式以及一个单独的头文件。头文件提供了详细信息,例如图像中的行数和列数,以及条带数(可以超过标准3) 图像本身的存储方式如下(假设为5波段图像): [B1][B2][B3][B4][B5][B1][B2][B3][B4][B5]。。。以此类推(基本上是5个字节——每个频带一个字节——从图像左上角开始的每个像素) 我需要在Python3.2(在Windows7 64位上)中将这些波段作为PIL图像分开,目前我认为我处理这个问题的方法不正确。我目前的

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

图像本身的存储方式如下(假设为5波段图像):

[B1][B2][B3][B4][B5][B1][B2][B3][B4][B5]。。。以此类推(基本上是5个字节——每个频带一个字节——从图像左上角开始的每个像素)

我需要在Python3.2(在Windows7 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库,但我不确定如何使用它们,或者它们是否有任何帮助

由于图像中的带数也是可变的,我发现很难找到一种方法来快速读取文件并将图像分割为其组成带

为了记录在案,我尝试过在循环中弄乱列表方法(使用切片,不使用切片,只使用append,只使用extend等),这并没有特别大的区别,因为由于涉及的迭代次数(宽度*高度*频带数)会损失大量时间


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

标准PIL

要从文件加载图像,请使用图像模块中的open函数

>>> import Image
>>> im = Image.open("lena.ppm")
如果成功,此函数将返回图像对象。现在可以使用实例属性检查文件内容

>>> print im.format, im.size, im.mode
PPM (512, 512) RGB
format属性标识图像的源。如果未从文件中读取图像,则将其设置为“无”。size属性是一个包含宽度和高度(以像素为单位)的2元组。“模式”属性定义图像中条带的数量和名称,以及像素类型和深度。常用模式为灰度图像的“L”(亮度),真彩色图像的“RGB”,以及印前图像的“CMYK”

Python图像库还允许您处理多波段图像的各个波段,例如RGB图像。分割方法创建一组新图像,每个图像包含原始多波段图像中的一个波段。merge函数接受一个模式和一个图像元组,并将它们组合成一个新图像。以下示例交换RGB图像的三个波段:

分裂和合并频带

r, g, b = im.split()
im = Image.merge("RGB", (b, g, r))
所以我认为你应该简单地推导出模式,然后进行相应的拆分

PIL与Spectral Python(间谍Python模块)

但是,正如您在下面的评论中指出的,您并没有处理具有3个波段的正常RGB图像。因此,为了解决这个问题,SpectralPython(一个需要PIL的纯python模块)可能正是您想要的

具体而言—

spectrum.io.bipfile.bipfile处理带交错像素(BIP)格式的图像文件


希望这能有所帮助。

我怀疑重复extend并不好,最好先分配所有

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

已编辑

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

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

这有帮助吗?

是的,这对标准图像非常有效,但我不会打开标准图像-我的图像可以有3个以上的波段。现在,如果有一种方法可以让PIL打开一个没有以任何已知图像格式存储的“n”波段图像,那将很有帮助。我现在明白你的意思了。如果是这样的话,这个链接可能会对你有所帮助——但是Python 3.x中没有PIL?@Xavier,我的意思是spectralpython不可用。是的,我也尝试过这个。我浪费时间是因为迭代次数太多,这就是为什么我试图找出其他方法来读取需要较少迭代的数据。一个空循环(也就是说,只有在主体中带有pass语句的for循环)需要约33秒(使用时间模块计时)。问题是您使用的是range而不是xrange,xrange分配了一个完整的无用整数列表。我使用的是python 3.x。。range是一个迭代器。您可以使用并构建一个c模块,该模块为您提供简单的c速度。谢谢,在您指出我的代码似乎运行得太慢之后,我发现了我的错误。让调试器挂起,这减慢了代码的速度(令人惊讶的是很多)。好的,你的代码已经用了2.4秒来打开这个图像。我正在尝试一种不同的方法,看看是否能在一秒钟内完成。谢谢!太神了我完全忘记了这种切片。图像在0.1秒内打开:)