使用Python Image Library创建非常大的图像

时间:2010-01-21 12:27:31

标签: python python-imaging-library

我正在尝试通过粘贴许多较小的图像来创建一个非常大的图像(25000x25000)。在调用具有如此大尺寸的Image.new()时,python内存不足,我得到一个MemoryError。

有没有办法逐步写出这样的图像,而不是整个东西都驻留在RAM中?

编辑: 使用ImageMagick的montage命令,似乎可以创建任意大小的图像。看起来它并没有尝试将最终图像加载到RAM中(它在处理期间使用的内存很少),而是将其流式传输到磁盘,这是理想的。

6 个答案:

答案 0 :(得分:3)

您可以尝试使用GDAL库。它提供了对Python的绑定。这里结合tutorial介绍了如何使用C ++,C和Python API读写图像 根据所使用的GDAL操作和功能,GDAL可以处理非常大的图像并处理太大而无法保存在RAM中的图像。

答案 1 :(得分:2)

不要太惊讶你的内存不足;该映像将占用内存中的2gig,并且根据您使用操作系统的系统,可能无法为python分配足够的虚拟内存来运行它,无论您的实际RAM是什么。

你肯定需要逐步写出来。如果你使用原始格式,你可以在每行图像中执行此操作,如果它们都具有相同的尺寸。然后你可以连接文件,否则你必须更仔细地对数据进行编码。

答案 2 :(得分:2)

这只是理解二进制文件格式的问题。压缩格式将变得更加困难。

假设你想要一个位图/ DIB,这段代码:

#incremental_write_bmp.py
import binascii

data='''
0h -2 -42 4D -"BM" -Magic Number (unsigned integer 66, 77)
2h -4 -46 00 00 00 -70 Bytes -Size of the BMP file
6h -2 -00 00 -Unused -Application Specific
8h -2 -00 00 -Unused -Application Specific
Ah -4 -36 00 00 00 -54 bytes -The offset where the bitmap data (pixels) can be found.
Eh -4 -28 00 00 00 -40 bytes -The number of bytes in the header (from this point).
12h -4 -02 00 00 00 -2 pixels -The width of the bitmap in pixels
16h -4 -02 00 00 00 -2 pixels -The height of the bitmap in pixels
1Ah -2 -01 00 -1 plane -Number of color planes being used.
1Ch -2 -18 00 -24 bits -The number of bits/pixel.
1Eh -4 -00 00 00 00 -0 -BI_RGB, No compression used
22h -4 -10 00 00 00 -16 bytes -The size of the raw BMP data (after this header)
26h -4 -13 0B 00 00 -2,835 pixels/meter -The horizontal resolution of the image
2Ah -4 -13 0B 00 00 -2,835 pixels/meter -The vertical resolution of the image
2Eh -4 -00 00 00 00 -0 colors -Number of colors in the palette
32h -4 -00 00 00 00 -0 important colors -Means all colors are important
36h -3 -00 00 FF -0 0 255 -Red, Pixel (1,0)
39h -3 -FF FF FF -255 255 255 -White, Pixel (1,1)
3Ch -2 -00 00 -0 0 -Padding for 4 byte alignment (Could be a value other than zero)
3Eh -3 -FF 00 00 -255 0 0 -Blue, Pixel (0,0)
41h -3 -00 FF 00 -0 255 0 -Green, Pixel (0,1)
44h -2 -00 00 -0 0 -Padding for 4 byte alignment (Could be a value other than zero)
'''.strip().split('\n')

open('test.bmp','wb')
for l in data:
    b = l.split('-')[2].strip()
    d = ''.join(b.split())
    x = binascii.a2b_hex(d)
    # this re-opens the file and appends each iteration
    open('test.bmp','ab').write(x)

...将逐步编写找到的{2}找到的{2}位图。现在只需将标题设置为您想要的大小,并按正确的顺序读取(有时重新阅读)您的图块。我用一个非常大的文件尝试了它,并没有看到python的内存峰值。我假设操作系统可以附加到文件而无需阅读整个文件。

答案 3 :(得分:0)

执行此操作时,请检查系统是否用尽了虚拟内存。如果是,请尝试添加更多。这样,您可以将整个问题卸载到虚拟内存子系统上,这可能会更快。

答案 4 :(得分:0)

mayby你可以尝试一个由GSoC学生创建的OIIO python绑定吗? OpenImageIO本身可以使用小内存读取大图像 - 但我自己并没有使用它

OIIO:http://openimageio.org 如何使用python绑定:http://openimageio.org/wiki/index.php?title=Python_bindings

还有一个名为“isticher”的小脚本正在做你想要的(至少我是这么认为)

答案 5 :(得分:-1)

使用numpy.memmap和png模块。