una tutorial transpuesta transponer que multiplicar multiplicacion matriz matrices español array python arrays numpy mask circle

tutorial - transponer matriz python



¿Cómo aplicar una máscara en forma de disco a una matriz numpy? (6)

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, usando 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 alguna manera fácil de aplicar esta máscara?

Editar: No debería haber mezclado booleanos y flotantes, 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 requiero.

array [máscara] = 255

enmascarará la matriz usando 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 quepa.


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

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


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:n-a, -b:n-b] mask = x*x + y*y <= r*r array = np.ones((n, n)) array[mask] = 255


Para decirlo 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 suma de píxeles dentro del radio, o regresa (matriz [máscara] = 2) para cualquier necesidad.


Para obtener el mismo resultado que en su ejemplo, puede 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)


Podría usar la función convolve de scipy, que tiene el beneficio de permitirle colocar cualquier máscara particular, también conocida como kernel, en cualquier cantidad de coordenadas dadas en su matriz, todas a la vez:

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

Primero crea una matriz de coordenadas con la coordenada de donde deseas que la máscara (kernel) se centre 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.]]

Convolve 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 convolve 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 algo 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 eliminar el relleno.

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


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

Mi problema era aplicar este kernel circular para calcular la media de todos los valores que rodean cada punto en una matriz 2D. El kernel generado se puede pasar 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!