Я хочу создать файл изображения в формате png или tiff из очень большого набора данных h5py, который нельзя загрузить в память сразу. Итак, мне было интересно, есть ли в python способ записи в файл png или tiff в патчах? (Я могу загрузить набор данных h5py фрагментами в numpy.ndarray).
Я пробовал использовать библиотеку подушек и делал PIL.Image.paste, задавая координаты коробки, но для больших изображений она выходит из памяти.
В принципе, мне интересно, есть ли способ сделать что-то вроде:
for y in range(0, height, patch_size):
for x in range(0, width, patch_size):
y2 = min(y + patch_size, height)
x2 = min(x + patch_size, width)
# image_arr is an h5py dataset that cannot be loaded completely
# in memory, so load it in slices
image_file.write(image_arr[y:y2, x:x2], box=(y, x, y2, x2))
Я ищу способ сделать это без загрузки всего изображения в память. Я пробовал библиотеку подушек, но она загружает / сохраняет все данные в памяти.
Обновлено: этот вопрос не о h5py, а скорее о том, насколько чрезвычайно большие изображения (которые не могут быть загружены в память) мы можем записать в файл патчами - аналогично тому, как большие текстовые файлы могут быть созданы путем записи в него построчно.
Не могли бы вы создать кучу отдельных относительно небольших изображений в формате png / tiff и впоследствии объединить их все в одно большое?
Голосование закрыто. Возможный дубликат Читает ли h5py весь файл в память?
@Colonder - это вопрос не о h5py, а о записи больших изображений в файл патчами. Я использую наборы данных h5py для большого массива, который не умещается в памяти, но вы также можете использовать что-то еще
@martineau - их объединение потребует загрузки их данных в память. Здесь все данные не могут быть загружены в память, поэтому записываются небольшими фрагментами.
assassin: Вы объединяете размер набора данных h5py и размер изображения (изображений). Тот факт, что один из них очень большой, не означает, что изображение, созданное из него, будет таким же большим.
@martineau - Для этого вопроса предположим, что массив изображений не может быть загружен в память в несжатом виде? Цель этого вопроса - найти в python хороший способ записи больших изображений в мозаичном формате (или патч за патчем).
убийца: Что хорошего в изображении, которое слишком велико, чтобы уместиться в памяти? Тем не менее, я сомневаюсь, что вы сможете добиться этого, пытаясь собрать кучу изображений вместе в любом из этих двух сжатых форматов. Если бы вместо этого, если бы он был несжатым (или ограничивался строчно-ориентированным сжатием, например RLE), можно было бы минимизировать использование памяти при их объединении, открыв только число, необходимое в любой момент времени, которое содержало строки тех же строк финальное изображение. Это позволило бы соединить линии окончательного изображения, не считывая их все сразу в память.
Я также не вижу смысла в том, чтобы одно изображение было слишком большим, чтобы поместиться в памяти. Как вы это сделаете? Для таких вещей, как карты, на которых вы концептуально должны были бы иметь одно большое изображение, на практике они разбиваются на плитки и обслуживаются по запросу. Если ваш вопрос не относится к HDF5, то это похоже на дубликат этого: stackoverflow.com/questions/31806526/…
Насколько я понимаю, TIFF, тем не менее, не поддерживает изображения размером более 4 ГБ. Вы можете записать патчи в несколько файлов TIFF и сложить их вместе в 3D-файл TIFF. Стандарт tiff определяет определение «полосок», которые можно независимо сжимать. Я не знаю библиотеки для их написания. Насколько велики изображения, которые вы хотите написать?
Пожалуйста, обновите вопрос, указав свои требования относительно сжатия или плиток. Как уже упоминалось, tifffile.memmap можно использовать для произвольной записи в несжатые файлы BigTIFF с чередованием.






Краткий ответ на вопрос «есть ли в Python способ записи в файл png или tiff патчами?». Что ж, да - в Python все возможно, если учесть достаточно времени и навыков, чтобы это реализовать. С другой стороны, НЕТ, готового решения для этого нет - потому что это не кажется очень полезным.
Я не знаю о TIFF, и в комментарии здесь говорится, что он ограничен 4 ГБ, поэтому этот формат, вероятно, не является хорошим кандидатом. PNG не имеет практических ограничений, и может записывается кусками, поэтому теоретически это выполнимо - при условии, что хотя бы одна строка развертки полученного изображения помещается в память.
Если вы В самом деле хотите продолжить, вот информация, которая вам нужна: Файл PNG состоит из нескольких фрагментов метаданных и серии фрагментов данных изображения. Последние не зависят друг от друга, и поэтому вы можете создать большое изображение из нескольких меньших изображений (каждое из которых содержит целое количество строк, минимум одну строку), просто объединив их блоки данных изображения (IDAT) вместе и добавив необходимые фрагменты метаданных (вы можете выбрать их из первого небольшого изображения, за исключением фрагмента IHDR - он должен быть сконструирован таким образом, чтобы он содержал окончательный размер изображения).
Итак, вот как я бы это сделал, если бы мне пришлось (ПРИМЕЧАНИЕ, вам понадобится некоторое понимание типа Python bytes и методов преобразования байтовых последовательностей в типы данных Python и из них, чтобы осуществить это):
найдите, сколько строк я могу уместить в памяти, и сделайте это высотой моего «маленького фрагмента изображения». Ширина - это ширина всего окончательного изображения. назовем их width и small_height
просмотреть мой гигантский набор данных в h5py по одному фрагменту (width * small_height), преобразовать его в PNG и сохранить на диск во временном файле или, если ваша библиотека преобразования изображений это позволяет, - непосредственно в строку bytes в памяти. Затем обработайте байтовые данные следующим образом и удалите их в конце:
- на первой итерации: просматривайте данные PNG по одной записи за раз (см. спецификацию PNG: http://www.libpng.org/pub/png/spec/1.2/png-1.2-pdg.html, это в форме значения тега длины и очень легко написать код, который эффективно перемещается по записи файла за записью) , сохраните ВСЕ записи в мой целевой файл, Кроме: измените IHDR, чтобы получить окончательный размер изображения, и пропустите запись IEND.
- на всех последующих итерациях: просканируйте данные PNG и выберите только записи IDAT, запишите их в выходной файл.
добавить запись IEND в целевой файл.
Все готово - теперь у вас должен быть действительный огромный PNG. Хотя мне интересно, кто или что мог это прочитать.
Попробуйте tifffile.memmap:
from tifffile import memmap
image_file = memmap('temp.tif', shape=(height, width), dtype=image_arr.dtype,
bigtiff=True)
for y in range(0, height, patch_size):
for x in range(0, width, patch_size):
y2 = min(y + patch_size, height)
x2 = min(x + patch_size, width)
image_file[y:y2, x:x2] = image_arr[y:y2, x:x2]
image_file.flush()
Это создает несжатый файл BigTIFF с одной полосой. Плитки с отображением в память еще не реализованы. Не уверен, сколько библиотек могут обрабатывать такие файлы, но вы всегда можете напрямую читать из полосы, используя метаданные в тегах TIFF.
@gohlke bigtiff = True, похоже, не работает в последней версии.
tifffile.memmapдает вам массив numpy с отображением памяти, хранящийся в файле TIFF. Но без сжатия или плитки.