2010-01-21 31 views
12

Estoy intentando crear una imagen muy grande (25000x25000) pegando juntas muchas imágenes más pequeñas. Al llamar a Image.new() con dimensiones tan grandes, Python se queda sin memoria y obtengo un MemoryError.Creación de imágenes muy grandes utilizando la biblioteca de imágenes de Python

¿Hay alguna manera de escribir una imagen como esta de forma incremental, sin tener todo el contenido residente en la memoria RAM?

EDITAR: Usando el comando montage de ImageMagick, parece posible crear imágenes de tamaño arbitrario. Parece que no está intentando cargar la imagen final en la memoria RAM (utiliza muy poca memoria durante el proceso), sino que la descarga al disco, lo que es ideal.

+0

¿Las imágenes tienen que estar en modo RGB? –

+0

Sí, son imágenes en color. Además, el 25000x25000 es en realidad solo una pequeña porción de la imagen completa, que probablemente será de 175,000x325,000. Incluso si las imágenes fueran en escala de grises, supongo que una imagen de ese tamaño todavía no cabría en la memoria RAM. – meatvest

+0

Por lo general, ayuda a responder estas preguntas para saber cómo se utilizará la salida. ¿Qué programa/sistema consumirá esta información (y/o para qué uso)? La respuesta a eso puede señalar el camino. –

Respuesta

0

Compruebe si su sistema se queda sin memoria virtual cuando hace esto. Si lo hace, intente agregar más. De esta forma, descarga todo el problema en el subsistema de memoria virtual, que puede ser más rápido.

2

No es demasiado sorprendente que se está quedando sin memoria; esa imagen tomará más de 2gig en la memoria y, dependiendo del sistema que esté utilizando, su sistema operativo podría no ser capaz de asignar suficiente memoria virtual a python para ejecutarlo, independientemente de su RAM real.

Definitivamente va a necesitar escribirlo de forma incremental. Si está utilizando un formato sin formato, probablemente podría hacer esto por fila de imágenes, si todas tienen las mismas dimensiones. Entonces podrías concatenar los archivos, de lo contrario tendrías que ser un poco más cuidadoso con la forma de codificar los datos.

0

mayby ​​¿Podría probar OIIO python bindings que fue creado por uno de los estudiantes de GSoC? OpenImageIO sí mismo puede leer grandes imágenes utilizando la memoria pequeña - pero no lo usamos por mí mismo

OIIO: http://openimageio.org Cómo utilizar enlaces Python: http://openimageio.org/wiki/index.php?title=Python_bindings

También hay un pequeño script llamado "isticher" que es haciendo lo que quieras (al menos eso creo)

-1

Usa numpy.memmap y el módulo png.

3

Puede intentar utilizar la biblioteca GDAL. Proporciona enlaces a Python. Aquí se combina tutorial que presenta cómo leer y escribir imágenes usando las API de C++, C y Python Dependiendo de las operaciones y funciones GDAL que se usen, GDAL puede manejar imágenes muy grandes y procesar imágenes que son demasiado grandes para guardarlas en la RAM.

2

Solo se trata de entender el formato de archivo binario. Los formatos comprimidos serán más difíciles.

Suponiendo que quieren un mapa de bits/DIB, este código:

#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) 

... incrementalmente escribir el mapa de bits ejemplo 2x2 encontró here. Ahora solo se trata de configurar los encabezados al tamaño que desee y de leer (y, a veces, volver a leer) sus teselas en el orden correcto. Lo intenté con un archivo muy grande y no vi el pico de memoria de Python. Supongo que el sistema operativo se puede agregar a un archivo sin leer todo.

Cuestiones relacionadas