Tengo una matriz numpy 4-D, con la primera dimensión que representa el número de imágenes en un conjunto de datos, la segunda y la tercera son la anchura y la altura (iguales) y la cuarta la cantidad de canales (3). Por ejemplo, digamos que tengo 4 imágenes en color que son 28 * 28, por lo que mis datos de imagen se ven así:
X = np.reshape(np.arange(4*28*28*3), (4,28,28,3))
Me gustaría seleccionar un recorte aleatorio de 16 * 16 de ancho x alto de cada una de las 4 imágenes. Críticamente, quiero que el recorte sea diferente por imagen, es decir, quiero generar 4 pares aleatorios (x_offset, y_offset). Al final quiero acceder a un conjunto de formas (4, 16, 16, 3).
Si tuviera que escribir esto en un bucle for, se vería algo así:
x = np.random.randint(0,12,4) y = np.random.randint(0,12,4) for i in range(X.shape[0]): cropped_image = X[i, x[i]:x[i]+16, y[i]:y[i]+16, :] #Add cropped image to a list or something
Pero me gustaría hacerlo de la manera más eficiente posible y me pregunto si hay una manera de hacerlo con zancadas e indexación elegante. He visto las respuestas a esta pregunta, pero no puedo comprender cómo podría combinar algo como stride_tricks con puntos de inicio aleatorios para los pasos en el segundo y tercer eje (ancho y alto).
strided-based
para la extracción eficiente de parches Podemos aprovechar np.lib.stride_tricks.as_strided
scikit-image's view_as_windows
para obtener ventanas deslizantes que serían simplemente views
en la matriz de entrada y, por lo tanto, no incurrirán en una sobrecarga de memoria adicional y prácticamente gratis. Seguramente podemos usar np.lib.stride_tricks.as_strided
directamente, pero el trabajo de configuración requerido es difícil de administrar, especialmente en arreglos con dimensiones más altas. Si scikit-image
no está disponible, podemos usar directamente el source code
que funciona de forma independiente.
Explicación sobre el uso de view_as_windows
La idea con view_as_windows
es que view_as_windows
en la entrada arg window_shape
como una tupla de longitud igual a la cantidad de dimensiones en la matriz de entrada cuyas ventanas deslizantes son necesarias. Los ejes a lo largo de los cuales debemos deslizarnos se alimentan con las longitudes de ventana respectivas y el rest se alimenta con 1s
. Esto crearía una matriz de views
con singleton dims/axes
es decir, ejes con lengths=1
correspondientes a los 1s
en window_shape
arg. Por lo tanto, para esos casos podríamos querer indexar en el elemento cero correspondiente a los ejes que se alimentan como longitudes de las ventanas deslizantes para tener una versión comprimida de las ventanas deslizantes.
Por lo tanto, tendríamos una solución, como tal –
# Get sliding windows from skimage.util.shape import view_as_windows w = view_as_windows(X, (1,16,16,1))[...,0,:,:,0] # Index and get our specific windows out = w[np.arange(X.shape[0]),x,y] # If you need those in the same format as in the posted loopy code out = out.transpose(0,2,3,1)