Итерационный многомерный массив в Python

Я хочу вычислить некоторую операцию (GLCM) над изображением с помощью скользящего окна. Код для этого:

import numpy as np
from skimage.feature import greycomatrix, greycoprops

from numpy.lib.stride_tricks import as_strided

image = np.arange(36).reshape((6,6))

window = 5

result = np.zeros(image.shape)
for i in xrange(window/2,image.shape[0]-window/2):
    for j in xrange(window/2,image.shape[1]-window/2):
        sample = image[i-(window/2):i+(window/2)+1, j - (window/2):j+(window/2)+1]
        glcm = greycomatrix(sample, [1], [0], 256, symmetric=False, normed=True)
        result[i,j] = greycoprops(glcm, 'contrast')[0, 0]

Это работает, но два цикла for очень дорого. Я хочу увеличить скорость, поэтому, глядя в сеть, я попытался использовать трюк as_stride:

from numpy.lib.stride_tricks import as_strided

image = np.arange(36).reshape((6,6))

window = 5

y = as_strided(image,shape=(image.shape[0] - window + 1,\
                            image.shape[1] - window + 1,) +\
               (window,window),  strides=image.strides * 2)

Чтобы вычислить, например, GLCM для первого окна:

glcm = greycoprops(greycomatrix(y[0,0], [1], [0], 256, symmetric=False, normed=True))[0][0]

Я пытался подать заявку на все скользящее окно как:

glcm[:,:] = greycoprops(greycomatrix(y[:,:], [1], [0], 256, symmetric=False, normed=True))[0][0]

Но в этом случае y[:,:] имеет не ndim==2 как y[0,0], а ndim==4, и так далее. Я не могу найти способ разумного перебора всего подмножества с сохранением ndim == 2 (требуется для функции greycomatrix).

Изменить

Я пробовал использовать ravel и работать с 1D вектором, так что всего 1 цикл for. Это код:

a = y.ravel()
print a.shape
glcm=np.zeros(a.shape[0]/(window*window))
for i in np.arange(a.shape[0]/(window*window)):
    glcm[i] = greycoprops(greycomatrix(a[i*25:i*25+25].reshape(5,5), [1], [0], 256, symmetric=False, normed=True))[0][0]

result= glcm.reshape(y.shape[0],y.shape[1])

Увеличение времени обработки ...


person user3075816    schedule 16.01.2015    source источник


Ответы (2)


Поскольку вы забыли задать вопрос, я предполагаю, что это был

Как мне заставить это работать быстро?

Что ж, в этом случае суровая правда в том, что, насколько хорош питон, выполнение цикла python for с большим количеством нарезок всегда будет относительно дорогостоящим по сравнению с отдельными пиксельными операциями.

Поэтому, если здесь вас беспокоит скорость, вам следует реализовать некоторую функцию на языке, который позволяет вам получать привязки Python (например, C с cpython), и использовать эту функцию.

person Marcus Müller    schedule 16.01.2015

С as_strided y вам по-прежнему нужно обращаться к подмассивам индивидуально, например:

for i in range(y.shape[0]):
    for j in range(y.shape[1]):
        sample = y[i,j,...]
        print sample

или даже

for row in y:
    for sample in row:
        print sample

разве что вам нужно собрать результаты.

В подобных итерациях as_strided имеет преимущество только в том случае, если он делает доступ к подмассивам более эффективным.

Но его реальная выгода приходит, если вы можете переписать расчет GCLM для работы с 4-мерными массивами. Некоторые numpy операции предназначены для работы с 1 или 2 осями, в то время как другие просто «уходят в путь». Например, если ваш расчет просто состоит из среднего значения изображения. С y это будет просто:

np.mean(y, axes=(-2,-1))
person hpaulj    schedule 16.01.2015