Повторная выборка массива numpy, представляющего изображение

Я ищу, как переделать массив numpy, представляющий данные изображения, с новым размером, предпочтительно с выбором метода интерполяции (ближайшего, билинейного и т. Д.). Я знаю, что есть

scipy.misc.imresize 

что делает это, обертывая функцию изменения размера PIL. Единственная проблема заключается в том, что, поскольку он использует PIL, массив numpy должен соответствовать форматам изображений, предоставляя мне максимум 4 "цветных" канала.

Я хочу, чтобы иметь возможность изменять размеры произвольных изображений с любым количеством «цветных» каналов. Мне было интересно, есть ли простой способ сделать это в scipy / numpy, или если мне нужно катиться самостоятельно.

У меня есть две идеи о том, как придумать сам:

  • функция, которая запускает scipy.misc.imresize на каждом канале отдельно
  • создайте свой собственный, используя scipy.ndimage.interpolation.affine_transform

Первый, вероятно, будет медленным для больших данных, а второй, похоже, не предлагает другого метода интерполяции, кроме сплайнов.

4 Solutions collect form web for “Повторная выборка массива numpy, представляющего изображение”

На основе вашего описания вы хотите scipy.ndimage.zoom .

Билинейная интерполяция будет иметь order=1 , ближайший – order=0 , а кубика – значение по умолчанию ( order=3 ).

zoom предназначен специально для данных с фиксированной сеткой, которые вы хотите переделать в новое разрешение.

В качестве краткого примера:

 import numpy as np import scipy.ndimage x = np.arange(9).reshape(3,3) print 'Original array:' print x print 'Resampled by a factor of 2 with nearest interpolation:' print scipy.ndimage.zoom(x, 2, order=0) print 'Resampled by a factor of 2 with bilinear interpolation:' print scipy.ndimage.zoom(x, 2, order=1) print 'Resampled by a factor of 2 with cubic interpolation:' print scipy.ndimage.zoom(x, 2, order=3) 

И результат:

 Original array: [[0 1 2] [3 4 5] [6 7 8]] Resampled by a factor of 2 with nearest interpolation: [[0 0 1 1 2 2] [0 0 1 1 2 2] [3 3 4 4 5 5] [3 3 4 4 5 5] [6 6 7 7 8 8] [6 6 7 7 8 8]] Resampled by a factor of 2 with bilinear interpolation: [[0 0 1 1 2 2] [1 2 2 2 3 3] [2 3 3 4 4 4] [4 4 4 5 5 6] [5 5 6 6 6 7] [6 6 7 7 8 8]] Resampled by a factor of 2 with cubic interpolation: [[0 0 1 1 2 2] [1 1 1 2 2 3] [2 2 3 3 4 4] [4 4 5 5 6 6] [5 6 6 7 7 7] [6 6 7 7 8 8]] 

Изменить: Как отметил Мэтт С., есть несколько предостережений для масштабирования многодиапазонных изображений. Я копирую часть ниже почти дословно из одного из моих более ранних ответов :

Масштабирование также работает для 3D (и nD) массивов. Однако имейте в виду, что если вы увеличите масштаб на 2x, например, вы будете увеличивать масштаб по всем осям.

 data = np.arange(27).reshape(3,3,3) print 'Original:\n', data print 'Zoomed by 2x gives an array of shape:', ndimage.zoom(data, 2).shape 

Это дает:

 Original: [[[ 0 1 2] [ 3 4 5] [ 6 7 8]] [[ 9 10 11] [12 13 14] [15 16 17]] [[18 19 20] [21 22 23] [24 25 26]]] Zoomed by 2x gives an array of shape: (6, 6, 6) 

В случае многодиапазонных изображений вы обычно не хотите интерполировать вдоль оси «z», создавая новые полосы.

Если у вас есть что-то вроде 3-полосного RGB-изображения, которое вы хотите увеличить, вы можете сделать это, указав последовательность кортежей как коэффициент масштабирования:

 print 'Zoomed by 2x along the last two axes:' print ndimage.zoom(data, (1, 2, 2)) 

Это дает:

 Zoomed by 2x along the last two axes: [[[ 0 0 1 1 2 2] [ 1 1 1 2 2 3] [ 2 2 3 3 4 4] [ 4 4 5 5 6 6] [ 5 6 6 7 7 7] [ 6 6 7 7 8 8]] [[ 9 9 10 10 11 11] [10 10 10 11 11 12] [11 11 12 12 13 13] [13 13 14 14 15 15] [14 15 15 16 16 16] [15 15 16 16 17 17]] [[18 18 19 19 20 20] [19 19 19 20 20 21] [20 20 21 21 22 22] [22 22 23 23 24 24] [23 24 24 25 25 25] [24 24 25 25 26 26]]] 

Вы посмотрели на изображение Scikit ? Его функции transform.pyramid_* могут быть полезны для вас.

Если вы хотите переделать, то вы должны посмотреть на кулинарную книгу Скипи для перепрофилирования . В частности, congrid функция, определенная в конце, будет поддерживать перестроение или интерполяцию (эквивалентную функции в IDL с тем же именем). Это должен быть самый быстрый вариант, если вы не хотите интерполяции.

Вы также можете использовать непосредственно scipy.ndimage.map_coordinates , который будет выполнять сплайн-интерполяцию для любого вида повторной выборки (включая неструктурированные сетки). Я считаю map_coordinates медленным для больших массивов (nx, ny> 200).

Для интерполяции на структурированных сетках я обычно использую scipy.interpolate.RectBivariateSpline . Вы можете выбрать порядок сплайнов (линейный, квадратичный, кубический и т. Д.) И даже независимо для каждой оси. Пример:

  import scipy.interpolate as interp f = interp.RectBivariateSpline(x, y, im, kx=1, ky=1) new_im = f(new_x, new_y) 

В этом случае вы выполняете двухлинейную интерполяцию (kx = ky = 1) . «Ближайший» вид интерполяции не поддерживается, так как все это делает сплайновую интерполяцию по прямоугольной сетке. Это также не самый быстрый метод.

Если вы после двухлинейной или би-кубической интерполяции, то, как правило, намного быстрее сделать две интерполяции 1D:

  f = interp.interp1d(y, im, kind='linear') temp = f(new_y) f = interp.interp1d(x, temp.T, kind='linear') new_im = f(new_x).T 

Вы также можете использовать kind='nearest' , но в этом случае избавиться от поперечных массивов.

Недавно я только что нашел проблему с scipy.ndimage.interpolation.zoom, которую я представил как отчет об ошибке: https://github.com/scipy/scipy/issues/3203

В качестве альтернативы (или, по крайней мере, для меня), я обнаружил, что skimage.shreform.resize scikit-image работает правильно: http://scikit-image.org/docs/dev/api/skimage.transform.html#skimage .transform.resize

Однако он работает по-разному с интерполяцией scipy.zoom – вместо указания mutliplier вы указываете желаемую форму вывода. Это работает для 2D и 3D изображений.

Для двухмерных изображений вы можете использовать transform.rescale и указать множитель или масштаб, как и с интерполяцией.zoom.

Python - лучший язык программирования в мире.