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