pyvips позволяет эффективно рассчитывать сложные вещи на больших изображениях и использовать очень мало памяти .Это LGPL, работает на Linux, MacOS и Windows, и работает на всех версиях Python.У большинства linux это есть в менеджере пакетов.
Когда вы выполняете операцию, подобную a + b
в pyvips, она фактически не выполняет никакой обработки, она просто добавляет еще один узел в график операций обработки изображения.Когда вы, наконец, записываете результат где-то, весь график оценивается, и он передает изображение через вашу систему в виде набора небольших частей и параллельно.
Поскольку промежуточные изображения на самом деле не существуют, вам нужен только небольшой объем памяти, и поскольку он параллелен, он быстрый.
Например, вы можете выполнить расчет sdev следующим образом:
import sys
import pyvips
# load the input image ... the access hint means we will only make a single
# top-to-bottom pass over image, and it can therefore be streamed
image = pyvips.Image.new_from_file(sys.argv[1], access='sequential')
# our convolution ... total pixels in an M x M window
# it's a simple box filter, so we can use a seperable convolution
# (two 1D filters at 90 degrees)
window_size = 25
size = window_size * window_size
sum_mask = pyvips.Image.new_from_array([1] * window_size)
# standard deviation ... sum and sum of squares
s = image.convsep(sum_mask)
s2 = (image * image).convsep(sum_mask)
sdev = ((s2 - (s * s / size)).abs() / (size - 1)) ** 0.5
# find all zero input pixels ... these become -9999 in the output
sdev = (image == 0).ifthenelse(-9999, sdev)
# find all pixels where more than half of the window is zero ... these become
# -1 in the output
# pyvips uses 255 for TRUE and 0 for FALSE
more_than_half_zero = (image == 0).convsep(sum_mask) > 255 * size / 2
sdev = more_than_half_zero.ifthenelse(-1, sdev)
sdev.write_to_file(sys.argv[2])
Я могу запустить его так:
$ vipsheader x.jpg
x.jpg: 10000x10000 uchar, 1 band, b-w, jpegload
$ /usr/bin/time -f %M:%e python3 sdev.py x.jpg x.pfm
81432:4.11
Чтобы сделать PFM размером 10 000 x 10 000 пикселей (простой формат, который может хранить значения с плавающей точкой) из 10 000 x 10 000 пикселейИзображение jpg, где каждый пиксель в PFM - это sdev соответствующего окна 25 x 25, плюс ваши правила для нулей.На этом рабочем столе требуется 4 секунды и максимум 81 МБ памяти.
Я могу немного уменьшить использование памяти, используя только один поток, но, конечно, он намного медленнее:
$ VIPS_CONCURRENCY=1 /usr/bin/time -f %M:%e python3 sdev.py x.jpg x.pfm
54128:16.92
Сейчас только 54 МБ памяти, но 17 секунд времени.
Вы также можете читать и записывать изображения в массивы и из них, см. Главу в документации .