2010-01-21 12 views
12

Sto cercando di creare un'immagine molto grande (25000x25000) incollando insieme molte immagini più piccole. Dopo aver chiamato Image.new() con dimensioni così grandi, python esaurisce la memoria e ottengo un MemoryError.Creazione di immagini molto grandi utilizzando Python Image Library

C'è un modo per scrivere un'immagine come questa in modo incrementale, senza che il tutto risieda nella RAM?

MODIFICA: Utilizzando il comando montage di ImageMagick, sembra possibile creare immagini di dimensioni arbitrarie. Sembra che non stia tentando di caricare l'immagine finale nella RAM (utilizza pochissima memoria durante il processo), ma piuttosto di riversarla su disco, che è l'ideale.

+0

Le immagini devono essere in modalità RGB? –

+0

Sì, sono immagini a colori. Anche il 25000x25000 è in realtà solo una piccola parte dell'immagine intera, che probabilmente sarà 175.000x325.000. Anche se le immagini erano in scala di grigi, immagino un'immagine di quelle dimensioni che non si adattano ancora alla RAM. – meatvest

+0

Di solito aiuta a rispondere a tali domande per sapere come verrà utilizzato l'output. Quale programma/sistema consumerà questi dati (e/o per quali scopi)? La risposta a ciò potrebbe indicare la strada. –

risposta

0

Controllare se il sistema esaurisce la memoria virtuale quando si esegue questa operazione. Se lo fa, prova ad aggiungerne altro. In questo modo, si scarica l'intero problema nel sottosistema di memoria virtuale, che potrebbe essere più veloce.

2

Non troppo sorprendente si sta esaurendo la memoria; quell'immagine occuperà 2gig in memoria e, a seconda del sistema che stai usando, il tuo sistema operativo potrebbe non essere in grado di allocare abbastanza memoria virtuale su python per eseguirlo, indipendentemente dalla tua RAM attuale.

Avrete sicuramente bisogno di scriverlo in modo incrementale. Se stai utilizzando un formato non elaborato, probabilmente lo puoi fare per riga di immagini, se sono tutte della stessa dimensione. Quindi potresti concatenare i file, altrimenti dovresti essere un po 'più attento con la codifica dei dati.

0

mayby ​​È possibile provare i collegamenti Python OIIO creati da uno degli studenti GSoC? OpenImageIO si può leggere grandi immagini utilizzando piccola memoria - ma non l'ho usato da solo

OIIO: http://openimageio.org Come utilizzare i binding python: http://openimageio.org/wiki/index.php?title=Python_bindings

C'è anche un piccolo script chiamato "isticher" che è facendo quello che vuoi (almeno io la penso così)

-1

Usa numpy.memmap e il modulo png.

3

Si può provare a utilizzare la libreria GDAL. Fornisce collegamenti a Python. Qui viene combinato tutorial che presenta come leggere e scrivere immagini usando le API C++, C e Python A seconda delle operazioni e delle funzioni GDAL utilizzate, GDAL può gestire immagini molto grandi e elaborare immagini troppo grandi per essere conservate nella RAM.

2

È solo una questione di comprensione del formato di file binario. I formati compressi saranno più difficili.

Dando per scontato che vogliono una bitmap/DIB, questo codice:

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

... sarà incrementale scrivere il bitmap esempio 2x2 trovato here. Ora si tratta solo di impostare le intestazioni sulla dimensione desiderata e di leggere (e talvolta rileggere) le tessere nel giusto ordine. Ho provato con un file molto grande e non ho visto picchi di memoria di Python. Presumo che il sistema operativo può aggiungere a un file senza leggere tutto.

Problemi correlati