Recorte diferentes partes de la imagen de la matriz 4D para aumentar los datos

1

Tengo la siguiente matriz de imágenes RGB por lotes (matriz 4D):

In [55]: img_arr = np.random.randint(0, 255, (10000, 32, 32, 3))

Ahora, quiero recortar solo ciertas dimensiones, digamos ( 12x12 ), desde la esquina superior izquierda a través de todos 3 canales, y preferiblemente a lo largo de la dimensión del lote (es decir axis 0 ) también, todo de una vez. Mi idea era producir una cuadrícula y simplemente cortarla. Entonces, he construido esta cuadrícula:

In [56]: grid = np.c_[np.arange(12)]+ np.r_[np.arange(12)]

In [57]: grid.shape
Out[57]: (12, 12)

Pero, cuando corto la matriz, obtengo algo inesperado:

In [58]: img_arr[:, grid, :].shape
Out[58]: (10000, 12, 12, 32, 3)

Esperaba y necesito que el resultado esté en forma (10000, 12, 12, 3) pero no se donde 32 viene de

Esto es solo un ejemplo. Idealmente, quiero hacer este recorte en 10 posiciones diferentes en la imagen a saber. arriba a la izquierda, arriba a la derecha, abajo a la izquierda, abajo a la derecha, etc.

Pero, al hacer primero el recorte superior izquierdo, el resto debe ser intuitivo.

Además, como puede ver, necesito almacenar más de 100K imágenes a lo largo de la dimensión del lote en una sola matriz 4D, por lo que sería muy bueno tener una vista al hacer recortes aleatorios, ya que será eficiente en memoria.

  • 0
    ¿Cómo planea introducir las 10 posiciones matemáticamente? ¿Quizás (x,y) del inicio (pt de la esquina superior izquierda) de cada parche? – 
  • 0
    @Divakar con cada porción de recorte de imagen original en: recorte top-left, top-right, bottom-left, bottom-right, center crop ; Luego, voltee la imagen horizontalmente y vuelva a recortar en: recorte top-left, top-right, bottom-left, bottom-right, and center crop . Aumento de datos :) – 
Mostrar mas 3 comentarios
Etiquetas de preguntas:
image-processing
numpy
multidimensional-array
computer-vision

1 respuesta

3
Mejor respuesta

Podemos usar la división para esto: podemos especificar un rango para la segunda y tercera dimensión como:

sub_img = img_arr[:, :12, :12 , :]

Entonces sub_img.shape == (10000, 12, 12, 3) . Aquí especificamos un rango de 0 a 12 (pero no necesitamos declarar explícitamente 0 ) Hacemos esto para la segunda y tercera dimensión. También es bastante declarativo: construimos un sub_img donde el primer índice toma todo ( : ), el segundo hasta el duodécimo elemento ( :12 ), etc.

Tenga en cuenta que no necesitamos especificar colas : s, también podemos escribir:

sub_img = img_arr[:, :12, :12]  # no last ":"

Rebanadas como vistas

Tenga en cuenta que aquí construimos una vista , no copiamos la matriz, solo construimos una vista. Entonces, si hacemos cambios en img_arr que están en el rango de la vista, podremos ver eso en sub_img , y viceversa. En caso de que necesite una copia, puede pasar, por ejemplo, la vista a través de array constructor:

sub_img = np.array(img_arr[:, :12, :12])  # making a copy, instead of a view

Sin embargo, usar una vista puede ser beneficioso ya que casi no usa memoria para almacenar una vista (aquí aproximadamente 144 bytes, mientras que una copia requerirá aproximadamente 34 megabytes), y además la construcción de una vista es casi instantánea (generalmente se escala con el número de dimensiones ), mientras que una copia se escalará con el número de elementos.

Número arbitrario de dimensiones usando slice objetos

En caso de que el número de dimensiones sea arbitrario, por ejemplo, también podemos pasar una tupla de slice objetos.

Por ejemplo, la primera expresión es equivalente a:

# equivalent to the first code fragment
indices = (slice(None), slice(12), slice(12))
sub_img = img_arr[indices]

Entonces, en caso de que el número de dimensiones sea arbitrario, primero podemos construir tal tupla. Una tupla que dividirá todas las dimensiones a 12 excepto la primera y la última es, por ejemplo:

# generalized with arbitrary number of dimensions
indices = (slice(None), *(slice(12) for _ in range(img_arr.ndim - 2)))
sub_img = img_arr[indices]
La respuesta fue
Fuente
  • 0
    ¡Muy agradable! Entonces, solo tengo que codificar las dimensiones y en qué ubicaciones en img_arr quiero recortar usando los índices de corte. – 
  • 0
    @ kmario23: no tiene que codificar, también puede usar identificadores como a = 12 y luego sub_img = img_arr[:, :a, :a] . Ni siquiera tiene que codificar el número de dimensiones, puede pasar una tupla con cortes. – 
Mostrar mas 1 comentario
Comunidad Progexpertos
Arriba
Menu