Подтвердить что ты не робот

Создание очень больших изображений с использованием библиотеки изображений Python

Я пытаюсь создать очень большое изображение (25000x25000), вставив вместе много меньших изображений. При вызове Image.new() с такими большими размерами python исчерпывает память, и я получаю MemoryError.

Есть ли способ записать изображение, подобное этому, без необходимости хранить всю память в ОЗУ?

EDIT: Используя команду ImageMagick montage, возможно создание изображений произвольного размера. Похоже, что он не пытается загрузить окончательное изображение в ОЗУ (он использует очень мало памяти во время процесса), а скорее передает его на диск, что идеально.

4b9b3361

Ответ 1

Вы можете попробовать использовать GDAL. Он предоставляет привязки к Python. Здесь объединено tutorial, в котором описывается, как читать и писать изображения с использованием С++, C и Python API В зависимости от используемых GDAL операций и функций GDAL может обрабатывать очень большие изображения и обрабатывать изображения, которые слишком велики для хранения в ОЗУ.

Ответ 2

Не слишком удивите, что у вас заканчивается память; это изображение займет более 2 гигабайт в памяти и в зависимости от системы, в которой вы используете вашу ОС, возможно, не сможет выделить достаточную виртуальную память для запуска python, независимо от вашей фактической ОЗУ.

Вам определенно придется писать его постепенно. Если вы используете необработанный формат, вы, вероятно, можете сделать это для каждой строки изображений, если они имеют одинаковые размеры. Затем вы можете объединить файлы, иначе вам нужно быть более осторожными с тем, как вы кодируете данные.

Ответ 3

Это просто вопрос понимания формата двоичного файла. Сжатые форматы будут сложнее.

Предполагая, что вы хотите растровое изображение /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)

... будет поэтапно писать пример 2x2 bitmap, найденный здесь. Теперь это просто вопрос настройки заголовков нужного размера и чтения (а иногда и повторного чтения) ваших фрагментов в правильном порядке. Я попробовал его с очень большим файлом и не видел всплеск памяти python. Я предполагаю, что ОС может присоединяться к файлу, не читая всего этого.

Ответ 4

Проверьте, закончилась ли ваша система из виртуальной памяти, когда вы это делаете. Если да, попробуйте добавить больше. Таким образом, вы разгрузите всю проблему в подсистему виртуальной памяти, которая может быть быстрее.

Ответ 5

mayby ​​Вы можете опробовать привязки python OIIO, которые были созданы одним из студентов GSoC? Сам OpenImageIO может читать большие изображения с использованием небольшой памяти - но сам я не использовал его

OIIO: http://openimageio.org Как использовать привязки python: http://openimageio.org/wiki/index.php?title=Python_bindings

Существует также небольшой script, называемый "isticher", который делает то, что вы хотите (по крайней мере, я так думаю)

Ответ 6

Используйте numpy.memmap и модуль png.