skimage scikit learn book numpy scipy scikit-learn scikit-image

scikit - Extrae bloques o parches de NumPy Array



scikits python (3)

Tengo una matriz numpy de 2 días de la siguiente manera:

a = np.array([[1,5,9,13], [2,6,10,14], [3,7,11,15], [4,8,12,16]]

Quiero extraerlo en parches de 2 por 2 tamaños sin repetir los elementos.

La respuesta debería ser exactamente la misma. Puede ser una matriz tridimensional o una lista con el mismo orden de elementos que a continuación:

[[[1,5], [2,6]], [[3,7], [4,8]], [[9,13], [10,14]], [[11,15], [12,16]]]

¿Cómo puede hacerlo fácilmente?

En mi problema real, el tamaño de a es (36, 72). No puedo hacerlo uno por uno. Quiero una forma programática de hacerlo.


Aquí hay un numby uníptico bastante críptico para generar su matriz de 3-d, llamado result1 aquí:

In [60]: x Out[60]: array([[2, 1, 2, 2, 0, 2, 2, 1, 3, 2], [3, 1, 2, 1, 0, 1, 2, 3, 1, 0], [2, 0, 3, 1, 3, 2, 1, 0, 0, 0], [0, 1, 3, 3, 2, 0, 3, 2, 0, 3], [0, 1, 0, 3, 1, 3, 0, 0, 0, 2], [1, 1, 2, 2, 3, 2, 1, 0, 0, 3], [2, 1, 0, 3, 2, 2, 2, 2, 1, 2], [0, 3, 3, 3, 1, 0, 2, 0, 2, 1]]) In [61]: result1 = x.reshape(x.shape[0]/2, 2, x.shape[1]/2, 2).swapaxes(1, 2).reshape(-1, 2, 2)

result1 es como una matriz de 1-d de matrices de 2-d:

In [68]: result1.shape Out[68]: (20, 2, 2) In [69]: result1[0] Out[69]: array([[2, 1], [3, 1]]) In [70]: result1[1] Out[70]: array([[2, 2], [2, 1]]) In [71]: result1[5] Out[71]: array([[2, 0], [0, 1]]) In [72]: result1[-1] Out[72]: array([[1, 2], [2, 1]])

(Lo siento, no tengo tiempo en este momento para dar un desglose detallado de cómo funciona. Tal vez más tarde ...)

Aquí hay una versión menos críptica que usa una lista anidada de comprensión. En este caso, result2 es una lista de python de matrices numpy de 2 días:

In [73]: result2 = [x[2*j:2*j+2, 2*k:2*k+2] for j in range(x.shape[0]/2) for k in range(x.shape[1]/2)] In [74]: result2[5] Out[74]: array([[2, 0], [0, 1]]) In [75]: result2[-1] Out[75]: array([[1, 2], [2, 1]])


Puede lograrlo con una combinación de np.reshape y np.swapaxes como tal -

def extract_blocks(a, blocksize): M,N = a.shape b0, b1 = blocksize return a.reshape(M//b0,b0,N//b1,b1).swapaxes(1,2).reshape(-1,b0,b1)

Casos de muestra

Usemos una matriz de entrada de muestra, como ese:

In [94]: a Out[94]: array([[2, 2, 6, 1, 3, 6], [1, 0, 1, 0, 0, 3], [4, 0, 0, 4, 1, 7], [3, 2, 4, 7, 2, 4], [8, 0, 7, 3, 4, 6], [1, 5, 6, 2, 1, 8]])

Ahora, usemos algunos tamaños de bloque para probar. Usemos dos casos con tamaños de bloques de (2,3) y (3,3) .

Caso 1 :

In [95]: extract_blocks(a, (2,3)) # Blocksize : (2,3) Out[95]: array([[[2, 2, 6], [1, 0, 1]], [[1, 3, 6], [0, 0, 3]], [[4, 0, 0], [3, 2, 4]], [[4, 1, 7], [7, 2, 4]], [[8, 0, 7], [1, 5, 6]], [[3, 4, 6], [2, 1, 8]]])

Caso # 2:

In [96]: extract_blocks(a, (3,3)) # Blocksize : (3,3) Out[96]: array([[[2, 2, 6], [1, 0, 1], [4, 0, 0]], [[1, 3, 6], [0, 0, 3], [4, 1, 7]], [[3, 2, 4], [8, 0, 7], [1, 5, 6]], [[7, 2, 4], [3, 4, 6], [2, 1, 8]]])


Usando scikit-image:

import numpy as np from skimage.util import view_as_blocks a = np.array([[1,5,9,13], [2,6,10,14], [3,7,11,15], [4,8,12,16]]) print(view_as_blocks(a, (2, 2)))