¿Cómo aplicar una máscara con forma de disco a una matriz numpy?

Tengo una matriz como esta:

>>> np.ones((8,8)) array([[ 1., 1., 1., 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1., 1., 1., 1.]]) 

Estoy creando una máscara en forma de disco con radio 3, así:

 y,x = np.ogrid[-3: 3+1, -3: 3+1] mask = x**2+y**2 <= 3**2 

Esto da:

 >> mask array([[False, False, False, True, False, False, False], [False, True, True, True, True, True, False], [False, True, True, True, True, True, False], [ True, True, True, True, True, True, True], [False, True, True, True, True, True, False], [False, True, True, True, True, True, False], [False, False, False, True, False, False, False]], dtype=bool) 

Ahora, quiero poder aplicar esta máscara a mi matriz, utilizando cualquier elemento como punto central. Entonces, por ejemplo, con el punto central en (1,1), quiero obtener una matriz como:

 >>> new_arr array([[ True, True, True, True, 1., 1., 1., 1.], [ True, True, True, True, True, 1., 1., 1.], [ True, True, True, True, 1., 1., 1., 1.], [ True, True, True, True, 1., 1., 1., 1.], [ 1., True, 1., 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1., 1., 1., 1.]]) 

¿Hay una manera fácil de aplicar esta máscara?

Edit: no debería haber mezclado booleanos y flotadores – fue engañoso.

 >>> new_arr array([[ 255., 255., 255., 255., 1., 1., 1., 1.], [ 255., 255., 255., 255., 255., 1., 1., 1.], [ 255., 255., 255., 255., 1., 1., 1., 1.], [ 255., 255., 255., 255., 1., 1., 1., 1.], [ 1., 255., 1., 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1., 1., 1., 1.], [ 1., 1., 1., 1., 1., 1., 1., 1.]]) 

Este es más el resultado que necesito.

array [máscara] = 255

enmascarará la matriz utilizando el punto central (0 + radio, 0 + radio).

Sin embargo, me gustaría poder colocar cualquier máscara de tamaño en cualquier punto (y, x) y hacer que se recorte automáticamente para que se ajuste.

Lo haría así, donde (a, b) es el centro de tu máscara:

 import numpy as np a, b = 1, 1 n = 7 r = 3 y,x = np.ogrid[-a:na, -b:nb] mask = x*x + y*y <= r*r array = np.ones((n, n)) array[mask] = 255 

Solo quería compartir con todos una aplicación un poco más avanzada de esta técnica que tuve que enfrentar.

Mi problema fue aplicar este kernel circular para calcular la media de todos los valores que rodean cada punto en una matriz 2D. El núcleo generado puede pasarse al filtro genérico de scipy de la siguiente manera:

 import numpy as np from scipy.ndimage.filters import generic_filter as gf kernel = np.zeros((2*radius+1, 2*radius+1)) y,x = np.ogrid[-radius:radius+1, -radius:radius+1] mask = x**2 + y**2 <= radius**2 kernel[mask] = 1 circular_mean = gf(data, np.mean, footprint=kernel) 

¡Espero que esto ayude!

Podría usar la función de convolución de scipy, que tiene la ventaja de permitirle colocar cualquier máscara en particular, también conocida como kernel, en cualquier número de coordenadas dadas en su matriz, todo al mismo tiempo:

 import numpy as np from scipy.ndimage.filters import convolve 

Primero cree una matriz de coordenadas con la coordenada donde desea que la máscara (kernel) se centre marcada como 2

 background = np.ones((10,10)) background[5,5] = 2 print(background) [[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 2. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]] 

Crea tu máscara:

 y,x = np.ogrid[-3: 3+1, -3: 3+1] mask = x**2+y**2 <= 3**2 mask = 254*mask.astype(float) print(mask) [[ 0. 0. 0. 254. 0. 0. 0.] [ 0. 254. 254. 254. 254. 254. 0.] [ 0. 254. 254. 254. 254. 254. 0.] [ 254. 254. 254. 254. 254. 254. 254.] [ 0. 254. 254. 254. 254. 254. 0.] [ 0. 254. 254. 254. 254. 254. 0.] [ 0. 0. 0. 254. 0. 0. 0.]] 

Convoluciona las dos imágenes:

 b = convolve(background, mask)-sum(sum(mask))+1 print(b) [[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 255. 1. 1. 1. 1.] [ 1. 1. 1. 255. 255. 255. 255. 255. 1. 1.] [ 1. 1. 1. 255. 255. 255. 255. 255. 1. 1.] [ 1. 1. 255. 255. 255. 255. 255. 255. 255. 1.] [ 1. 1. 1. 255. 255. 255. 255. 255. 1. 1.] [ 1. 1. 1. 255. 255. 255. 255. 255. 1. 1.] [ 1. 1. 1. 1. 1. 255. 1. 1. 1. 1.] [ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]] 

Tenga en cuenta que las entradas de la función de convolución no se conmutan, es decir, convolve (a, b)! = Convolve (b, a)

Tenga en cuenta también que si su punto está cerca de un borde, el algoritmo no reproduce el núcleo en la coordenada. Para evitar esto, puede rellenar el fondo con el eje más grande de su kernel, aplicar la convolución y luego quitar el relleno.

Ahora, puede asignar cualquier núcleo a cualquier número de puntos en una matriz, pero tenga en cuenta que si dos núcleos se superponen, se agregan a la superposición. Puede umbral esto si necesita.

Para ponerlo una función conveniente:

 def cmask(index,radius,array): a,b = index nx,ny = array.shape y,x = np.ogrid[-a:nx-a,-b:ny-b] mask = x*x + y*y <= radius*radius return(sum(array[mask])) 

Devuelve la sum de píxeles dentro del radio, o devuelve (matriz [máscara] = 2) para cualquier necesidad.

¿Intentaste hacer una máscara o ceros y unos y luego usar la multiplicación de matrices por elemento? Esta es la forma canónica, más o menos.

Además, ¿estás seguro de que quieres una combinación de números y valores booleanos en una matriz numpy ? NumPy, como su nombre lo indica, funciona mejor con números.

Para obtener el mismo resultado que en tu ejemplo, puedes hacer algo como esto:

 >>> new_arr = np.array(ones, dtype=object) >>> new_arr[mask[2:, 2:]] = True >>> print new_arr array([[True, True, True, True, 1.0, 1.0, 1.0, 1.0], [True, True, True, True, True, 1.0, 1.0, 1.0], [True, True, True, True, 1.0, 1.0, 1.0, 1.0], [True, True, True, True, 1.0, 1.0, 1.0, 1.0], [1.0, True, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]], dtype=object)