2014-05-14 5 views
2
import numpy as np 

data = np.array([[0, 0, 1, 1, 2, 2], 
       [1, 0, 0, 1, 2, 2], 
       [1, 0, 1, 0, 0, 0], 
       [1, 1, 0, 0, 2, 0]]) 

Как я могу сделать следующее?Элементы расположения в матрице numpy

В 2 на 2 пластыря:

if any element is 2: put 2 
if any element is 1: put 1 
if all elements are 0: put 0 

Ожидаемый результат:

np.array([[1, 1, 2], 
      [1, 1, 2]]) 
+0

Что вы пробовали? Поскольку это стоит, похоже, вы просите кого-то написать код для вас. –

+1

Что делать, если в блоке присутствуют как '1', так и' 2'? – user2357112

+0

@ Lego Stormtroopr «Как он выглядит, это выглядит», что это значит? Извините, я не являюсь носителем английского языка. –

ответ

4

Использования extract_patches из scikit учиться вы можете написать это следующим образом (скопировать и вставить код, который может):

import numpy as np 
from sklearn.feature_extraction.image import extract_patches 

data = np.array([[0, 0, 1, 1, 2, 2], 
       [1, 0, 0, 1, 2, 2], 
       [1, 0, 1, 0, 0, 0], 
       [1, 1, 0, 0, 2, 0]]) 

patches = extract_patches(data, patch_shape=(2, 2), extraction_step=(2, 2)) 
output = patches.max(axis=-1).max(axis=-1) 

Объяснения: extract_patches дает представление о вкраплениях массива, размером patch_shape и лежащим на сетке extraction_step. Результатом является массив 4D, в котором первые две оси индексируют патч, а последние две оси индексируют пиксели внутри патча. Затем мы вычисляем максимум по двум последним осям, чтобы получить максимум за патч.

EDIT Это на самом деле очень много связано с this question

+1

Cool - '' 'extract_patches''' использует' '' numpy.lib.stride_tricks.as_strided''' - https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/feature_extraction/image .py – wwii

+0

Действительно - (и спасибо, что заметили, я гордился этим вкладом в то время;)), замечательно, что numpy делает копию, как только вы воздействуете на это представление с помощью. .reshape ((- 1,) + patch_shape). Таким образом вы удаляете извлечение патчей до уровня C вместо использования, например. цикл for. – eickenberg

2

Я не уверен, где вы получите ваш вход или куда вы должны оставить выход, но вы можете адаптировать это.

import numpy as np 

data = np.array([[0, 0, 1, 1, 2, 2], 
       [1, 0, 0, 1, 2, 2], 
       [1, 0, 1, 0, 0, 0], 
       [1, 1, 0, 0, 2, 0]]) 

def patchValue(i,j): 
    return max([data[i][j], 
       data[i][j+1], 
       data[i+1][j], 
       data[i+1][j+1]]) 

result = np.array([[0, 0, 0], 
        [0, 0, 0]]) 

for (v,i) in enumerate(range(0,4,2)): 
    for (w,j) in enumerate(range(0,6,2)): 
     result[v][w] = patchValue(i,j) 

print(result) 
+4

Использование 'max' - блестящая идея, но ваша реализация не в полной мере использует numpy. Это будет делать то же самое более numpythonic образом: 'rows, cols = data.shape; result = np.max (данные.reshape (rows // 2, 2, cols // 2, 2), axis = (1, 3)) ' – Jaime

+0

Какую версию numpy вам нужно написать' axis = (1, 3) '? Он не работает в моем «1.6.1», но это функциональность, которая мне всегда нужна. Это сделало бы мое предложение более кратким. – eickenberg

+0

@Jaime Какая разница между строками // 2 и строками/2? –

1

Вот довольно длинный один вкладыш, который опирается исключительно на изменения формы, переставляет, и принимая максимальные значения по различным осям. Это довольно быстро.

data.reshape((-1,2)).max(axis=1).reshape((data.shape[0],-1)).T.reshape((-1,2)).max(axis=1).reshape((data.shape[1]/2,data.shape[0]/2)).T 

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

+0

Это, если я не ошибаюсь, именно то, что @Jaime предлагает в своем комментарии дальше, с шагами, предпринятыми отдельно. – eickenberg

+0

Да, это так. Я пропустил его комментарий. Его версия довольно немного элегантна. – IanH

0

Если исходный массив является большим, и производительность является проблемой, петли можно сдвинуть вниз к коду NumPy C манипулируя формы и шаги исходного массива в создать окна, которые вы воздействующие на:

import numpy as np 
from numpy.lib.stride_tricks import as_strided 

data = np.array([[0, 0, 1, 1, 2, 2], 
       [1, 0, 0, 1, 2, 2], 
       [1, 0, 1, 0, 0, 0], 
       [1, 1, 0, 0, 2, 0]]) 

patch_shape = (2,2) 
data_shape = np.array(data.shape) 

# transform data to a 2x3 array of 2x2 patches/windows 

# final shape of the computation on the windows can be calculated with: 
# tuple(((data_shape-patch_shape) // patch_shape) + 1) 
final_shape = (2,3) 

# the shape of the windowed array can be calculated with: 
# final_shape + patch_shape 
newshape = (2, 3, 2, 2) 

# the strides of the windowed array can be calculated with: 
# tuple(np.array(data.strides) * patch_shape) + data.strides 
newstrides = (48, 8, 24, 4) 

# use as_strided to 'transform' the array 
patch_array = as_strided(data, shape = newshape, strides = newstrides) 

# flatten the windowed array for iteration - dim of 6x2x2 
# the number of windows is the product of the 'first' dimensions of the array 
# which can be calculated with: 
# (np.product(newshape[:-len(patch_shape)])) + (newshape[-len(patch_array):]) 
dim = (6,2,2) 

patch_array = patch_array.reshape(dim) 

# perfom computations on the windows and reshape to final dimensions 
result = [2 if np.any(patch == 2) else 
      1 if np.any(patch == 1) else 
      0 for patch in patch_array] 
result = np.array(result).reshape(final_shape) 

обобщенная 1-d функцию для создания оконного массива можно найти по адресу Efficient rolling statistics with NumPy

обобщенной функции многомерной и хорошее объяснение можно найти по адресу Efficient Overlapping Windows with Numpy

+0

Функция '' 'extract_patches''', используемая @eickenburg, также использует' '' as_strided() '' 'и является еще одним примером обобщенного n-мерного решения для * создания * окон для работы. https://github.com/scikit-learn/scikit-learn/blob/master/sklearn/feature_extraction/image.py – wwii

Смежные вопросы